IkDemo.cpp
Go to the documentation of this file.
1#include "IkDemo.h"
2
3#include <SimoxUtility/algorithm/string.h>
4#include <SimoxUtility/math/pose/invert.h>
5#include <SimoxUtility/meta/EnumNames.hpp>
6#include <VirtualRobot/IK/CompositeDiffIK/CompositeDiffIK.h>
7#include <VirtualRobot/IK/CompositeDiffIK/ManipulabilityNullspaceGradient.h>
8#include <VirtualRobot/IK/CompositeDiffIK/SoechtingNullspaceGradient.h>
9#include <VirtualRobot/Robot.h>
10#include <VirtualRobot/RobotNodeSet.h>
11#include <VirtualRobot/XML/RobotIO.h>
12
15
18
19#include "PoseGizmo.h"
20
21
22namespace viz = armarx::viz;
23
25{
26
32 const simox::meta::EnumNames<IkMethod> IkMethodNames = {
33 {IkMethod::SimpleDiffIk, "Simple Diff IK"},
34 {IkMethod::CompositeDiffIk, "Composite Diff IK"},
35 };
36
38 {
40 {
41 gizmo.box.color(simox::Color::cyan(255, 64));
42 }
43
44 virtual ~Manipulator()
45 {
46 }
47
48 virtual bool
50 {
51 bool updated = false;
52 if (interaction.layer() == gizmo.layer.data_.name)
53 {
54 updated |= gizmo.handleInteraction(interaction, stage);
55 }
56 return updated;
57 }
58
59 virtual void visualize(viz::Client& arviz) = 0;
60 virtual void runIk(IkDemo::Robot& robot) = 0;
61
63 };
64
66 {
68 {
69 std::vector<std::string> options;
70 for (IkMethod method : IkMethodNames.values())
71 {
72 options.push_back("Use " + IkMethodNames.to_name(method));
73 }
74 gizmo.box.size({75, 100, 200})
75 .enable(
76 viz::interaction().selection().transform().hideDuringTransform().contextMenu(
77 options));
78 };
79
80 void
81 visualize(viz::Client& arviz) override
82 {
83 gizmo.setLayer(arviz.layer(tcp->getName()));
84 gizmo.update();
85 }
86
87 bool
88 handle(viz::InteractionFeedback const& interaction, viz::StagedCommit* stage) override
89 {
90 bool updated = Manipulator::handle(interaction, stage);
91
92 if (interaction.layer() == gizmo.layer.data_.name)
93 {
94 switch (interaction.type())
95 {
97 {
98 int i = 0;
99 for (IkMethod method : IkMethodNames.values())
100 {
101 if (i == interaction.chosenContextMenuEntry())
102 {
103 this->method = method;
104 updated |= true;
105 ARMARX_IMPORTANT << "[" << tcp->getName() << "] Using "
106 << IkMethodNames.to_name(method);
107 break;
108 }
109 ++i;
110 }
111 }
112 break;
113 default:
114 break;
115 }
116 }
117
118 return updated;
119 }
120
121 void
122 runIk(IkDemo::Robot& robot) override
123 {
124 const Eigen::Matrix4f tcpPoseInRobotFrame =
125 simox::math::inverted_pose(robot.robot->getGlobalPose()) * gizmo.getCurrent();
126
127 switch (method)
128 {
130 {
133 ik.CalculateDiffIK(tcpPoseInRobotFrame, nodeSet, tcp);
134
135 if (result.reached)
136 {
137 gizmo.box.color(simox::Color::kit_green(64));
138
139 std::map<std::string, float> jointValues;
140 size_t i = 0;
141 for (const auto& rn : nodeSet->getAllRobotNodes())
142 {
143 jointValues[rn->getName()] = result.jointValues(i);
144 ++i;
145 }
146
147 robot.robot->setJointValues(jointValues);
148 }
149 else
150 {
151 gizmo.box.color(simox::Color::red(255, 64));
152 }
153 }
154 break;
155
157 {
158 // Code taken from: simox/VirtualRobot/examples/RobotViewer/DiffIKWidget.cpp
159
160 const float jointLimitAvoidance = 0;
161 const float kGainManipulabilityAsNullspace = 0.01;
162 const float kSoechtingAsNullspace = 0.0;
163 const int steps = 100;
164
165 VirtualRobot::CompositeDiffIK ik(nodeSet);
166 Eigen::Matrix4f pose = tcpPoseInRobotFrame;
167
168 const bool ori = true;
169 VirtualRobot::CompositeDiffIK::TargetPtr target1 = ik.addTarget(
170 tcp,
171 pose,
172 ori ? VirtualRobot::IKSolver::All : VirtualRobot::IKSolver::Position);
173
174
175 if (jointLimitAvoidance > 0)
176 {
177 VirtualRobot::CompositeDiffIK::NullspaceJointLimitAvoidancePtr nsjla(
178 new VirtualRobot::CompositeDiffIK::NullspaceJointLimitAvoidance(
179 nodeSet));
180 nsjla->kP = jointLimitAvoidance;
181 for (auto node : nodeSet->getAllRobotNodes())
182 {
183 if (node->isLimitless())
184 {
185 nsjla->setWeight(node->getName(), 0);
186 }
187 }
188 ik.addNullspaceGradient(nsjla);
189 }
190
191 VirtualRobot::NullspaceManipulabilityPtr nsman = nullptr;
192 if (kGainManipulabilityAsNullspace > 0)
193 {
194#if 0
195 std::cout << "Adding manipulability as nullspace target" << std::endl;
196 auto manipTracking = getManipulabilityTracking(nodeSet, nullptr);
197 if (!manipTracking)
198 {
199 std::cout << "Manip tracking zero!" << std::endl;
200 return;
201 }
202 Eigen::MatrixXd followManip = readFollowManipulability();
203 if (followManip.rows() != manipTracking->getTaskVars())
204 {
205 std::cout << "Wrong manipulability matrix!" << std::endl;
206 return;
207 }
208 nsman = VirtualRobot::NullspaceManipulabilityPtr(new VirtualRobot::NullspaceManipulability(manipTracking, followManip, Eigen::MatrixXd(), true));
209 nsman->kP = kGainManipulabilityAsNullspace;
210 ik.addNullspaceGradient(nsman);
211#endif
212 }
213
214 if (kSoechtingAsNullspace > 0)
215 {
216 if (robot.robot->getName() == "Armar6" and nodeSet->getName() == "RightArm")
217 {
218 std::cout << "Adding soechting nullspace" << std::endl;
219 VirtualRobot::SoechtingNullspaceGradient::ArmJoints armjoints;
220 armjoints.clavicula = robot.robot->getRobotNode("ArmR1_Cla1");
221 armjoints.shoulder1 = robot.robot->getRobotNode("ArmR2_Sho1");
222 armjoints.shoulder2 = robot.robot->getRobotNode("ArmR3_Sho2");
223 armjoints.shoulder3 = robot.robot->getRobotNode("ArmR4_Sho3");
224 armjoints.elbow = robot.robot->getRobotNode("ArmR5_Elb1");
225
226 auto gradient =
227 std::make_shared<VirtualRobot::SoechtingNullspaceGradient>(
228 target1,
229 "ArmR2_Sho1",
230 VirtualRobot::Soechting::ArmType::Right,
231 armjoints);
232
233 gradient->kP = kSoechtingAsNullspace;
234 ik.addNullspaceGradient(gradient);
235 }
236 else if (robot.robot->getName() == "Armar6" and
237 nodeSet->getName() == "LeftArm")
238 {
239 std::cout << "Adding soechting nullspace" << std::endl;
240 VirtualRobot::SoechtingNullspaceGradient::ArmJoints armjoints;
241 armjoints.clavicula = robot.robot->getRobotNode("ArmL1_Cla1");
242 armjoints.shoulder1 = robot.robot->getRobotNode("ArmL2_Sho1");
243 armjoints.shoulder2 = robot.robot->getRobotNode("ArmL3_Sho2");
244 armjoints.shoulder3 = robot.robot->getRobotNode("ArmL4_Sho3");
245 armjoints.elbow = robot.robot->getRobotNode("ArmL5_Elb1");
246
247 auto gradient =
248 std::make_shared<VirtualRobot::SoechtingNullspaceGradient>(
249 target1,
250 "ArmL2_Sho1",
251 VirtualRobot::Soechting::ArmType::Left,
252 armjoints);
253 gradient->kP = kSoechtingAsNullspace;
254 ik.addNullspaceGradient(gradient);
255 }
256 else
257 {
258 ARMARX_INFO << "Soechting currently supports only Armar6 and "
259 "RightArm/LeftArm robot node set "
260 "for first robot node set for demonstration purposes.";
261 }
262 }
263
264 {
265 VirtualRobot::CompositeDiffIK::Parameters cp;
266 cp.resetRnsValues = false;
267 cp.returnIKSteps = true;
268 cp.steps = 1;
269 VirtualRobot::CompositeDiffIK::SolveState state;
270 ik.solve(cp, state);
271
272 int i = 0;
273 while (i < steps or
274 (steps < 0 and not ik.getLastResult().reached and i < 1000))
275 {
276 ik.step(cp, state, i);
277 i++;
278 }
279
280 if (ik.getLastResult().reached)
281 {
282 gizmo.box.color(simox::Color::kit_green(64));
283 robot.robot->setJointValues(ik.getRobotNodeSet()->getJointValueMap());
284 }
285 else
286 {
287 gizmo.box.color(simox::Color::red(255, 64));
288 }
289 }
290 }
291 break;
292 }
293 }
294
295 VirtualRobot::RobotNodeSetPtr nodeSet;
296 VirtualRobot::RobotNodePtr tcp;
297
299 };
300
302 {
304 {
305 gizmo.box.size({1000, 1000, 100});
306 }
307
308 void
309 visualize(viz::Client& arviz) override
310 {
311 gizmo.setLayer(arviz.layer(root->getName()));
312 gizmo.update();
313 }
314
315 void
316 runIk(IkDemo::Robot& robot) override
317 {
318 robot.robot->setGlobalPose(gizmo.getCurrent());
319 }
320
321 VirtualRobot::RobotNodePtr root;
322 };
323
325 {
326 }
327
329 {
330 }
331
333 robotFile("armar6_rt/robotmodel/Armar6-SH/Armar6-SH.xml"),
334 robotNodeSetNamesStr(simox::alg::join({"LeftArm", "RightArm"}, "; "))
335 {
336 }
337
338 std::vector<std::string>
340 {
341 bool trim = true;
342 return simox::alg::split(robotNodeSetNamesStr, ";", trim);
343 }
344
345 void
347 {
348 defs.optional(params.robotFile,
349 "p.robotFile",
350 "The ArmarX data path to the robot XML file."
351 "\n For ARMAR-III: 'RobotAPI/robots/Armar3/ArmarIII.xml'"
352 "\n For ARMAR-6: 'armar6_rt/robotmodel/Armar6-SH/Armar6-SH.xml'");
353 defs.optional(params.robotNodeSetNamesStr,
354 "p.robotNodeSetNames",
355 "Names of robot node sets for TCPs.");
356 }
357
358 void
360 {
361 this->stage.reset();
362
363 {
365 robot.robot = VirtualRobot::RobotIO::loadRobot(params.robotFile,
366 VirtualRobot::RobotIO::eStructure);
367
368 robot.layer = remote.arviz->layer("Robot");
369
370 robot.visu.file("", robot.robot->getFilename()).joints(robot.robot->getJointValues());
371 robot.layer.add(robot.visu);
372 stage.add(robot.layer);
373 }
374
375 {
376 auto root = robot.robot->getRootNode();
377
378 std::unique_ptr<PlatformManipulator> manip = std::make_unique<PlatformManipulator>();
379
380 manip->gizmo.initial = root->getGlobalPose();
381 manip->root = root;
382
383 manipulators.emplace_back(std::move(manip));
384 }
385
386 for (const std::string& rnsName : params.robotNodeSetNames())
387 {
388 ARMARX_CHECK(robot.robot->hasRobotNodeSet(rnsName))
389 << VAROUT(rnsName) << " must exist.";
390
391 const auto& rns = robot.robot->getRobotNodeSet(rnsName);
392 const auto tcp = rns->getTCP();
393 ARMARX_CHECK_NOT_NULL(tcp) << VAROUT(rnsName) << " must have a TCP.";
394
395 std::unique_ptr<TcpManipulator> manip = std::make_unique<TcpManipulator>();
396
397 manip->gizmo.initial = tcp->getGlobalPose();
398 manip->tcp = tcp;
399 manip->nodeSet = rns;
400
401 manipulators.emplace_back(std::move(manip));
402 }
403
404 for (auto& manip : manipulators)
405 {
406 manip->visualize(remote.arviz.value());
407 stage.add(manip->gizmo.layer);
408 }
409
410 runIk();
411
412 viz::CommitResult result = remote.arviz->commit(stage);
413 ARMARX_VERBOSE << "Initial commit at revision: " << result.revision();
414 }
415
416 void
418 {
419 viz::CommitResult result = remote.arviz->commit(stage);
420
421 // Reset the stage, so that it can be rebuild during the interaction handling
422 stage.reset();
423
424 for (auto& manip : manipulators)
425 {
426 stage.requestInteraction(manip->gizmo.layer);
427 }
428
429 viz::InteractionFeedbackRange interactions = result.interactions();
430
431 bool updated = false;
432 for (viz::InteractionFeedback const& inter : interactions)
433 {
434 for (auto& manip : manipulators)
435 {
436 updated |= manip->handle(inter, &stage);
437 }
438 }
439 if (updated)
440 {
441 runIk();
442 }
443 }
444
445 void
447 {
448 for (auto& manip : manipulators)
449 {
450 manip->runIk(robot);
451 }
452
453 robot.visu.pose(robot.robot->getGlobalPose());
454 robot.visu.joints(robot.robot->getJointValues());
455 stage.add(robot.layer);
456 }
457
458} // namespace armar6::skills::components::armar6_ik_demo
#define VAROUT(x)
std::vector< std::unique_ptr< Manipulator > > manipulators
Definition IkDemo.h:61
void defineProperties(armarx::PropertyDefinitionContainer &defs)
Definition IkDemo.cpp:346
static std::string resolvePath(const std::string &path, bool verbose=true)
Resolves environment variables and home paths and tries to make path absolute.
decltype(auto) optional(PropertyType &setter, const std::string &name, const std::string &description="", PropertyDefinitionBase::PropertyConstness constness=PropertyDefinitionBase::eConstant)
static Result CalculateDiffIK(const Eigen::Matrix4f targetPose, VirtualRobot::RobotNodeSetPtr rns, VirtualRobot::RobotNodePtr tcp=VirtualRobot::RobotNodePtr(), Parameters params=Parameters())
virtual Layer layer(std::string const &name) const
Definition Client.cpp:80
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#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_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
const simox::meta::EnumNames< IkMethod > IkMethodNames
Definition IkDemo.cpp:32
This file is part of ArmarX.
InteractionDescription interaction()
Definition ElementOps.h:109
@ ContextMenuChosen
A context menu entry was chosen.
Definition Interaction.h:21
Definition Impl.cpp:41
std::vector< std::string > robotNodeSetNames() const
Definition IkDemo.cpp:339
virtual void visualize(viz::Client &arviz)=0
virtual bool handle(viz::InteractionFeedback const &interaction, viz::StagedCommit *stage)
Definition IkDemo.cpp:49
virtual void runIk(IkDemo::Robot &robot)=0
bool handle(viz::InteractionFeedback const &interaction, viz::StagedCommit *stage) override
Definition IkDemo.cpp:88
long revision() const
Definition Client.h:79
InteractionFeedbackRange interactions() const
Definition Client.h:85
A staged commit prepares multiple layers to be committed.
Definition Client.h:30