KITProstheticHandUnit.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::KITProstheticHandUnit
17 * @author Raphael Grimm ( raphael dot grimm at kit dot edu )
18 * @date 2018
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
24
25#include <algorithm>
26#include <regex>
27#include <thread>
28
30
32
33namespace armarx
34{
41
42 void
44 {
45 _driver = std::make_unique<BLEProthesisInterface>(getProperty<std::string>("MAC"));
46 //addShapeName("Open"); //is added by something else already
47 addShapeName("Close");
48 addShapeName("G0");
49 addShapeName("G1");
50 addShapeName("G2");
51 addShapeName("G3");
52 addShapeName("G4");
53 addShapeName("G5");
54 addShapeName("G6");
55 addShapeName("G7");
56 addShapeName("G8");
57
58 offeringTopic(getProperty<std::string>("DebugObserverName"));
59 if (!getProperty<std::string>("RemoteGuiName").getValue().empty())
60 {
61 usingProxy(getProperty<std::string>("RemoteGuiName"));
62 }
63 }
64
65 void
67 {
68 _debugObserver =
70 if (!getProperty<std::string>("RemoteGuiName").getValue().empty())
71 {
72 _remoteGuiPrx = getProxy<RemoteGuiInterfacePrx>(
73 getProperty<std::string>("RemoteGuiName").getValue());
74
75
77
78 auto addFinger = [&](std::string name, float min, float max, float val, int steps)
79 {
80 rootLayoutBuilder.addChild(
82 .addChild(RemoteGui::makeTextLabel(name))
83 .addChild(RemoteGui::makeTextLabel("min " + std::to_string(min)))
84 .addChild(
85 RemoteGui::makeFloatSlider(name).min(min).max(max).value(val).steps(
86 steps))
87 .addChild(RemoteGui::makeTextLabel("max " + std::to_string(max))));
88 rootLayoutBuilder.addChild(
90 .addChild(RemoteGui::makeTextLabel(name + " Pos "))
91 .addChild(RemoteGui::makeLabel(name + "_pos").value("0"))
92 .addChild(new RemoteGui::HSpacer()));
93 rootLayoutBuilder.addChild(
95 .addChild(RemoteGui::makeTextLabel(name + " PWM "))
96 .addChild(RemoteGui::makeLabel(name + "_pwm").value("0"))
97 .addChild(new RemoteGui::HSpacer()));
98 };
99
100 addFinger("Thumb", 0, 1, _lastGuiValueThumb, _driver->getMaxPosThumb());
101 addFinger("Fingers", 0, 1, _lastGuiValueFingers, _driver->getMaxPosFingers());
102
103 rootLayoutBuilder.addChild(new RemoteGui::VSpacer());
104
105 _guiTask = new SimplePeriodicTask<>(
106 [&]()
107 {
108 _guiTab.receiveUpdates();
109 _driver->getMaxPosThumb();
110 const float t = _guiTab.getValue<float>("Thumb").get();
111 const float f = _guiTab.getValue<float>("Fingers").get();
112
113 bool updateT = t != _lastGuiValueThumb;
114 bool updateF = f != _lastGuiValueFingers;
115 _lastGuiValueThumb = t;
116 _lastGuiValueFingers = f;
117
118 if (updateT && updateF)
119 {
120 setJointAngles({{"Thumb", t}, {"Fingers", f}});
121 }
122 else if (updateT)
123 {
124 setJointAngles({{"Thumb", t}});
125 }
126 else if (updateF)
127 {
128 setJointAngles({{"Fingers", f}});
129 }
130
131 _guiTab.getValue<std::string>("Thumb_pos")
132 .set(std::to_string(_driver->getThumbPos()));
133 _guiTab.getValue<std::string>("Thumb_pwm")
134 .set(std::to_string(_driver->getThumbPWM()));
135 _guiTab.getValue<std::string>("Fingers_pos")
136 .set(std::to_string(_driver->getFingerPos()));
137 _guiTab.getValue<std::string>("Fingers_pwm")
138 .set(std::to_string(_driver->getFingerPWM()));
139 _guiTab.sendUpdates();
140 },
141 10);
142
143 RemoteGui::WidgetPtr rootLayout = rootLayoutBuilder;
144
145 _remoteGuiPrx->createTab("KITProstheticHandUnit", rootLayout);
146 _guiTab = RemoteGui::TabProxy(_remoteGuiPrx, "KITProstheticHandUnit");
147
148 _guiTask->start();
149 }
150 }
151
152 void
154 {
155 _driver.reset();
156 }
157
158 void
159 KITProstheticHandUnit::setJointAngles(const NameValueMap& targetJointAngles,
160 const Ice::Current&)
161 {
162 ARMARX_CHECK_NOT_NULL(_driver);
163
164 for (const auto& pair : targetJointAngles)
165 {
166 if (pair.first == "Fingers")
167 {
168 const std::uint64_t pos = std::clamp(
169 static_cast<std::uint64_t>(pair.second * _driver->getMaxPosFingers()),
170 0ul,
171 _driver->getMaxPosFingers());
172 ARMARX_INFO << "set fingers " << pos;
173 _driver->sendFingerPWM(200, 2999, pos);
174 // fix until hw driver is fixed to handle multiple commands at the same time
175 std::this_thread::sleep_for(std::chrono::milliseconds(100));
176 }
177 else if (pair.first == "Thumb")
178 {
179 const std::uint64_t pos =
180 std::clamp(static_cast<std::uint64_t>(pair.second * _driver->getMaxPosThumb()),
181 0ul,
182 _driver->getMaxPosThumb());
183 ARMARX_INFO << "set thumb " << pos;
184 _driver->sendThumbPWM(200, 2999, pos);
185 // fix until hw driver is fixed to handle multiple commands at the same time
186 std::this_thread::sleep_for(std::chrono::milliseconds(100));
187 }
188 else
189 {
190 ARMARX_WARNING << "Invalid HandJointName '" << pair.first << "', ignoring.";
191 }
192 }
193 }
194
195 NameValueMap
197 {
198 NameValueMap jointValues;
199 jointValues["Fingers"] = _driver->getFingerPos() * 1.f / _driver->getMaxPosFingers();
200 jointValues["Thumb"] = _driver->getThumbPos() * 1.f / _driver->getMaxPosThumb();
201 return jointValues;
202 }
203
204 void
205 KITProstheticHandUnit::addShape(const std::string& name,
206 const std::map<std::string, float>& shape)
207 {
208 _shapes[name] = shape;
209 addShapeName(name);
210 }
211
212 void
213 KITProstheticHandUnit::addShapeName(const std::string& name)
214 {
215 Variant currentPreshape;
216 currentPreshape.setString(name);
217 shapeNames->addVariant(currentPreshape);
218 }
219
220 void
221 KITProstheticHandUnit::setShape(const std::string& shapeName, const Ice::Current&)
222 {
223 if (std::regex_match(shapeName, std::regex{"[gG](0|[1-9][0-9]*)"}))
224 {
225 _driver->sendGrasp(std::stoul(shapeName.substr(1)));
226 }
227 else if (shapeName == "Open")
228 {
229 _driver->sendGrasp(0);
230 }
231 else if (shapeName == "Close")
232 {
233 _driver->sendGrasp(1);
234 }
235 else if (!_shapes.count(shapeName))
236 {
237 ARMARX_WARNING << "Unknown shape name '" << shapeName << "'\nKnown shapes: " << _shapes;
238 }
239 else
240 {
241 setJointAngles(_shapes.at(shapeName));
242 }
243 }
244} // 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)
SingleTypeVariantListPtr shapeNames
List containing the names of all valid shapes.
Definition HandUnit.h:169
void addShapeName(const std::string &name)
NameValueMap getCurrentJointValues(const Ice::Current &) override
void setShape(const std::string &shapeName, const Ice::Current &c=Ice::emptyCurrent) override
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
void addShape(const std::string &name, const std::map< std::string, float > &shape)
void setJointAngles(const NameValueMap &targetJointAngles, const Ice::Current &=Ice::emptyCurrent) override
void offeringTopic(const std::string &name)
Registers a topic for retrival after initialization.
TopicProxyType getTopic(const std::string &name)
Returns a proxy of the specified topic.
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
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_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
detail::FloatSliderBuilder makeFloatSlider(std::string const &name)
detail::VBoxLayoutBuilder makeVBoxLayout(std::string const &name="")
detail::LabelBuilder makeTextLabel(std::string const &text)
detail::HBoxLayoutBuilder makeHBoxLayout(std::string const &name="")
detail::LabelBuilder makeLabel(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)
SimplePeriodicTask(Ts...) -> SimplePeriodicTask< std::function< void(void)> >
std::vector< T > min(const std::vector< T > &v1, const std::vector< T > &v2)
Derived & addChild(WidgetPtr const &child)