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
31using namespace KITHand;
32
33namespace armarx
34{
37 {
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);
45 "MAC-Address of the hand to connect to.");
47 "AutomaticReconnectActive",
48 false,
49 "Whether the hand unit should try to reconnect after the connection is lost.");
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
213 NameValueMap
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
244
245 void
247 {
248 if (state == State::DeviceLost)
249 {
250 getArmarXManager()->asyncShutdown();
251 }
252 }
253
254 RemoteGui::WidgetPtr
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
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition Component.cpp:90
Property< PropertyType > getProperty(const std::string &name)
HandUnitPropertyDefinitions(std::string prefix)
Definition HandUnit.h:45
SingleTypeVariantListPtr shapeNames
List containing the names of all valid shapes.
Definition HandUnit.h:169
KITHandUnitPropertyDefinitions(std::string prefix)
void addShapeName(const std::string &name)
void onInitHandUnit() override
void setShape(const std::string &shapeName, const Ice::Current &=Ice::emptyCurrent) override
void onExitHandUnit() override
void connectionStateChangedCallback(const KITHand::State state)
RemoteGui::WidgetPtr buildGui()
virtual armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
void addShape(const std::string &name, const std::map< std::string, float > &shape)
void onStartHandUnit() override
void setJointAngles(const NameValueMap &targetJointAngles, const Ice::Current &=Ice::emptyCurrent) override
void processGui(RemoteGui::TabProxy &prx)
NameValueMap getCurrentJointValues(const Ice::Current &=Ice::emptyCurrent) override
virtual std::string getDefaultName() const override
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
ArmarXManagerPtr getArmarXManager() const
Returns the ArmarX manager used to add and remove components.
std::string prefix
Prefix of the properties such as namespace, domain, component name, etc.
PropertyDefinition< PropertyType > & defineOptionalProperty(const std::string &name, PropertyType defaultValue, const std::string &description="", PropertyDefinitionBase::PropertyConstness constness=PropertyDefinitionBase::eConstant)
PropertyDefinition< PropertyType > & defineRequiredProperty(const std::string &name, const std::string &description="", PropertyDefinitionBase::PropertyConstness constness=PropertyDefinitionBase::eConstant)
bool getButtonClicked(std::string const &name)
ValueProxy< T > getValue(std::string const &name)
Class that offers the main functionality needed to create a statechart.
Definition State.h:54
The Variant class is described here: Variants.
Definition Variant.h:224
void setString(const std::string &s, const Ice::Current &c=Ice::emptyCurrent) override
Sets the Variant's value to s.
Definition Variant.cpp:428
#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...
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
Definition Logging.h:190
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
detail::CheckBoxBuilder makeCheckBox(std::string const &name)
Definition BoolWidgets.h:27
detail::FloatSpinBoxBuilder makeFloatSpinBox(std::string const &name)
detail::SimpleGridLayoutBuilder makeSimpleGridLayout(std::string const &name="")
detail::ButtonBuilder makeButton(std::string const &name)
detail::LineEditBuilder makeLineEdit(std::string const &name)
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
std::vector< T > max(const std::vector< T > &v1, const std::vector< T > &v2)
std::vector< T > min(const std::vector< T > &v1, const std::vector< T > &v2)
SimpleGridLayoutBuilder & addTextLabel(std::string const &text, int colspan)
SimpleGridLayoutBuilder & addChild(WidgetPtr const &child, int colspan)