KITHandUnit.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * ArmarX is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * ArmarX is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * @package RobotAPI::ArmarXObjects::KITHandUnit
17  * @author Stefan Reither ( stefan dot reither at kit dot edu )
18  * @date 2019
19  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 
23 #include "KITHandUnit.h"
24 
25 #include <algorithm>
26 
28 
30 
31 using namespace KITHand;
32 
33 namespace armarx
34 {
35  KITHandUnitPropertyDefinitions::KITHandUnitPropertyDefinitions(std::string prefix) :
37  {
38  defineOptionalProperty<KITHandCommunicationDriver::ScanMode>(
39  "ConnectionType",
40  KITHandCommunicationDriver::ScanMode::Bluetooth,
41  "Type of the connection to the hand, either Bluetooth or Serial")
42  .map("Bluetooth", KITHandCommunicationDriver::ScanMode::Bluetooth)
43  .map("Serial", KITHandCommunicationDriver::ScanMode::Serial);
44  defineRequiredProperty<std::string>("MAC-Address",
45  "MAC-Address of the hand to connect to.");
46  defineOptionalProperty<bool>(
47  "AutomaticReconnectActive",
48  false,
49  "Whether the hand unit should try to reconnect after the connection is lost.");
50  defineOptionalProperty<bool>(
51  "ScanUntilHandFound",
52  true,
53  "Wheather to keep scanning until the hand with the given MAC-Address is found.");
54  defineOptionalProperty<int>("ScanTimeout", 5, "Timeout for scanning repeatedly.");
55  }
56 
57  std::string
59  {
60  return "KITHandUnit";
61  }
62 
63  void
65  {
66  //addShapeName("Open"); //is added by something else already
67  addShapeName("Close");
68  addShapeName("G0");
69  addShapeName("G1");
70  addShapeName("G2");
71  addShapeName("G3");
72  addShapeName("G4");
73  addShapeName("G5");
74  addShapeName("G6");
75  addShapeName("G7");
76  addShapeName("G8");
77 
78  _driver = std::make_unique<KITHandCommunicationDriver>();
79  _driver->registerConnectionStateChangedCallback(
80  std::bind(&KITHandUnit::connectionStateChangedCallback, this, std::placeholders::_1));
81  }
82 
83  void
85  {
86  std::string macAddress = getProperty<std::string>("MAC-Address");
87  KITHandCommunicationDriver::ScanMode mode =
88  getProperty<KITHandCommunicationDriver::ScanMode>("ConnectionType").getValue();
89  bool found = false;
90  auto start = std::chrono::system_clock::now();
91  do
92  {
93  std::vector<HandDevice> devices = _driver->scanForDevices(mode);
94  for (HandDevice& d : devices)
95  {
96  if (mode == KITHandCommunicationDriver::ScanMode::Bluetooth)
97  {
98  ARMARX_INFO << "Found device with MAC-Address: " << d.macAdress;
99  }
100  else if (mode == KITHandCommunicationDriver::ScanMode::Serial)
101  {
102  ARMARX_INFO << "Found device at serial port: " << d.serialDeviceFile;
103  }
104  else
105  {
106  ARMARX_INFO << "Found hand"; //TODO
107  }
108  if (d.macAdress == macAddress ||
109  (mode == KITHandCommunicationDriver::ScanMode::Serial))
110  {
111  d.hardwareTarget = mode == KITHandCommunicationDriver::ScanMode::Bluetooth
112  ? KITHand::HardwareTarget::Bluetooth
113  : KITHand::HardwareTarget::Serial;
114  _driver->connect(d);
115  while (!_driver->connected())
116  {
117  std::this_thread::sleep_for(std::chrono::milliseconds(100));
118  }
119  found = true;
120 
121  //gui
123  buildGui(), [this](RemoteGui::TabProxy& prx) { processGui(prx); });
124  return;
125  }
126  }
127  } while (getProperty<bool>("ScanUntilHandFound").getValue() && !found &&
128  std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now() -
129  start)
130  .count() < getProperty<int>("ScanTimeout").getValue());
131 
132  if (mode == KITHandCommunicationDriver::ScanMode::Bluetooth)
133  {
134  ARMARX_WARNING << "Could not find hand with the given MAC-Address: " << macAddress
135  << " Shutting down this KITHandUnit.";
136  }
137  else
138  {
140  << "Could not find hand ove serial ports. Shutting down this KITHHandUnit";
141  }
142  getArmarXManager()->asyncShutdown();
143  }
144 
145  void
147  {
148  ARMARX_IMPORTANT << "Calling driver disconnect";
149  _driver->disconnect();
150  _driver.reset();
151  }
152 
153  void
154  KITHandUnit::setShape(const std::string& shapeName, const Ice::Current&)
155  {
156  if (std::regex_match(shapeName, std::regex{"[gG](0|[1-9][0-9]*)"}) &&
157  _driver->getCurrentConnectedDevice()->abilities.receivesAdditionalGraspCommands)
158  {
159  _driver->sendGrasp(std::stoul(shapeName.substr(1)));
160  }
161  else if (shapeName == "Open")
162  {
163  _driver->sendGrasp(0);
164  }
165  else if (shapeName == "Close")
166  {
167  _driver->sendGrasp(1);
168  }
169  else if (!_shapes.count(shapeName))
170  {
171  ARMARX_WARNING << "Unknown shape name '" << shapeName << "'\nKnown shapes: " << _shapes;
172  }
173  else
174  {
175  setJointAngles(_shapes.at(shapeName));
176  }
177  }
178 
179  void
180  KITHandUnit::setJointAngles(const NameValueMap& targetJointAngles, const Ice::Current&)
181  {
182  ARMARX_CHECK_NOT_NULL(_driver);
183 
184  for (const std::pair<std::string, float>& pair : targetJointAngles)
185  {
186  if (pair.first == "Fingers")
187  {
188  const std::uint64_t pos =
189  std::clamp(static_cast<std::uint64_t>(pair.second *
190  KITHand::ControlOptions::maxPosFingers),
191  static_cast<std::uint64_t>(0),
192  KITHand::ControlOptions::maxPosFingers);
193  ARMARX_DEBUG << deactivateSpam(1, std::to_string(pos)) << "set fingers " << pos;
194  _driver->sendFingersPosition(pos);
195  }
196  else if (pair.first == "Thumb")
197  {
198  const std::uint64_t pos = std::clamp(
199  static_cast<std::uint64_t>(pair.second * KITHand::ControlOptions::maxPosThumb),
200  static_cast<std::uint64_t>(0),
201  KITHand::ControlOptions::maxPosThumb);
202  ARMARX_DEBUG << deactivateSpam(1, std::to_string(pos)) << "set thumb " << pos;
203  _driver->sendThumbPosition(pos);
204  }
205  else
206  {
207  ARMARX_WARNING << "Invalid HandJointName '" << pair.first << "', ignoring.";
208  }
209  _driver->waitForCommunicationMedium();
210  }
211  }
212 
215  {
216  NameValueMap jointValues;
217  jointValues["Fingers"] =
218  _driver->getFingersPos() * 1.f / KITHand::ControlOptions::maxPosFingers;
219  jointValues["Thumb"] = _driver->getThumbPos() * 1.f / KITHand::ControlOptions::maxPosThumb;
220  return jointValues;
221  }
222 
223  void
224  KITHandUnit::addShape(const std::string& name, const std::map<std::string, float>& shape)
225  {
226  _shapes[name] = shape;
227  addShapeName(name);
228  }
229 
230  void
231  KITHandUnit::addShapeName(const std::string& name)
232  {
233  Variant currentPreshape;
234  currentPreshape.setString(name);
235  shapeNames->addVariant(currentPreshape);
236  }
237 
240  {
243  }
244 
245  void
247  {
248  if (state == State::DeviceLost)
249  {
250  getArmarXManager()->asyncShutdown();
251  }
252  }
253 
256  {
258  .cols(3)
259  .addTextLabel("Fingers")
260  .addChild(RemoteGui::makeFloatSpinBox("Fingers").min(0).max(1).value(0))
261  .addChild(new RemoteGui::HSpacer)
262 
263  .addTextLabel("Thumb")
264  .addChild(RemoteGui::makeFloatSpinBox("Thumb").min(0).max(1).value(0))
265  .addChild(new RemoteGui::HSpacer)
266 
267  .addChild(RemoteGui::makeCheckBox("AutoSendValues").value(false).label("Auto send"))
268  .addChild(RemoteGui::makeButton("SendValues").label("Send"))
269  .addChild(new RemoteGui::HSpacer)
270 
271  .addChild(RemoteGui::makeLineEdit("Raw").value("M2,1000,1000,100000"))
272  .addChild(RemoteGui::makeButton("SendRaw").label("Send Raw"))
273  .addChild(new RemoteGui::HSpacer);
274  }
275 
276  void
278  {
279  prx.receiveUpdates();
280  if (prx.getValue<bool>("AutoSendValues").get() || prx.getButtonClicked("SendValues"))
281  {
282  const auto fingers = prx.getValue<float>("Fingers").get();
283  const auto thumb = prx.getValue<float>("Thumb").get();
284  ARMARX_INFO << "setting Fingers " << fingers << " and Thumb " << thumb;
285  setJointAngles({{"Fingers", fingers}, {"Thumb", thumb}});
286  }
287  if (prx.getButtonClicked("SendRaw") && _driver)
288  {
289  _driver->sendRaw(prx.getValue<std::string>("Raw").get());
290  }
291  }
292 } // namespace armarx
armarx::KITHandUnit::addShape
void addShape(const std::string &name, const std::map< std::string, float > &shape)
Definition: KITHandUnit.cpp:224
armarx::Variant
The Variant class is described here: Variants.
Definition: Variant.h:223
armarx::HandUnit::shapeNames
SingleTypeVariantListPtr shapeNames
List containing the names of all valid shapes.
Definition: HandUnit.h:167
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:190
armarx::KITHandUnit::processGui
void processGui(RemoteGui::TabProxy &prx)
Definition: KITHandUnit.cpp:277
armarx::RemoteGui::makeButton
detail::ButtonBuilder makeButton(std::string const &name)
Definition: IntegerWidgets.h:52
ArmarXManager.h
armarx::SensorActorUnit::start
void start(const Ice::Current &c=Ice::emptyCurrent) override
Set execution state to eStarted.
Definition: SensorActorUnit.cpp:69
ARMARX_CHECK_NOT_NULL
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
Definition: ExpressionException.h:206
WidgetBuilder.h
armarx::Variant::setString
void setString(const std::string &s, const Ice::Current &c=Ice::emptyCurrent) override
Sets the Variant's value to s.
Definition: Variant.cpp:428
armarx::ManagedIceObject::getArmarXManager
ArmarXManagerPtr getArmarXManager() const
Returns the ArmarX manager used to add and remove components.
Definition: ManagedIceObject.cpp:360
armarx::max
std::vector< T > max(const std::vector< T > &v1, const std::vector< T > &v2)
Definition: VectorHelpers.h:297
armarx::RemoteGui::makeLineEdit
detail::LineEditBuilder makeLineEdit(std::string const &name)
Definition: StringWidgets.h:55
armarx::RemoteGui::detail::SimpleGridLayoutBuilder::addChild
SimpleGridLayoutBuilder & addChild(WidgetPtr const &child, int colspan)
Definition: LayoutWidgets.h:139
armarx::KITHandUnit::connectionStateChangedCallback
void connectionStateChangedCallback(const KITHand::State state)
Definition: KITHandUnit.cpp:246
armarx::RemoteGuiComponentPluginUser::createOrUpdateRemoteGuiTab
void createOrUpdateRemoteGuiTab(Ts &&... ts)
Definition: RemoteGuiComponentPlugin.h:239
armarx::RemoteGui::makeSimpleGridLayout
detail::SimpleGridLayoutBuilder makeSimpleGridLayout(std::string const &name="")
Definition: LayoutWidgets.h:274
clamp
double clamp(double x, double a, double b)
Definition: point.hpp:136
armarx::KITHandUnitPropertyDefinitions
Definition: KITHandUnit.h:40
armarx::RemoteGui::TabProxy
Definition: WidgetProxy.h:17
armarx::KITHandUnit::setJointAngles
void setJointAngles(const NameValueMap &targetJointAngles, const Ice::Current &=Ice::emptyCurrent) override
Definition: KITHandUnit.cpp:180
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:855
armarx::RemoteGui::TabProxy::receiveUpdates
void receiveUpdates()
Definition: WidgetProxy.h:135
armarx::RemoteGui::makeCheckBox
detail::CheckBoxBuilder makeCheckBox(std::string const &name)
Definition: BoolWidgets.h:27
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:184
armarx::KITHandUnit::getCurrentJointValues
NameValueMap getCurrentJointValues(const Ice::Current &=Ice::emptyCurrent) override
Definition: KITHandUnit.cpp:214
armarx::KITHandUnit::getDefaultName
virtual std::string getDefaultName() const override
Definition: KITHandUnit.cpp:58
armarx::RemoteGui::detail::SimpleGridLayoutBuilder::addTextLabel
SimpleGridLayoutBuilder & addTextLabel(std::string const &text, int colspan)
Definition: LayoutWidgets.h:150
armarx::HandUnitPropertyDefinitions
Defines all necessary properties for armarx::HandUnit.
Definition: HandUnit.h:42
armarx::State
Definition: State.h:53
armarx::KITHandUnit::setShape
void setShape(const std::string &shapeName, const Ice::Current &=Ice::emptyCurrent) override
Definition: KITHandUnit.cpp:154
armarx::to_string
const std::string & to_string(const std::string &s)
Definition: StringHelpers.h:41
armarx::KITHandUnit::onStartHandUnit
void onStartHandUnit() override
Definition: KITHandUnit.cpp:84
armarx::WidgetDescription::WidgetPtr
::IceInternal::Handle<::armarx::WidgetDescription::Widget > WidgetPtr
Definition: NJointControllerBase.h:67
armarx::RemoteGui::TabProxy::getValue
ValueProxy< T > getValue(std::string const &name)
Definition: WidgetProxy.h:167
armarx::KITHandUnit::onExitHandUnit
void onExitHandUnit() override
Definition: KITHandUnit.cpp:146
armarx::control::njoint_controller::platform::platform_follower_controller::NameValueMap
std::map< std::string, float > NameValueMap
Definition: PlatformFollowerController.h:88
armarx::Component::getConfigIdentifier
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition: Component.cpp:79
armarx::RemoteGui::TabProxy::getButtonClicked
bool getButtonClicked(std::string const &name)
Definition: WidgetProxy.cpp:12
armarx::KITHandUnit::buildGui
RemoteGui::WidgetPtr buildGui()
Definition: KITHandUnit.cpp:255
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
IceUtil::Handle< class PropertyDefinitionContainer >
armarx::RemoteGui::detail::SimpleGridLayoutBuilder::cols
SimpleGridLayoutBuilder & cols(int n)
Definition: LayoutWidgets.h:123
armarx::min
std::vector< T > min(const std::vector< T > &v1, const std::vector< T > &v2)
Definition: VectorHelpers.h:327
KITHandUnit.h
armarx::KITHandUnit::onInitHandUnit
void onInitHandUnit() override
Definition: KITHandUnit.cpp:64
armarx::Logging::deactivateSpam
SpamFilterDataPtr deactivateSpam(float deactivationDurationSec=10.0f, const std::string &identifier="", bool deactivate=true) const
disables the logging for the current line for the given amount of seconds.
Definition: Logging.cpp:99
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
armarx::PropertyDefinitionsPtr
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
Definition: forward_declarations.h:35
armarx::KITHandUnit::createPropertyDefinitions
virtual armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Definition: KITHandUnit.cpp:239
armarx::RemoteGui::makeFloatSpinBox
detail::FloatSpinBoxBuilder makeFloatSpinBox(std::string const &name)
Definition: FloatWidgets.h:58
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27
armarx::KITHandUnit::addShapeName
void addShapeName(const std::string &name)
Definition: KITHandUnit.cpp:231