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
34
35namespace armarx
36{
43
44 void
46 {
47 _driver = std::make_unique<BLEProthesisInterface>(getProperty<std::string>("MAC"));
48 //addShapeName("Open"); //is added by something else already
49 addShapeName("Close");
50 addShapeName("G0");
51 addShapeName("G1");
52 addShapeName("G2");
53 addShapeName("G3");
54 addShapeName("G4");
55 addShapeName("G5");
56 addShapeName("G6");
57 addShapeName("G7");
58 addShapeName("G8");
59
60 offeringTopic(getProperty<std::string>("DebugObserverName"));
61 if (!getProperty<std::string>("RemoteGuiName").getValue().empty())
62 {
63 usingProxy(getProperty<std::string>("RemoteGuiName"));
64 }
65 }
66
67 void
69 {
70 _debugObserver =
72 if (!getProperty<std::string>("RemoteGuiName").getValue().empty())
73 {
74 _remoteGuiPrx = getProxy<RemoteGuiInterfacePrx>(
75 getProperty<std::string>("RemoteGuiName").getValue());
76
77
79
80 auto addFinger = [&](std::string name, float min, float max, float val, int steps)
81 {
82 rootLayoutBuilder.addChild(
84 .addChild(RemoteGui::makeTextLabel(name))
85 .addChild(RemoteGui::makeTextLabel("min " + std::to_string(min)))
86 .addChild(
87 RemoteGui::makeFloatSlider(name).min(min).max(max).value(val).steps(
88 steps))
89 .addChild(RemoteGui::makeTextLabel("max " + std::to_string(max))));
90 rootLayoutBuilder.addChild(
92 .addChild(RemoteGui::makeTextLabel(name + " Pos "))
93 .addChild(RemoteGui::makeLabel(name + "_pos").value("0"))
94 .addChild(new RemoteGui::HSpacer()));
95 rootLayoutBuilder.addChild(
97 .addChild(RemoteGui::makeTextLabel(name + " PWM "))
98 .addChild(RemoteGui::makeLabel(name + "_pwm").value("0"))
99 .addChild(new RemoteGui::HSpacer()));
100 };
101
102 addFinger("Thumb", 0, 1, _lastGuiValueThumb, _driver->getMaxPosThumb());
103 addFinger("Fingers", 0, 1, _lastGuiValueFingers, _driver->getMaxPosFingers());
104
105 rootLayoutBuilder.addChild(new RemoteGui::VSpacer());
106
107 _guiTask = new SimplePeriodicTask<>(
108 [&]()
109 {
110 _guiTab.receiveUpdates();
111 _driver->getMaxPosThumb();
112 const float t = _guiTab.getValue<float>("Thumb").get();
113 const float f = _guiTab.getValue<float>("Fingers").get();
114
115 bool updateT = t != _lastGuiValueThumb;
116 bool updateF = f != _lastGuiValueFingers;
117 _lastGuiValueThumb = t;
118 _lastGuiValueFingers = f;
119
120 if (updateT && updateF)
121 {
122 setJointAngles({{"Thumb", t}, {"Fingers", f}});
123 }
124 else if (updateT)
125 {
126 setJointAngles({{"Thumb", t}});
127 }
128 else if (updateF)
129 {
130 setJointAngles({{"Fingers", f}});
131 }
132
133 _guiTab.getValue<std::string>("Thumb_pos")
134 .set(std::to_string(_driver->getThumbPos()));
135 _guiTab.getValue<std::string>("Thumb_pwm")
136 .set(std::to_string(_driver->getThumbPWM()));
137 _guiTab.getValue<std::string>("Fingers_pos")
138 .set(std::to_string(_driver->getFingerPos()));
139 _guiTab.getValue<std::string>("Fingers_pwm")
140 .set(std::to_string(_driver->getFingerPWM()));
141 _guiTab.sendUpdates();
142 },
143 10);
144
145 RemoteGui::WidgetPtr rootLayout = rootLayoutBuilder;
146
147 _remoteGuiPrx->createTab("KITProstheticHandUnit", rootLayout);
148 _guiTab = RemoteGui::TabProxy(_remoteGuiPrx, "KITProstheticHandUnit");
149
150 _guiTask->start();
151 }
152 }
153
154 void
156 {
157 _driver.reset();
158 }
159
160 void
161 KITProstheticHandUnit::setJointAngles(const NameValueMap& targetJointAngles,
162 const Ice::Current&)
163 {
164 ARMARX_CHECK_NOT_NULL(_driver);
165
166 for (const auto& pair : targetJointAngles)
167 {
168 if (pair.first == "Fingers")
169 {
170 const std::uint64_t pos = std::clamp(
171 static_cast<std::uint64_t>(pair.second * _driver->getMaxPosFingers()),
172 0ul,
173 _driver->getMaxPosFingers());
174 ARMARX_INFO << "set fingers " << pos;
175 _driver->sendFingerPWM(200, 2999, pos);
176 // fix until hw driver is fixed to handle multiple commands at the same time
177 std::this_thread::sleep_for(std::chrono::milliseconds(100));
178 }
179 else if (pair.first == "Thumb")
180 {
181 const std::uint64_t pos =
182 std::clamp(static_cast<std::uint64_t>(pair.second * _driver->getMaxPosThumb()),
183 0ul,
184 _driver->getMaxPosThumb());
185 ARMARX_INFO << "set thumb " << pos;
186 _driver->sendThumbPWM(200, 2999, pos);
187 // fix until hw driver is fixed to handle multiple commands at the same time
188 std::this_thread::sleep_for(std::chrono::milliseconds(100));
189 }
190 else
191 {
192 ARMARX_WARNING << "Invalid HandJointName '" << pair.first << "', ignoring.";
193 }
194 }
195 }
196
197 NameValueMap
199 {
200 NameValueMap jointValues;
201 jointValues["Fingers"] = _driver->getFingerPos() * 1.f / _driver->getMaxPosFingers();
202 jointValues["Thumb"] = _driver->getThumbPos() * 1.f / _driver->getMaxPosThumb();
203 return jointValues;
204 }
205
206 void
207 KITProstheticHandUnit::addShape(const std::string& name,
208 const std::map<std::string, float>& shape)
209 {
210 _shapes[name] = shape;
211 addShapeName(name);
212 }
213
214 void
215 KITProstheticHandUnit::addShapeName(const std::string& name)
216 {
217 Variant currentPreshape;
218 currentPreshape.setString(name);
219 shapeNames->addVariant(currentPreshape);
220 }
221
222 void
223 KITProstheticHandUnit::setShape(const std::string& shapeName, const Ice::Current&)
224 {
225 if (std::regex_match(shapeName, std::regex{"[gG](0|[1-9][0-9]*)"}))
226 {
227 _driver->sendGrasp(std::stoul(shapeName.substr(1)));
228 }
229 else if (shapeName == "Open")
230 {
231 _driver->sendGrasp(0);
232 }
233 else if (shapeName == "Close")
234 {
235 _driver->sendGrasp(1);
236 }
237 else if (!_shapes.count(shapeName))
238 {
239 ARMARX_WARNING << "Unknown shape name '" << shapeName << "'\nKnown shapes: " << _shapes;
240 }
241 else
242 {
243 setJointAngles(_shapes.at(shapeName));
244 }
245 }
246
248} // namespace armarx
#define ARMARX_REGISTER_COMPONENT_EXECUTABLE(ComponentT, applicationName)
Definition Decoupled.h:29
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
Brief description of class KITProstheticHandUnit.
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)