TCPControlUnit.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 ArmarX::
17* @author Mirko Waechter ( mirko.waechter at kit dot edu)
18* @date 2013
19* @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20* GNU General Public License
21*/
22
23#include "TCPControlUnit.h"
24
25#include <cfloat>
26#include <memory>
27
28#include <Eigen/Core>
29
30#include <SimoxUtility/algorithm/string/string_tools.h>
31#include <VirtualRobot/IK/DifferentialIK.h>
32#include <VirtualRobot/MathTools.h>
33#include <VirtualRobot/RobotConfig.h>
34#include <VirtualRobot/RobotNodeSet.h>
35#include <VirtualRobot/XML/RobotIO.h>
36
40
42
43using namespace VirtualRobot;
44using namespace Eigen;
45
46namespace armarx
47{
49 maxJointVelocity(30.f / 180 * 3.141),
50 cycleTime(30),
51 requested(false),
52 calculationRunning(false)
53 {
54 }
55
56 void
58 {
59 topicName = getName() + "State";
60 usingProxy(getProperty<std::string>("KinematicUnitName").getValue());
61 usingProxy(getProperty<std::string>("RobotStateComponentName").getValue());
62 offeringTopic("DebugObserver");
63 offeringTopic(topicName);
64 usingTopic(getProperty<std::string>("RobotStateTopicName").getValue());
65
66 cycleTime = getProperty<int>("CycleTime").getValue();
67 maxJointVelocity = getProperty<float>("MaxJointVelocity").getValue();
68 }
69
70 void
72 {
73 std::unique_lock lock(dataMutex);
74
75 debugObs = getTopic<DebugObserverInterfacePrx>("DebugObserver");
76 kinematicUnitPrx = getProxy<KinematicUnitInterfacePrx>(
77 getProperty<std::string>("KinematicUnitName").getValue());
78 robotStateComponentPrx = getProxy<RobotStateComponentInterfacePrx>(
79 getProperty<std::string>("RobotStateComponentName").getValue());
80
81
82 //remoteRobotPrx = robotStateComponentPrx->getSynchronizedRobot();
83 robotName = robotStateComponentPrx->getRobotName();
84 localRobot = RemoteRobot::createLocalClone(robotStateComponentPrx,
85 robotStateComponentPrx->getRobotFilename(),
86 robotStateComponentPrx->getArmarXPackages());
87 jointExistenceCheckRobot =
88 RemoteRobot::createLocalClone(robotStateComponentPrx,
89 robotStateComponentPrx->getRobotFilename(),
90 robotStateComponentPrx->getArmarXPackages());
91
92 localReportRobot = localRobot->clone(localRobot->getName());
93
94 std::string nodesetsString = getProperty<std::string>("TCPsToReport").getValue();
95 nodesToReport.clear();
96 if (!nodesetsString.empty())
97 {
98 if (nodesetsString == "*")
99 {
100 auto nodesets = localReportRobot->getRobotNodeSets();
101
102 for (RobotNodeSetPtr& set : nodesets)
103 {
104 if (set->getTCP())
105 {
106 nodesToReport.push_back(set->getTCP());
107 }
108 }
109 }
110 else
111 {
112 std::vector<std::string> nodesetNames = simox::alg::split(nodesetsString, ",");
113
114 for (auto& name : nodesetNames)
115 {
116 auto node = localReportRobot->getRobotNode(name);
117
118 if (node)
119 {
120 nodesToReport.push_back(node);
121 }
122 else
123 {
124 ARMARX_ERROR << "Could not find node with name: " << name;
125 }
126 }
127 }
128 }
129
130 std::vector<RobotNodePtr> nodes = localRobot->getRobotNodes();
131
132 for (unsigned int i = 0; i < nodes.size(); i++)
133 {
134 ARMARX_VERBOSE << nodes.at(i)->getName();
135 }
136
137
138 listener = getTopic<TCPControlUnitListenerPrx>(topicName);
139
140 requested = false;
141
142 if (execTask)
143 {
144 execTask->stop();
145 }
146
147 execTask = new PeriodicTask<TCPControlUnit>(
148 this, &TCPControlUnit::periodicExec, cycleTime, false, "TCPVelocityCalculator");
149 execTask->start();
150 execTask->setDelayWarningTolerance(100);
151 }
152
153 void
155 {
156
157 try
158 {
159 release();
160 }
161 catch (std::exception& e)
162 {
163 ARMARX_WARNING << "Releasing TCP Unit failed";
164 }
165
166 if (execTask)
167 {
168 execTask->stop();
169 }
170 }
171
172 void
176
177 void
178 TCPControlUnit::setCycleTime(Ice::Int milliseconds, const Ice::Current& c)
179 {
180 std::unique_lock lock(taskMutex);
181 cycleTime = milliseconds;
182
183 if (execTask)
184 {
185 execTask->changeInterval(cycleTime);
186 }
187 }
188
189 void
190 TCPControlUnit::setTCPVelocity(const std::string& nodeSetName,
191 const std::string& tcpName,
192 const FramedDirectionBasePtr& translationVelocity,
193 const FramedDirectionBasePtr& orientationVelocityRPY,
194 const Ice::Current& c)
195 {
196 if (!isRequested())
197 {
198 ARMARX_WARNING << "Implicitly requesting TCPControlUnit! Please call request before "
199 "setting TCPVelocities!";
200 request();
201 }
202
203 std::unique_lock lock(dataMutex);
204 ARMARX_CHECK_EXPRESSION(jointExistenceCheckRobot->hasRobotNodeSet(nodeSetName))
205 << "The robot does not have the node set: " + nodeSetName;
206
207
208 if (translationVelocity)
209 {
210 ARMARX_DEBUG << "Setting new Velocity for " << nodeSetName << " in frame "
211 << translationVelocity->frame << ":\n"
212 << FramedDirectionPtr::dynamicCast(translationVelocity)->toEigen();
213 }
214
215 if (orientationVelocityRPY)
216 {
217 ARMARX_DEBUG << "Orientation Velo in frame " << orientationVelocityRPY->frame << ": \n"
218 << FramedDirectionPtr::dynamicCast(orientationVelocityRPY)->toEigen();
219 }
220
221 TCPVelocityData data;
222 data.nodeSetName = nodeSetName;
223 data.translationVelocity = FramedDirectionPtr::dynamicCast(translationVelocity);
224 data.orientationVelocity = FramedDirectionPtr::dynamicCast(orientationVelocityRPY);
225
226 if (tcpName.empty())
227 {
228 data.tcpName =
229 jointExistenceCheckRobot->getRobotNodeSet(nodeSetName)->getTCP()->getName();
230 }
231 else
232 {
233 ARMARX_CHECK_EXPRESSION(jointExistenceCheckRobot->hasRobotNode(tcpName))
234 << "The robot does not have the node: " + tcpName;
235
236 data.tcpName = tcpName;
237 }
238
239 tcpVelocitiesMap[data.tcpName] = data;
240 }
241
242 void
243 TCPControlUnit::init(const Ice::Current& c)
244 {
245 }
246
247 void
248 TCPControlUnit::start(const Ice::Current& c)
249 {
250 }
251
252 void
253 TCPControlUnit::stop(const Ice::Current& c)
254 {
255 }
256
257 UnitExecutionState
259 {
260 switch (getState())
261 {
262 case eManagedIceObjectStarted:
263 return eUnitStarted;
264
265 case eManagedIceObjectInitialized:
266 case eManagedIceObjectStarting:
267 return eUnitInitialized;
268
269 case eManagedIceObjectExiting:
270 case eManagedIceObjectExited:
271 return eUnitStopped;
272
273 default:
274 return eUnitConstructed;
275 }
276 }
277
278 void
279 TCPControlUnit::request(const Ice::Current& c)
280 {
281 if (execTask)
282 {
283 // while (calculationRunning)
284 // {
285 // IceUtil::ThreadControl::yield();
286 // }
287
288 execTask->stop();
289 }
290
291 ARMARX_IMPORTANT << "Requesting TCPControlUnit";
292 std::unique_lock lock(dataMutex);
293 requested = true;
294
295 execTask = new PeriodicTask<TCPControlUnit>(
296 this, &TCPControlUnit::periodicExec, cycleTime, false, "TCPVelocityCalculator");
297 execTask->start();
298 execTask->setDelayWarningTolerance(100);
299 ARMARX_IMPORTANT << "Requested TCPControlUnit";
300 }
301
302 void
303 TCPControlUnit::release(const Ice::Current& c)
304 {
305 ARMARX_IMPORTANT << "Releasing TCPControlUnit";
306 std::unique_lock lock(dataMutex);
307
308 // while (calculationRunning)
309 // {
310 // IceUtil::ThreadControl::yield();
311 // }
312
313 tcpVelocitiesMap.clear();
314 localTcpVelocitiesMap.clear();
315 requested = false;
316 //kinematicUnitPrx->stop();
317 ARMARX_IMPORTANT << "Released TCPControlUnit";
318 }
319
320 bool
321 TCPControlUnit::isRequested(const Ice::Current& c)
322 {
323 // no lock needed to read a single bool value.
324 return requested;
325 }
326
327 void
328 TCPControlUnit::periodicExec()
329 {
330 std::unique_lock lock(dataMutex, std::defer_lock);
331
332 if (lock.try_lock())
333 {
334
335 {
336 localTcpVelocitiesMap.clear();
337 TCPVelocityDataMap::iterator it = tcpVelocitiesMap.begin();
338
339 for (; it != tcpVelocitiesMap.end(); it++)
340 {
341 localTcpVelocitiesMap[it->first] = it->second;
342 }
343
344 localDIKMap.clear();
345 DIKMap::iterator itDIK = dIKMap.begin();
346
347 for (; itDIK != dIKMap.end(); itDIK++)
348 {
349 localDIKMap[itDIK->first] = itDIK->second;
350 }
351
352 //ARMARX_DEBUG << "RN TCP R pose1:" << localRobot->getRobotNode("TCP R")->getGlobalPose();
353
354 RemoteRobot::synchronizeLocalClone(localRobot, robotStateComponentPrx);
355 //ARMARX_DEBUG << "RN TCP R pose2:" << localRobot->getRobotNode("TCP R")->getGlobalPose();
356 }
357
358 if (requested)
359 {
361 }
362 }
363 }
364
365 void
367 {
368 TCPVelocityDataMap::iterator it = localTcpVelocitiesMap.begin();
369
370 for (; it != localTcpVelocitiesMap.end(); it++)
371 {
372 const TCPVelocityData& data = it->second;
373 RobotNodeSetPtr nodeSet = localRobot->getRobotNodeSet(data.nodeSetName);
374 // std::string refFrame = nodeSet->getTCP()->getName();
375 DIKMap::iterator itDIK = localDIKMap.find(data.nodeSetName);
376
377 if (itDIK == localDIKMap.end())
378 {
379 VirtualRobot::DifferentialIKPtr dIk(new EDifferentialIK(
380 nodeSet, localRobot->getRootNode(), VirtualRobot::JacobiProvider::eSVDDamped));
381 float lambda = getProperty<float>("LambdaDampedSVD").getValue();
382 dIk->setDampedSvdLambda(lambda);
383 localDIKMap[data.nodeSetName] = dIk;
384 }
385
386 auto dIk = std::dynamic_pointer_cast<EDifferentialIK>(localDIKMap[data.nodeSetName]);
387 dIk->clearGoals();
388 }
389
390 using namespace Eigen;
391
392 it = localTcpVelocitiesMap.begin();
393
394 for (; it != localTcpVelocitiesMap.end(); it++)
395 {
396
397 TCPVelocityData& data = it->second;
398 // RobotNodeSetPtr nodeSet = localRobot->getRobotNodeSet(data.nodeSetName);
399 std::string refFrame = localRobot->getRootNode()->getName();
400 IKSolver::CartesianSelection mode;
401
402 if (data.translationVelocity && data.orientationVelocity)
403 {
404 mode = IKSolver::All;
405 // ARMARX_DEBUG << deactivateSpam(4) << "FullMode";
406 }
407 else if (data.translationVelocity && !data.orientationVelocity)
408 {
409 mode = IKSolver::Position;
410 }
411 else if (!data.translationVelocity && data.orientationVelocity)
412 {
413 mode = IKSolver::Orientation;
414 }
415 else
416 {
417 // ARMARX_VERBOSE << deactivateSpam(2) << "No mode feasible for " << data.nodeSetName << " - skipping";
418 continue;
419 }
420
421 RobotNodePtr tcpNode = localRobot->getRobotNode(data.tcpName);
422 Eigen::Matrix4f m;
423 m.setIdentity();
424
425 if (data.orientationVelocity)
426 {
427 Eigen::Matrix3f rotInOriginalFrame, rotInRefFrame;
428 rotInOriginalFrame =
429 Eigen::AngleAxisf(data.orientationVelocity->z * cycleTime * 0.001,
430 Eigen::Vector3f::UnitZ()) *
431 Eigen::AngleAxisf(data.orientationVelocity->y * cycleTime * 0.001,
432 Eigen::Vector3f::UnitY()) *
433 Eigen::AngleAxisf(data.orientationVelocity->x * cycleTime * 0.001,
434 Eigen::Vector3f::UnitX());
435
436 if (data.orientationVelocity->frame != refFrame)
437 {
438 Eigen::Matrix4f trafoOriginalFrameToGlobal = Eigen::Matrix4f::Identity();
439
440 if (data.orientationVelocity->frame != GlobalFrame)
441 {
442 trafoOriginalFrameToGlobal =
443 localRobot->getRobotNode(data.orientationVelocity->frame)
444 ->getGlobalPose();
445 }
446
447 Eigen::Matrix4f trafoRefFrameToGlobal = Eigen::Matrix4f::Identity();
448
449 if (refFrame != GlobalFrame)
450 {
451 trafoRefFrameToGlobal = localRobot->getRobotNode(refFrame)->getGlobalPose();
452 }
453
454 Eigen::Matrix4f trafoOriginalToRef =
455 trafoRefFrameToGlobal.inverse() * trafoOriginalFrameToGlobal;
456 rotInRefFrame = trafoOriginalToRef.block<3, 3>(0, 0) * rotInOriginalFrame *
457 trafoOriginalToRef.block<3, 3>(0, 0).inverse();
458 }
459 else
460 {
461 rotInRefFrame = rotInOriginalFrame;
462 }
463
464 m.block(0, 0, 3, 3) = rotInRefFrame * (tcpNode->getGlobalPose().block(0, 0, 3, 3));
465 }
466
467 // ARMARX_VERBOSE << deactivateSpam(1) << "Delta Mat: \n" << m;
468
469
470 // m = m * tcpNode->getGlobalPose();
471
472 if (data.translationVelocity)
473 {
474 data.translationVelocity =
475 FramedDirection::ChangeFrame(localRobot, *data.translationVelocity, refFrame);
476 ARMARX_INFO << deactivateSpam(1) << "Translation in " << refFrame << ": "
477 << data.translationVelocity->toEigen();
478
479 m.block<3, 1>(0, 3) = tcpNode->getGlobalPose().block<3, 1>(0, 3) +
480 data.translationVelocity->toEigen() * cycleTime * 0.001;
481 }
482
483
484 DifferentialIKPtr dIK = localDIKMap[data.nodeSetName];
485
486 if (!dIK)
487 {
489 << "DiffIK is NULL for robot node set: " << data.nodeSetName;
490 continue;
491 }
492
493 // ARMARX_VERBOSE << deactivateSpam(1) << "Old Pos: \n" << tcpNode->getGlobalPose();
494 // ARMARX_VERBOSE << deactivateSpam(1) << "New Goal: \n" << m;
495 // if(tcpNode != nodeSet->getTCP())
496 // {
497 // mode = IKSolver::Z;
498 // Eigen::VectorXf weight(1);
499 // weight << 0.2;
500 // boost::shared_dynamic_cast<EDifferentialIK>(dIK)->setGoal(m, tcpNode,mode, 0.001, 0.001/180.0f*3.14159, weight);
501 // }
502 // else
503 dIK->setGoal(m, tcpNode, mode, 0.001, 0.001 / 180.0f * 3.14159);
504
505 // ARMARX_VERBOSE << deactivateSpam(1) << "Delta to Goal: " << dIK->getDeltaToGoal(tcpNode);
506 }
507
508
509 NameValueMap targetVelocities;
510 NameControlModeMap controlModes;
511 DIKMap::iterator itDIK = localDIKMap.begin();
512
513 for (; itDIK != localDIKMap.end(); itDIK++)
514 {
515 RobotNodeSetPtr robotNodeSet = localRobot->getRobotNodeSet(itDIK->first);
516
517 auto dIK = std::dynamic_pointer_cast<EDifferentialIK>(itDIK->second);
518 // ARMARX_VERBOSE << deactivateSpam(1) << "Old Pos: \n" << robotNodeSet->getTCP()->getGlobalPose();
519 // dIK->setVerbose(true);
520 Eigen::VectorXf jointDelta;
521 dIK->computeSteps(
522 jointDelta, 0.8f, 0.001, 1, &EDifferentialIK::computeStep); // 1.0, 0.00001, 50
523 // ARMARX_VERBOSE << deactivateSpam(1) << "New Goal: \n" << robotNodeSet->getTCP()->getGlobalPose();
524
525 jointDelta /= (cycleTime * 0.001);
526
527 jointDelta = applyMaxJointVelocity(jointDelta, maxJointVelocity);
528
529 lastTCPPose = robotNodeSet->getTCP()->getGlobalPose();
530
531 // build name value map
532
533 const std::vector<VirtualRobot::RobotNodePtr> nodes = robotNodeSet->getAllRobotNodes();
534 std::vector<VirtualRobot::RobotNodePtr>::const_iterator iter = nodes.begin();
535 int i = 0;
536
537 while (iter != nodes.end() && i < jointDelta.rows())
538 {
539 if (targetVelocities.find((*iter)->getName()) != targetVelocities.end())
540 {
542 << deactivateSpam(2) << (*iter)->getName()
543 << " is set from two joint delta calculations - overwriting first value";
544 }
545
546 targetVelocities.insert(std::make_pair((*iter)->getName(), jointDelta(i)));
547
548 controlModes.insert(std::make_pair((*iter)->getName(), eVelocityControl));
549 i++;
550 iter++;
551 };
552 }
553
554
555 kinematicUnitPrx->switchControlMode(controlModes);
556 kinematicUnitPrx->setJointVelocities(targetVelocities);
557 }
558
559 void
560 TCPControlUnit::ContinuousAngles(const Eigen::AngleAxisf& oldAngle,
561 Eigen::AngleAxisf& newAngle,
562 double& offset)
563 {
564 // if(oldAngle.axis().isApprox(newAngle.axis()*-1))
565 const Eigen::Vector3f& v1 = oldAngle.axis();
566 const Eigen::Vector3f& v2 = newAngle.axis();
567 const Eigen::Vector3f& v2i = newAngle.axis() * -1;
568 double angle = acos(v1.dot(v2) / (v1.norm() * v2.norm()));
569 double angleInv = acos(v1.dot(v2i) / (v1.norm() * v2i.norm()));
570 // std::cout << "angle1: " << angle << std::endl;
571 // std::cout << "angleInv: " << angleInv << std::endl;
572
573 // Eigen::AngleAxisd result;
574 if (angle > angleInv)
575 {
576 // ARMARX_IMPORTANT_S << "inversion needed" << std::endl;
577 newAngle = Eigen::AngleAxisf(2.0 * M_PI - newAngle.angle(), newAngle.axis() * -1);
578 }
579
580 // else newAngle = newAngle;
581
582 if (fabs(newAngle.angle() + offset - oldAngle.angle()) >
583 fabs(newAngle.angle() + offset - (oldAngle.angle() + M_PI * 2)))
584 {
585 offset -= M_PI * 2;
586 }
587 else if (fabs(newAngle.angle() + offset - oldAngle.angle()) >
588 fabs((newAngle.angle() + M_PI * 2 + offset) - oldAngle.angle()))
589 {
590 offset += M_PI * 2;
591 }
592
593 newAngle.angle() += offset;
594 }
595
596 Eigen::VectorXf
597 TCPControlUnit::CalcJointLimitAvoidanceDeltas(VirtualRobot::RobotNodeSetPtr robotNodeSet,
598 const Eigen::MatrixXf& jacobian,
599 const Eigen::MatrixXf& jacobianInverse,
600 Eigen::VectorXf desiredJointValues)
601 {
602 std::vector<VirtualRobot::RobotNodePtr> nodes = robotNodeSet->getAllRobotNodes();
603 Eigen::VectorXf actualJointValues(nodes.size());
604
605 if (desiredJointValues.rows() == 0)
606 {
607
608 desiredJointValues.resize(nodes.size());
609
610 for (unsigned int i = 0; i < nodes.size(); i++)
611 {
612 VirtualRobot::RobotNodePtr node = nodes.at(i);
613 desiredJointValues(i) =
614 (node->getJointLimitHigh() - node->getJointLimitLow()) * 0.5f +
615 node->getJointLimitLow();
616 }
617 }
618
619 // ARMARX_IMPORTANT << deactivateSpam(true, 0.5) << "desiredJointValues: " << desiredJointValues;
620 Eigen::VectorXf jointCompensationDeltas(desiredJointValues.rows());
621
622 for (unsigned int i = 0; i < desiredJointValues.rows(); i++)
623 {
624 VirtualRobot::RobotNodePtr node = nodes.at(i);
625 actualJointValues(i) = node->getJointValue();
626 jointCompensationDeltas(i) = (node->getJointValue() - desiredJointValues(i)) /
627 (node->getJointLimitHigh() - node->getJointLimitLow());
628 jointCompensationDeltas(i) =
629 -pow(jointCompensationDeltas(i), 3) * pow(nodes.size() - i, 2);
630 }
631
632 // ARMARX_IMPORTANT << deactivateSpam(true, 0.5) << "actualJointValues: " << actualJointValues;
633
634 return CalcNullspaceJointDeltas(jointCompensationDeltas, jacobian, jacobianInverse);
635 }
636
637 Eigen::VectorXf
638 TCPControlUnit::CalcNullspaceJointDeltas(const Eigen::VectorXf& desiredJointDeltas,
639 const Eigen::MatrixXf& jacobian,
640 const Eigen::MatrixXf& jacobianInverse)
641 {
642 Eigen::MatrixXf I(jacobianInverse.rows(), jacobian.cols());
643 I.setIdentity();
644
645 Eigen::MatrixXf nullspaceProjection = I - jacobianInverse * jacobian;
646
647 Eigen::VectorXf delta = nullspaceProjection * desiredJointDeltas;
648 return delta;
649 }
650
651 Eigen::VectorXf
652 TCPControlUnit::applyMaxJointVelocity(const Eigen::VectorXf& jointVelocity,
653 float maxJointVelocity)
654 {
655 double currentMaxJointVel = std::numeric_limits<double>::min();
656
657 for (unsigned int i = 0; i < jointVelocity.rows(); i++)
658 {
659 currentMaxJointVel =
660 std::max(static_cast<double>(std::abs(jointVelocity(i))), currentMaxJointVel);
661 }
662
663 if (currentMaxJointVel > maxJointVelocity)
664 {
666 << "max joint velocity too high: " << currentMaxJointVel
667 << " allowed: " << maxJointVelocity;
668 return jointVelocity * (maxJointVelocity / currentMaxJointVel);
669 }
670 else
671 {
672 return jointVelocity;
673 }
674 }
675
682
684 RobotNodePtr coordSystem,
685 JacobiProvider::InverseJacobiMethod invJacMethod) :
686 DifferentialIK(rns, coordSystem, invJacMethod)
687 {
688 }
689
690 Eigen::MatrixXf
692 {
693 if (nRows == 0)
694 {
695 this->setNRows();
696 }
697
698 size_t nDoF = nodes.size();
699
700 using namespace Eigen;
701 MatrixXf Jacobian(nRows, nDoF);
702
703 size_t index = 0;
704
705 for (size_t i = 0; i < tcp_set.size(); i++)
706 {
707 SceneObjectPtr tcp = tcp_set[i];
708
709 if (this->targets.find(tcp) != this->targets.end())
710 {
711 IKSolver::CartesianSelection mode = this->modes[tcp];
712 MatrixXf partJacobian = this->getJacobianMatrix(tcp, mode);
713 Jacobian.block(index, 0, partJacobian.rows(), nDoF) = partJacobian;
714 }
715 else
716 {
717 ARMARX_ERROR << "Internal error?!" << std::endl; // Error
718 }
719 }
720
721 return Jacobian;
722 }
723
724 void
726 {
727 targets.clear();
728 modes.clear();
729 tolerancePosition.clear();
730 toleranceRotation.clear();
731 parents.clear();
732 tcpWeights.clear();
733 }
734
735 void
736 EDifferentialIK::setRefFrame(RobotNodePtr coordSystem)
737 {
738 this->coordSystem = coordSystem;
739 }
740
741 void
742 EDifferentialIK::setGoal(const Matrix4f& goal,
743 RobotNodePtr tcp,
744 IKSolver::CartesianSelection mode,
745 float tolerancePosition,
746 float toleranceRotation,
747 VectorXf tcpWeight)
748 {
749 if (mode <= IKSolver::Z)
750 {
751 ARMARX_CHECK_EXPRESSION(tcpWeight.rows() == 1)
752 << "The tcpWeight vector must be of size 1";
753 }
754 else if (mode <= IKSolver::Orientation)
755 {
756 ARMARX_CHECK_EXPRESSION(tcpWeight.rows() == 3)
757 << "The tcpWeight vector must be of size 3";
758 }
759 else if (mode == IKSolver::All)
760 {
761 ARMARX_CHECK_EXPRESSION(tcpWeight.rows() == 6)
762 << "The tcpWeight vector must be of size 6";
763 }
764
765 tcpWeights[tcp] = tcpWeight;
766 DifferentialIK::setGoal(goal, tcp, mode, tolerancePosition, toleranceRotation);
767 }
768
769 void
771 {
772 this->dofWeights = dofWeights;
773 }
774
775 bool
776 EDifferentialIK::computeSteps(float stepSize, float mininumChange, int maxNStep)
777 {
778 VectorXf jointDelta;
779 return computeSteps(
780 jointDelta, stepSize, mininumChange, maxNStep, &DifferentialIK::computeStep);
781 }
782
783 // void EDifferentialIK::setTCPWeights(Eigen::VectorXf tcpWeights)
784 // {
785 // this->tcpWeights = tcpWeights;
786 // }
787
788 bool
789 EDifferentialIK::computeSteps(VectorXf& resultJointDelta,
790 float stepSize,
791 float mininumChange,
792 int maxNStep,
793 ComputeFunction computeFunction)
794 {
795 VR_ASSERT(rns);
796 VR_ASSERT(nodes.size() == rns->getSize());
797 //std::vector<RobotNodePtr> rn = this->nodes;
798 RobotPtr robot = rns->getRobot();
799 VR_ASSERT(robot);
800 std::vector<float> jv(nodes.size(), 0.0f);
801 std::vector<float> jvBest = rns->getJointValues();
802 int step = 0;
803 checkTolerances();
804
805 std::vector<std::pair<float, VectorXf>> jointDeltaIterations;
806 float lastDist = FLT_MAX;
807 VectorXf oldJointValues;
808 rns->getJointValues(oldJointValues);
809 VectorXf tempDOFWeights = dofWeights;
810 // VectorXf dThetaSum(nodes.size());
811 resultJointDelta.resize(nodes.size());
812 resultJointDelta.setZero();
813
814 do
815 {
816 VectorXf dTheta = (this->*computeFunction)(stepSize);
817
819 {
820 dTheta = computeStep(stepSize);
821 }
822
823
824 for (unsigned int i = 0; i < nodes.size(); i++)
825 {
826 ARMARX_DEBUG << VAROUT(nodes[i]->getJointValue()) << VAROUT(dTheta[i]);
827 jv[i] = (nodes[i]->getJointValue() + dTheta[i]);
828
829 if (std::isnan(jv[i]) || std::isinf(jv[i]))
830 {
831 ARMARX_WARNING_S << "Aborting, invalid joint value (nan)" << std::endl;
832 dofWeights = tempDOFWeights;
833 return false;
834 }
835
836 //nodes[i]->setJointValue(nodes[i]->getJointValue() + dTheta[i]);
837 }
838
839 robot->setJointValues(rns, jv);
840
841 VectorXf newJointValues;
842 rns->getJointValues(newJointValues);
843 resultJointDelta = newJointValues - oldJointValues;
844
845
846 // ARMARX_DEBUG << "joint angle deltas:\n" << dThetaSum;
847
848 // check tolerances
849 if (checkTolerances())
850 {
851 if (verbose)
852 {
853 ARMARX_INFO << deactivateSpam(1) << "Tolerances ok, loop:" << step << std::endl;
854 }
855
856 break;
857 }
858
859 float d = dTheta.norm();
860 float posDist = getMeanErrorPosition();
861 float oriErr = getErrorRotation(rns->getTCP());
862
863 if (dTheta.norm() < mininumChange)
864 {
865 // if (verbose)
867 << "Could not improve result any more (dTheta.norm()=" << d
868 << "), loop:" << step << " Resulting error: pos " << posDist
869 << " orientation: " << oriErr << std::endl;
870 break;
871 }
872
873 if (checkImprovement && posDist > lastDist)
874 {
875 // if (verbose)
877 << "Could not improve result any more (current position error="
878 << posDist << ", last loop's error:" << lastDist << "), loop:" << step
879 << std::endl;
880 robot->setJointValues(rns, jvBest);
881 break;
882 }
883
884 jvBest = jv;
885 lastDist = posDist;
886 step++;
887
888 jointDeltaIterations.push_back(std::make_pair(getWeightedError(), resultJointDelta));
889 } while (step < maxNStep);
890
891
892 float bestJVError = std::numeric_limits<float>::max();
893
894 for (unsigned int i = 0; i < jointDeltaIterations.size(); i++)
895 {
896 if (jointDeltaIterations.at(i).first < bestJVError)
897 {
898 bestJVError = jointDeltaIterations.at(i).first;
899 resultJointDelta = jointDeltaIterations.at(i).second;
900 }
901 }
902
903 robot->setJointValues(rns, oldJointValues + resultJointDelta);
904
905 // ARMARX_DEBUG << "best try: " << bestIndex << " with error: " << bestJVError;
906 // rns->setJointValues(oldJointValues);
907 // Matrix4f oldPose = rns->getTCP()->getGlobalPose();
908 // rns->setJointValues(oldJointValues+dThetaSum);
909 // Matrix4f newPose = rns->getTCP()->getGlobalPose();
910 // ARMARX_IMPORTANT << "tcp delta:\n" << newPose.block(0,3,3,1) - oldPose.block(0,3,3,1);
911 dofWeights = tempDOFWeights;
912
913 if (step >= maxNStep && verbose)
914 {
915 ARMARX_INFO << deactivateSpam(1) << "IK failed, loop:" << step << std::endl;
916 ARMARX_INFO << deactivateSpam(1) << "pos error:" << getMeanErrorPosition() << std::endl;
917 ARMARX_INFO << deactivateSpam(1) << "rot error:" << getErrorRotation(rns->getTCP())
918 << std::endl;
919 return false;
920 }
921
922 return true;
923 }
924
925 VectorXf
927 {
928
929 if (nRows == 0)
930 {
931 this->setNRows();
932 }
933
934 size_t nDoF = nodes.size();
935
936 MatrixXf Jacobian(nRows, nDoF);
937 VectorXf error(nRows);
938 size_t index = 0;
939
940 for (size_t i = 0; i < tcp_set.size(); i++)
941 {
942 SceneObjectPtr tcp = tcp_set[i];
943
944 if (this->targets.find(tcp) != this->targets.end())
945 {
946 Eigen::VectorXf delta = getDeltaToGoal(tcp);
947 //ARMARX_DEBUG << VAROUT(delta);
948 IKSolver::CartesianSelection mode = this->modes[tcp];
949 MatrixXf partJacobian = this->getJacobianMatrix(tcp, mode);
950 //ARMARX_DEBUG << VAROUT(partJacobian);
951
952 Jacobian.block(index, 0, partJacobian.rows(), nDoF) = partJacobian;
953 Vector3f position = delta.head(3);
954 position *= stepSize;
955
956 if (mode & IKSolver::X)
957 {
958 error(index) = position(0);
959 index++;
960 }
961
962 if (mode & IKSolver::Y)
963 {
964 error(index) = position(1);
965 index++;
966 }
967
968 if (mode & IKSolver::Z)
969 {
970 error(index) = position(2);
971 index++;
972 }
973
974 if (mode & IKSolver::Orientation)
975 {
976 error.segment(index, 3) = delta.tail(3) * stepSize;
977 index += 3;
978 }
979 }
980 else
981 {
982 ARMARX_ERROR << "Internal error?!" << std::endl; // Error
983 }
984 }
985
986 // applyDOFWeightsToJacobian(Jacobian);
987 ARMARX_DEBUG << VAROUT(Jacobian);
988 MatrixXf pseudo = computePseudoInverseJacobianMatrix(Jacobian);
989 ARMARX_DEBUG << VAROUT(pseudo);
990 ARMARX_DEBUG << VAROUT(error);
991 return pseudo * error;
992 }
993
994 VectorXf
996 {
997 if (nRows == 0)
998 {
999 this->setNRows();
1000 }
1001
1002 size_t nDoF = nodes.size();
1003
1004 std::map<float, MatrixXf> partJacobians;
1005
1006 VectorXf thetaSum(nDoF);
1007 thetaSum.setZero();
1008 size_t index = 0;
1009
1010 for (size_t i = 0; i < tcp_set.size(); i++)
1011 {
1012 SceneObjectPtr tcp = tcp_set[i];
1013
1014 if (this->targets.find(tcp) != this->targets.end())
1015 {
1016 Eigen::VectorXf delta = getDeltaToGoal(tcp);
1017 IKSolver::CartesianSelection mode = this->modes[tcp];
1018 MatrixXf partJacobian = this->getJacobianMatrix(tcp, mode);
1019
1020 // apply tcp weights
1021 // applyTCPWeights(tcp, partJacobian);
1022 int tcpDOF = 0;
1023
1024 if (mode <= IKSolver::Z)
1025 {
1026 tcpDOF = 1;
1027 }
1028 else if (mode <= IKSolver::Orientation)
1029 {
1030 tcpDOF = 3;
1031 }
1032 else if (mode == IKSolver::All)
1033 {
1034 tcpDOF = 6;
1035 }
1036
1037 index = 0;
1038 VectorXf partError(tcpDOF);
1039 Vector3f position = delta.head(3);
1040 // ARMARX_DEBUG << tcp->getName() << "'s error: " << position << " weighted error: " << position*stepSize;
1041 position *= stepSize;
1042
1043 if (mode & IKSolver::X)
1044 {
1045 partError(index) = position(0);
1046 index++;
1047 }
1048
1049 if (mode & IKSolver::Y)
1050 {
1051 partError(index) = position(1);
1052 index++;
1053 }
1054
1055 if (mode & IKSolver::Z)
1056 {
1057 partError(index) = position(2);
1058 index++;
1059 }
1060
1061 if (mode & IKSolver::Orientation)
1062 {
1063 partError.segment(index, 3) = delta.tail(3) * stepSize;
1064 index += 3;
1065 }
1066
1067
1068 ARMARX_DEBUG << deactivateSpam(0.05) << "step size adjusted error to goal:\n"
1069 << partError;
1070
1071 applyDOFWeightsToJacobian(partJacobian);
1072 // ARMARX_DEBUG << "Jac:\n" << partJacobian;
1073
1074
1075 MatrixXf pseudo = computePseudoInverseJacobianMatrix(partJacobian);
1076
1077 Eigen::VectorXf tcpWeightVec;
1078 std::map<VirtualRobot::SceneObjectPtr, Eigen::VectorXf>::iterator it =
1079 tcpWeights.find(tcp);
1080
1081 if (it != tcpWeights.end())
1082 {
1083 tcpWeightVec = it->second;
1084 }
1085 else
1086 {
1087 IKSolver::CartesianSelection mode = modes[tcp_set.at(i)];
1088 int size = 1;
1089
1090 if (mode <= IKSolver::Z)
1091 {
1092 size = 1;
1093 }
1094 else if (mode <= IKSolver::Orientation)
1095 {
1096 size = 3;
1097 }
1098 else if (mode == IKSolver::All)
1099 {
1100 size = 6;
1101 }
1102
1103 Eigen::VectorXf tmptcpWeightVec(size);
1104 tmptcpWeightVec.setOnes();
1105 tcpWeightVec = tmptcpWeightVec;
1106 }
1107
1108
1109 if (pseudo.cols() == tcpWeightVec.rows())
1110 {
1111
1112 Eigen::MatrixXf weightMat(tcpWeightVec.rows(), tcpWeightVec.rows());
1113 weightMat.setIdentity();
1114 weightMat.diagonal() = tcpWeightVec;
1115 // ARMARX_DEBUG << /*deactivateSpam(1) <<*/ "tcpWeightVec:\n" << tcpWeightVec;
1116 // ARMARX_DEBUG << /*deactivateSpam(1) << */"InvJac Before:\n" << invJacobian;
1117 pseudo = pseudo * weightMat;
1118 // ARMARX_DEBUG << /*deactivateSpam(1) <<*/ "InvJac after:\n" << pseudo;
1119 }
1120 else
1121 {
1123 << "Wrong dimension of tcp weights: " << tcpWeightVec.rows()
1124 << ", but should be: " << pseudo.cols();
1125 }
1126
1127
1128 thetaSum += pseudo * partError;
1129 }
1130 else
1131 {
1132 ARMARX_ERROR << "Internal error?!" << std::endl; // Error
1133 }
1134 }
1135
1136 return thetaSum;
1137 }
1138
1139 bool
1141 float minChange,
1142 int maxSteps,
1143 bool useAlternativeOnFail)
1144 {
1145 Eigen::VectorXf jointValuesBefore;
1146 rns->getJointValues(jointValuesBefore);
1147 Eigen::VectorXf resultJointDelta;
1148 Eigen::VectorXf jointDeltaAlternative;
1149 bool result = computeSteps(resultJointDelta, stepSize, minChange, maxSteps);
1150 float error = getWeightedError();
1151
1152 if (useAlternativeOnFail && error > 5)
1153 {
1154 result = computeSteps(jointDeltaAlternative,
1155 stepSize,
1156 minChange,
1157 maxSteps,
1159 }
1160
1161 if (getWeightedError() < error)
1162 {
1163 resultJointDelta = jointDeltaAlternative;
1164 }
1165
1166 return result;
1167 }
1168
1169 void
1171 {
1172 if (dofWeights.rows() == Jacobian.cols())
1173 {
1174 Eigen::MatrixXf weightMat(dofWeights.rows(), dofWeights.rows());
1175 weightMat.setIdentity();
1176 weightMat.diagonal() = dofWeights;
1177 // ARMARX_DEBUG << deactivateSpam(1) << "Jac before:\n" << Jacobian;
1178 // ARMARX_DEBUG << deactivateSpam(1) << "Weights:\n" << weightMat;
1179 Jacobian = Jacobian * weightMat;
1180 // ARMARX_DEBUG << deactivateSpam(1) << "Jac after:\n" << Jacobian;
1181 }
1182 }
1183
1184 void
1185 EDifferentialIK::applyTCPWeights(RobotNodePtr tcp, MatrixXf& partJacobian)
1186 {
1187
1188 std::map<VirtualRobot::SceneObjectPtr, Eigen::VectorXf>::iterator it = tcpWeights.find(tcp);
1189
1190 if (it != tcpWeights.end())
1191 {
1192 Eigen::VectorXf& tcpWeightVec = it->second;
1193
1194 if (partJacobian.rows() == tcpWeightVec.rows())
1195 {
1196
1197 Eigen::MatrixXf weightMat(tcpWeightVec.rows(), tcpWeightVec.rows());
1198 weightMat.setIdentity();
1199 weightMat.diagonal() = tcpWeightVec;
1200 ARMARX_DEBUG << deactivateSpam(1) << "Jac Before: " << partJacobian;
1201 partJacobian = weightMat * partJacobian;
1202 ARMARX_DEBUG << deactivateSpam(1) << "Jac after: " << partJacobian;
1203 }
1204 else
1205 {
1207 << "Wrong dimension of tcp weights: " << tcpWeightVec.rows()
1208 << ", but should be: " << partJacobian.rows();
1209 }
1210 }
1211 }
1212
1213 void
1214 EDifferentialIK::applyTCPWeights(MatrixXf& invJacobian)
1215 {
1216 if (tcpWeightVec.rows() == 0)
1217 for (size_t i = 0; i < tcp_set.size(); i++)
1218 {
1219 std::map<VirtualRobot::SceneObjectPtr, Eigen::VectorXf>::iterator it =
1220 tcpWeights.find(tcp_set.at(i));
1221
1222 if (it != tcpWeights.end())
1223 {
1224 Eigen::VectorXf& tmptcpWeightVec = it->second;
1225 Eigen::VectorXf oldVec = tcpWeightVec;
1226 tcpWeightVec.resize(tcpWeightVec.rows() + tmptcpWeightVec.rows());
1227
1228 if (oldVec.rows() > 0)
1229 {
1230 tcpWeightVec.head(oldVec.rows()) = oldVec;
1231 }
1232
1233 tcpWeightVec.tail(tmptcpWeightVec.rows()) = tmptcpWeightVec;
1234 }
1235 else
1236 {
1237 IKSolver::CartesianSelection mode = modes[tcp_set.at(i)];
1238 int size = 1;
1239
1240 if (mode <= IKSolver::Z)
1241 {
1242 size = 1;
1243 }
1244 else if (mode <= IKSolver::Orientation)
1245 {
1246 size = 3;
1247 }
1248 else if (mode == IKSolver::All)
1249 {
1250 size = 6;
1251 }
1252
1253 Eigen::VectorXf oldVec = tcpWeightVec;
1254 tcpWeightVec.resize(tcpWeightVec.rows() + size);
1255
1256 if (oldVec.rows() > 0)
1257 {
1258 tcpWeightVec.head(oldVec.rows()) = oldVec;
1259 }
1260
1261 Eigen::VectorXf tmptcpWeightVec(size);
1262 tmptcpWeightVec.setOnes();
1263 tcpWeightVec.tail(size) = tmptcpWeightVec;
1264 }
1265 }
1266
1267 if (invJacobian.cols() == tcpWeightVec.rows())
1268 {
1269
1270 Eigen::MatrixXf weightMat(tcpWeightVec.rows(), tcpWeightVec.rows());
1271 weightMat.setIdentity();
1272 weightMat.diagonal() = tcpWeightVec;
1273 // ARMARX_DEBUG << /*deactivateSpam(1) <<*/ "tcpWeightVec:\n" << tcpWeightVec;
1274 // ARMARX_DEBUG << /*deactivateSpam(1) << */"InvJac Before:\n" << invJacobian;
1275 invJacobian = invJacobian * weightMat;
1276 ARMARX_DEBUG << /*deactivateSpam(1) <<*/ "InvJac after:\n" << invJacobian;
1277 }
1278 else
1279 {
1281 << "Wrong dimension of tcp weights: " << tcpWeightVec.rows()
1282 << ", but should be: " << invJacobian.cols();
1283 }
1284 }
1285
1286 float
1288 {
1289 float result = 0.0f;
1290 float positionOrientationRatio = 3.f / 180.f * M_PI;
1291
1292 for (size_t i = 0; i < tcp_set.size(); i++)
1293 {
1294 SceneObjectPtr tcp = tcp_set[i];
1295 result +=
1296 getWeightedErrorPosition(tcp) + getErrorRotation(tcp) * positionOrientationRatio;
1297 }
1298
1299 return result;
1300 }
1301
1302 float
1304 {
1305 if (modes[tcp] == IKSolver::Orientation)
1306 {
1307 return 0.0f; // ignoring position
1308 }
1309
1310 if (!tcp)
1311 {
1312 tcp = getDefaultTCP();
1313 }
1314
1315 Vector3f position = targets[tcp].block(0, 3, 3, 1) - tcp->getGlobalPose().block(0, 3, 3, 1);
1316 //cout << "Error Position <" << tcp->getName() << ">: " << position.norm() << std::endl;
1317 //cout << boost::format("Error Position < %1% >: %2%") % tcp->getName() % position.norm() << std::endl;
1318 float result = 0.0f;
1319 Eigen::VectorXf tcpWeight(3);
1320
1321 if (tcpWeights.find(tcp) != tcpWeights.end())
1322 {
1323 tcpWeight = tcpWeights.find(tcp)->second;
1324 }
1325 else
1326 {
1327 tcpWeight.setOnes();
1328 }
1329
1330 int weightIndex = 0;
1331
1332 if (modes[tcp] & IKSolver::X)
1333 {
1334 // ARMARX_DEBUG << "error x: " << position(0)*tcpWeight(weightIndex);
1335 result += position(0) * position(0) * tcpWeight(weightIndex++);
1336 }
1337
1338 if (modes[tcp] & IKSolver::Y)
1339 {
1340 // ARMARX_DEBUG << "error y: " << position(1)*tcpWeight(weightIndex);
1341 result += position(1) * position(1) * tcpWeight(weightIndex++);
1342 }
1343
1344 if (modes[tcp] & IKSolver::Z)
1345 {
1346 // ARMARX_DEBUG << "error z: " << position(2)*tcpWeight(weightIndex);
1347 result += position(2) * position(2) * tcpWeight(weightIndex++);
1348 }
1349
1350 return sqrtf(result);
1351 }
1352
1353 bool
1354 EDifferentialIK::adjustDOFWeightsToJointLimits(const VectorXf& plannedJointDeltas)
1355 {
1356 if (dofWeights.rows() != plannedJointDeltas.rows())
1357 {
1358 dofWeights.resize(plannedJointDeltas.rows());
1359 dofWeights.setOnes();
1360 }
1361
1362 bool result = false;
1363
1364 for (unsigned int i = 0; i < nodes.size(); i++)
1365 {
1366 float angle = nodes[i]->getJointValue() + plannedJointDeltas[i] * 0.1;
1367
1368 if (angle > nodes[i]->getJointLimitHi() || angle < nodes[i]->getJointLimitLo())
1369 {
1370 ARMARX_VERBOSE << deactivateSpam(3) << nodes[i]->getName()
1371 << " joint deactivated because of joint limit";
1372 dofWeights(i) = 0;
1373 result = true;
1374 }
1375 }
1376
1377 return result;
1378 }
1379
1380
1381} // namespace armarx
1382
1383void
1385 Ice::Long timestamp,
1386 bool,
1387 const Ice::Current&)
1388{
1389}
1390
1391void
1392armarx::TCPControlUnit::reportJointAngles(const NameValueMap& jointAngles,
1393 Ice::Long timestamp,
1394 bool,
1395 const Ice::Current&)
1396{
1397 std::unique_lock lock(reportMutex);
1398 FramedPoseBaseMap tcpPoses;
1399 std::string rootFrame = localReportRobot->getRootNode()->getName();
1400 auto it = jointAngles.find("timestamp");
1401 if (it == jointAngles.end())
1402 {
1403 localReportRobot->setJointValues(jointAngles);
1404 }
1405 else
1406 {
1407 NameValueMap tempMap = jointAngles;
1408 tempMap.erase("timestamp");
1409 localReportRobot->setJointValues(tempMap);
1410 }
1411 for (unsigned int i = 0; i < nodesToReport.size(); i++)
1412 {
1413 RobotNodePtr& node = nodesToReport.at(i);
1414 const std::string& tcpName = node->getName();
1415 const Eigen::Matrix4f& currentPose = node->getPoseInRootFrame();
1416 tcpPoses[tcpName] = new FramedPose(currentPose, rootFrame, robotName);
1417 }
1418
1419 listener->reportTCPPose(tcpPoses);
1420}
1421
1422void
1424 Ice::Long timestamp,
1425 bool,
1426 const Ice::Current&)
1427{
1428 if ((TimeUtil::GetTime() - lastTopicReportTime).toMilliSeconds() < cycleTime)
1429 {
1430 return;
1431 }
1432
1433 lastTopicReportTime = TimeUtil::GetTime();
1434 std::unique_lock lock(reportMutex);
1435
1436 if (!localVelReportRobot)
1437 {
1438 localVelReportRobot = localReportRobot->clone(robotName);
1439 }
1440
1441 // ARMARX_DEBUG << jointVel; FramedPoseBaseMap tcpPoses;
1442 FramedDirectionMap tcpTranslationVelocities;
1443 FramedDirectionMap tcpOrientationVelocities;
1444 std::string rootFrame = localReportRobot->getRootNode()->getName();
1445 NameValueMap tempJointAngles = localReportRobot->getConfig()->getRobotNodeJointValueMap();
1446 FramedPoseBaseMap tcpPoses;
1447
1448 for (unsigned int i = 0; i < nodesToReport.size(); i++)
1449 {
1450 RobotNodePtr node = nodesToReport.at(i);
1451 const std::string& tcpName = node->getName();
1452 const Eigen::Matrix4f& currentPose = node->getPoseInRootFrame();
1453 tcpPoses[tcpName] = new FramedPose(currentPose, rootFrame, robotName);
1454 }
1455
1456 double tDelta = 0.001;
1457
1458 for (NameValueMap::iterator it = tempJointAngles.begin(); it != tempJointAngles.end(); it++)
1459 {
1460 NameValueMap::const_iterator itSrc = jointVel.find(it->first);
1461 if (itSrc != jointVel.end())
1462 {
1463 if (itSrc->first == "timestamp")
1464 {
1465 continue;
1466 }
1467 it->second += itSrc->second * tDelta;
1468 }
1469 }
1470
1471 localVelReportRobot->setJointValues(tempJointAngles);
1472
1473 for (unsigned int i = 0; i < nodesToReport.size(); i++)
1474 {
1475 RobotNodePtr node = localVelReportRobot->getRobotNode(nodesToReport.at(i)->getName());
1476 const std::string& tcpName = node->getName();
1477 const Eigen::Matrix4f& currentPose = node->getPoseInRootFrame();
1478
1479
1480 FramedPosePtr lastPose = FramedPosePtr::dynamicCast(tcpPoses[tcpName]);
1481
1482 tcpTranslationVelocities[tcpName] = new FramedDirection(
1483 (currentPose.block(0, 3, 3, 1) - lastPose->toEigen().block(0, 3, 3, 1)) / tDelta,
1484 rootFrame,
1485 localReportRobot->getName());
1486
1487 const Eigen::Matrix4f mat = currentPose * lastPose->toEigen().inverse();
1488 // const Eigen::Matrix3f rot = currentPose.block(0,0,3,3) * lastPose->toEigen().block(0,0,3,3).inverse();
1489 Eigen::Vector3f rpy;
1490 VirtualRobot::MathTools::eigen4f2rpy(mat, rpy);
1491 // Eigen::AngleAxisf orient(rot.block<3,3>(0,0));
1492
1493 tcpOrientationVelocities[tcpName] = new FramedDirection(rpy / tDelta, rootFrame, robotName);
1494 }
1495
1496 listener->reportTCPVelocities(tcpTranslationVelocities, tcpOrientationVelocities);
1497}
1498
1499void
1501 Ice::Long timestamp,
1502 bool,
1503 const Ice::Current&)
1504{
1505}
1506
1507void
1508armarx::TCPControlUnit::reportJointAccelerations(const armarx::NameValueMap& jointAccelerations,
1509 Ice::Long timestamp,
1510 bool aValueChanged,
1511 const Ice::Current& c)
1512{
1513}
1514
1515void
1517 Ice::Long timestamp,
1518 bool,
1519 const Ice::Current&)
1520{
1521}
1522
1523void
1525 Ice::Long timestamp,
1526 bool,
1527 const Ice::Current&)
1528{
1529}
1530
1531void
1533 Ice::Long timestamp,
1534 bool,
1535 const Ice::Current&)
1536{
1537}
std::string timestamp()
uint8_t index
#define M_PI
Definition MathTools.h:17
#define VAROUT(x)
constexpr T c
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition Component.cpp:90
Property< PropertyType > getProperty(const std::string &name)
Eigen::VectorXf computeStep(float stepSize) override
std::map< VirtualRobot::SceneObjectPtr, Eigen::VectorXf > tcpWeights
void setGoal(const Eigen::Matrix4f &goal, VirtualRobot::RobotNodePtr tcp, VirtualRobot::IKSolver::CartesianSelection mode, float tolerancePosition, float toleranceRotation, Eigen::VectorXf tcpWeight)
void applyDOFWeightsToJacobian(Eigen::MatrixXf &Jacobian)
Eigen::VectorXf tcpWeightVec
bool solveIK(float stepSize=1, float minChange=0.01f, int maxSteps=50, bool useAlternativeOnFail=false)
void applyTCPWeights(VirtualRobot::RobotNodePtr tcp, Eigen::MatrixXf &partJacobian)
bool adjustDOFWeightsToJointLimits(const Eigen::VectorXf &plannedJointDeltas)
Eigen::VectorXf computeStepIndependently(float stepSize)
float getWeightedErrorPosition(VirtualRobot::SceneObjectPtr tcp)
Eigen::MatrixXf calcFullJacobian()
void setRefFrame(VirtualRobot::RobotNodePtr coordSystem)
EDifferentialIK(VirtualRobot::RobotNodeSetPtr rns, VirtualRobot::RobotNodePtr coordSystem=VirtualRobot::RobotNodePtr(), VirtualRobot::JacobiProvider::InverseJacobiMethod invJacMethod=eSVD)
bool computeSteps(float stepSize=1.f, float mininumChange=0.01f, int maxNStep=50) override
Eigen::VectorXf dofWeights
void setDOFWeights(Eigen::VectorXf dofWeights)
FramedDirection is a 3 dimensional direction vector with a reference frame.
Definition FramedPose.h:87
static FramedDirectionPtr ChangeFrame(const VirtualRobot::RobotConstPtr &robot, const FramedDirection &framedVec, const std::string &newFrame)
The FramedPose class.
Definition FramedPose.h:281
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
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.
void usingTopic(const std::string &name, bool orderedPublishing=false)
Registers a proxy for subscription after initialization.
std::string getName() const
Retrieve name of object.
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
int getState() const
Retrieve current state of the ManagedIceObject.
The periodic task executes one thread method repeatedly using the time period specified in the constr...
VirtualRobot::RobotPtr createLocalClone()
Clones the structure of this remote robot to a local instance.
static bool synchronizeLocalClone(VirtualRobot::RobotPtr robot, RobotStateComponentInterfacePrx robotStatePrx)
void onInitComponent() override
Pure virtual hook for the subclass.
static Eigen::VectorXf CalcNullspaceJointDeltas(const Eigen::VectorXf &desiredJointDeltas, const Eigen::MatrixXf &jacobian, const Eigen::MatrixXf &jacobianInverse)
void start(const Ice::Current &c=Ice::emptyCurrent) override
Does not do anything at the moment.
void release(const Ice::Current &c=Ice::emptyCurrent) override
Releases and stops the recalculation and updating of joint velocities.
UnitExecutionState getExecutionState(const Ice::Current &c=Ice::emptyCurrent) override
void reportJointMotorTemperatures(const NameValueMap &, Ice::Long timestamp, bool, const Ice::Current &) override
void reportControlModeChanged(const NameControlModeMap &, Ice::Long timestamp, bool, const Ice::Current &) override
void onDisconnectComponent() override
Hook for subclass.
static Eigen::VectorXf CalcJointLimitAvoidanceDeltas(VirtualRobot::RobotNodeSetPtr robotNodeSet, const Eigen::MatrixXf &jacobian, const Eigen::MatrixXf &jacobianInverse, Eigen::VectorXf desiredJointValues=Eigen::VectorXf())
void init(const Ice::Current &c=Ice::emptyCurrent) override
Does not do anything at the moment.
void setCycleTime(Ice::Int milliseconds, const Ice::Current &c=Ice::emptyCurrent) override
Sets the cycle time with which the joint velocities are recalculated.
void reportJointTorques(const NameValueMap &, Ice::Long timestamp, bool, const Ice::Current &) override
void stop(const Ice::Current &c=Ice::emptyCurrent) override
Does not do anything at the moment.
void reportJointAngles(const NameValueMap &jointAngles, Ice::Long timestamp, bool, const Ice::Current &) override
void setTCPVelocity(const std::string &nodeSetName, const std::string &tcpName, const ::armarx::FramedDirectionBasePtr &translationVelocity, const ::armarx::FramedDirectionBasePtr &orientationVelocityRPY, const Ice::Current &c=Ice::emptyCurrent) override
Sets the cartesian velocity of a node in a nodeset for translation and/or orientation.
bool isRequested(const Ice::Current &c=Ice::emptyCurrent) override
void onConnectComponent() override
Pure virtual hook for the subclass.
void request(const Ice::Current &c=Ice::emptyCurrent) override
Triggers the calculation loop for using cartesian velocity.
void reportJointAccelerations(const NameValueMap &jointAccelerations, Ice::Long timestamp, bool aValueChanged, const Ice::Current &c) override
PropertyDefinitionsPtr createPropertyDefinitions() override
void onExitComponent() override
Hook for subclass.
void reportJointCurrents(const NameValueMap &, Ice::Long timestamp, bool, const Ice::Current &) override
void reportJointStatuses(const NameStatusMap &, Ice::Long timestamp, bool, const Ice::Current &) override
void reportJointVelocities(const NameValueMap &jointVel, Ice::Long timestamp, bool, const Ice::Current &) override
static IceUtil::Time GetTime(TimeMode timeMode=TimeMode::VirtualTime)
Get the current time.
Definition TimeUtil.cpp:42
Brief description of class targets.
Definition targets.h:39
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#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_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:196
#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
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
#define ARMARX_WARNING_S
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:213
std::string const GlobalFrame
Variable of the global coordinate system.
Definition FramedPose.h:65
std::shared_ptr< class Robot > RobotPtr
Definition Bus.h:19
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
IceInternal::Handle< FramedPose > FramedPosePtr
Definition FramedPose.h:272
::std::map<::std::string, ::armarx::FramedPoseBasePtr > FramedPoseBaseMap
double angle(const Point &a, const Point &b, const Point &c)
Definition point.hpp:109