ReachOutToHumanPose.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 RobotSkillTemplates::HandOverGroup
17 * @author Mirko Waechter ( mirko dot waechter 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
23#include "ReachOutToHumanPose.h"
24#include <VirtualRobot/MathTools.h>
25#include <VirtualRobot/RobotNodeSet.h>
26
28
30
31//#include <ArmarXCore/core/time/TimeUtil.h>
35
39#include <RobotAPI/interface/units/RobotUnit/NJointCartesianVelocityControllerWithRamp.h>
46
47
48using namespace armarx;
49using namespace visionx;
50using namespace HandOverGroup;
51
52// DO NOT EDIT NEXT LINE
53ReachOutToHumanPose::SubClassRegistry
54 ReachOutToHumanPose::Registry(ReachOutToHumanPose::GetName(),
56
57#define ENABLE_DEBUG_DRAWER 0
58
59void
61{
62 // put your user code for the enter-point here
63 // execution time should be short (<100ms)
64 // ManagedIceObjectPtr obj = ManagedIceObjectPtr::dynamicCast(getContext());
65 // obj->getIceManager()->subscribeTopic()
66}
67
68void
70{
71 viz::ScopedClient arviz = viz::Client::createFromTopic("ReachOutToHumanPose", getArvizTopic());
72 arviz.commit({arviz.layer("HandOverState")}); // Clear layer.
73
75 getContext<HandOverGroupStatechartContextExtension>();
76 c->getOpenPoseEstimation()->start3DPoseEstimation();
77
79 CycleUtil cycle(10);
80 filters::PoseMedianFilter lwristFilter(in.getPoseMedianFilterSize()),
81 rwristFilter(in.getPoseMedianFilterSize());
82 filters::PoseAverageFilter headIKTargetFilter(50);
83 std::vector<filters::AverageFilter> targetPositionFilter(3), targetVelocityFilter(3);
84 for (auto& filter : targetPositionFilter)
85 {
86 filter.windowFilterSize = in.getTargetPositionAverageFilterSize();
87 }
88 for (auto& filter : targetVelocityFilter)
89 {
90 filter.windowFilterSize = in.getTargetPositionAverageFilterSize();
91 }
92 float maxTCPVelocity = in.getMaxTCPVelocity();
93 float considerForceDistanceThreshold = in.getConsiderForceDistanceThreshold();
94 auto robot = getLocalRobot();
95
96 {
97 auto node = robot->getRobotNode("ArmR3_Sho2");
98 node->setJointLimits(node->getJointLimitLow(), VirtualRobot::MathTools::deg2rad(90));
99 }
100 {
101 auto node = robot->getRobotNode("ArmR5_Elb1");
102 node->setJointLimits(VirtualRobot::MathTools::deg2rad(5), node->getJointLimitHigh());
103 }
104 {
105 auto node = robot->getRobotNode("ArmR1_Cla1");
106 node->setJointLimits(VirtualRobot::MathTools::deg2rad(-45),
107 VirtualRobot::MathTools::deg2rad(45));
108 }
109
110 {
111 auto node = robot->getRobotNode("ArmL3_Sho2");
112 node->setJointLimits(node->getJointLimitLow(), VirtualRobot::MathTools::deg2rad(90));
113 }
114 {
115 auto node = robot->getRobotNode("ArmL5_Elb1");
116 node->setJointLimits(VirtualRobot::MathTools::deg2rad(5), node->getJointLimitHigh());
117 }
118 {
119 auto node = robot->getRobotNode("ArmL1_Cla1");
120 node->setJointLimits(VirtualRobot::MathTools::deg2rad(-45),
121 VirtualRobot::MathTools::deg2rad(45));
122 }
123
124 auto cameraRobot = getLocalRobot(); // receives new copy
125 ARMARX_CHECK_EXPRESSION(robot.get() != cameraRobot.get());
126 filters::AverageFilter forceMagnitudeAvgFilter;
127 forceMagnitudeAvgFilter.windowFilterSize = 10;
128
129 getHeadIKUnit()->request();
130
131 // look straight ahead
132 ARMARX_INFO << "InitialHeadIKTarget(): " << in.getInitialHeadIKTarget()->output();
133 getHeadIKUnit()->setHeadTarget(in.getHeadIKNodeSet(), in.getInitialHeadIKTarget());
134 TimeUtil::MSSleep(1000);
135
136 auto kinematicChainName = in.getKinematicChainName();
137 MultiDimPIDController pid(in.getKp(), 0, 0);
138 IceUtil::Time lastTimestamp = armarx::TimeUtil::GetTime();
140 auto nodeset = robot->getRobotNodeSet(kinematicChainName);
141 auto tcp = nodeset->getTCP();
142 auto kinematicRootName = nodeset->getKinematicRoot()->getName();
143
144 ARMARX_INFO << VAROUT(kinematicRootName)
145 << " position in root: " << nodeset->getKinematicRoot()->getPositionInRootFrame();
146 FramedDirectionPtr targetVelocity;
147 DatafieldRefPtr forceTorqueRef = DatafieldRefPtr::dynamicCast(
148 getForceTorqueObserver()->getDataFieldRef(new DataFieldIdentifier(
149 getForceTorqueObserver()->getObserverName(), in.getFTSensorName(), "forces")));
150 ARMARX_CHECK_EXPRESSION(forceTorqueRef);
151 DatafieldRefPtr nulledForceTorqueRef;
152 NJointCartesianVelocityControllerWithRampConfigPtr ctrlCfg =
153 new NJointCartesianVelocityControllerWithRampConfig();
154 ctrlCfg->KpJointLimitAvoidance = 0;
155 ctrlCfg->jointLimitAvoidanceScale = 1;
156 ctrlCfg->mode = CartesianSelectionMode::eAll;
157 ctrlCfg->nodeSetName = kinematicChainName;
158 ctrlCfg->tcpName = tcp->getName();
159 ctrlCfg->maxNullspaceAcceleration = 2;
160 ctrlCfg->maxPositionAcceleration = in.getTCPAcceleration();
161 ctrlCfg->maxOrientationAcceleration = 1;
162
163 CartesianPositionController posController(tcp);
164 posController.maxOriVel = in.getMaxOrientationVelocity();
165 posController.maxPosVel = in.getMaxTCPVelocity();
166 posController.KpOri = in.getKpOrientation();
167 posController.KpPos = in.getKp();
168
169 auto ctrlName = "ReachOutToHumanTCPCtrl";
170 TIMING_START(NJointCtrlCreation);
171 ARMARX_INFO << deactivateSpam(1) << "Getting old controller";
172 if (auto oldCtrl = getRobotUnit()->getNJointController(ctrlName))
173 {
174 ARMARX_INFO << deactivateSpam(1) << "got old controller";
175 while (oldCtrl->isControllerActive())
176 {
177 oldCtrl->deactivateController();
178 ARMARX_INFO << deactivateSpam(1) << "Waiting for old controller to be deactivated";
179 usleep(30000);
180 }
181 ARMARX_INFO << deactivateSpam(1) << "deleting old controller";
183 usleep(100000);
184 }
185 ARMARX_INFO << deactivateSpam(1) << "Getting new controller";
186 auto baseCtrl = getRobotUnit()->createNJointController(
187 "NJointCartesianVelocityControllerWithRamp", ctrlName, ctrlCfg);
188 ARMARX_CHECK_EXPRESSION(baseCtrl);
189 NJointCartesianVelocityControllerWithRampInterfacePrx ctrl =
190 NJointCartesianVelocityControllerWithRampInterfacePrx::checkedCast(baseCtrl);
191 TIMING_END(NJointCtrlCreation);
192 ARMARX_CHECK_EXPRESSION(ctrl) << baseCtrl->ice_ids();
193 ctrl->activateController();
194
195 auto targetOrientation = in.getHandOrientation();
196 IceUtil::Time startTime = TimeUtil::GetTime();
197
198 RemoteRobot::synchronizeLocalClone(robot, getRobotStateComponent());
199
200 const Eigen::Vector3f offset{0, 0, 300};
201 Eigen::Vector3f idlePosi = tcp->getPositionInRootFrame() + offset;
202 FramedPositionPtr idlePosition =
203 new FramedPosition(idlePosi, robot->getRootNode()->getName(), robot->getName());
204 // in.getIdlePosition();
205
206 bool drawDebugInfos = in.getDrawDebugInfos();
207 FramedPositionPtr lastIKTarget;
208 while (!isRunningTaskStopped()) // stop run function if returning true
209 {
210 viz::Layer vizLayer = arviz.layer("HandOverState");
211
212 auto now = armarx::TimeUtil::GetTime();
213 auto timeSinceSinceStart = now - startTime;
214 IceUtil::Time duration = now - lastTimestamp;
215 lastTimestamp = now;
216
217 c->getImageSourceSelectionTopic()->setImageSource("OpenPoseEstimationResult", 5000);
218
219 // do your calculations
220 std::vector<Keypoint3DMap> keypointList;
221 IceUtil::Time timestamp;
222 std::tie(timestamp, keypointList) = c->getPoseData()->getLatestData();
223 RemoteRobot::synchronizeLocalClone(robot, getRobotStateComponent());
225 cameraRobot, getRobotStateComponent(), timestamp.toMicroSeconds());
226
227 Keypoint3DMap poseData = getClosestPerson(keypointList);
228 int validKeypoints = 0;
229 for (auto& pair : poseData)
230 {
231 if (isKeypointValid(pair.second))
232 {
233 validKeypoints++;
234 }
235 }
236
237
238 Keypoint3D rwrist = poseData["RWrist"];
239 Vector3Ptr rwristPosition = new Vector3(rwrist.x, rwrist.y, rwrist.z);
240 bool validTarget = false;
241 if (isKeypointValid(rwrist))
242 {
243 rwristFilter.update(now.toMicroSeconds(), new Variant(rwristPosition));
244 }
245 auto tmp = rwristFilter.getValue();
246 if (tmp)
247 {
248 Vector3Ptr filteredRWristPosition = VariantPtr::dynamicCast(tmp)->get<Vector3>();
249 ARMARX_CHECK_EXPRESSION(filteredRWristPosition);
250 FramedPositionPtr globalrWristPosition =
252 filteredRWristPosition->toEigen(), in.getCameraFrameName(), robot->getName())
253 .toGlobal(robot);
254 // ARMARX_INFO << deactivateSpam(1) << VAROUT(*globalrWristPosition);
255 if (drawDebugInfos)
256 {
257#if ENABLE_DEBUG_DRAWER
258 this->getDebugDrawerTopic()->setSphereVisu(
259 "HandOverState",
260 "rwrist",
261 globalrWristPosition,
262 DrawColor{1.0f, 0.0f, 0.0f, rwrist.confidence},
263 30);
264#else
265 vizLayer.add(viz::Sphere("rwrist")
266 .position(globalrWristPosition->toEigen())
267 .color(simox::Color::red(255, 255 * rwrist.confidence))
268 .radius(30));
269#endif
270 getDebugObserver()->setDebugChannel(
271 "HandOverState",
272 {
273 {"rwristpoint_z", new Variant(rwristPosition->z)},
274 {"rwristpoint_z_filtered", new Variant(filteredRWristPosition->z)},
275 });
276 }
277
278 rwristPosition = filteredRWristPosition;
279 validTarget = true;
280 }
281 Keypoint3D lwrist = poseData["LWrist"];
282 Vector3Ptr lwristPosition = new Vector3(lwrist.x, lwrist.y, lwrist.z);
283 if (isKeypointValid(lwrist))
284 {
285 lwristFilter.update(now.toMicroSeconds(), new Variant(lwristPosition));
286 }
287 tmp = lwristFilter.getValue();
288 if (tmp)
289 {
290 lwristPosition = VariantPtr::dynamicCast(tmp)->get<Vector3>();
291 ARMARX_CHECK_EXPRESSION(lwristPosition);
292 FramedPositionPtr globallWristPosition =
293 FramedPosition(lwristPosition->toEigen(), in.getCameraFrameName(), robot->getName())
294 .toGlobal(robot);
295 // ARMARX_INFO << deactivateSpam(1) << VAROUT(*globallWristPosition) << VAROUT(robot->getGlobalPose());
296 if (drawDebugInfos)
297 {
298#if ENABLE_DEBUG_DRAWER
299 this->getDebugDrawerTopic()->setSphereVisu(
300 "HandOverState",
301 "lwrist",
302 globallWristPosition,
303 DrawColor{0.0f, 1.0f, 0.0f, lwrist.confidence},
304 30);
305#else
306 vizLayer.add(viz::Sphere("lwrist")
307 .position(globallWristPosition->toEigen())
308 .color(simox::Color::green(255, 255 * lwrist.confidence))
309 .radius(30));
310#endif
311 }
312 validTarget = true;
313 }
314 // ARMARX_INFO << deactivateSpam(1) << "Filtered wrist data";
315 float leftHandDistance = lwristPosition && isKeypointValid(lwrist)
316 ? lwristPosition->toEigen().norm()
317 : std::numeric_limits<float>::max();
318 float rightHandDistance = rwristPosition && isKeypointValid(rwrist)
319 ? rwristPosition->toEigen().norm()
320 : std::numeric_limits<float>::max();
321
322 Vector3Ptr currentHandPosition =
323 leftHandDistance < rightHandDistance ? lwristPosition : rwristPosition;
324
325 if (drawDebugInfos)
326 {
327 getDebugObserver()->setDebugChannel(
328 "ReachOutToHuman",
329 {{"zDiffLShoulder",
330 new Variant(std::abs(poseData["LWrist"].z - poseData["LShoulder"].z))},
331 {"zDiffNeckR", new Variant(std::abs(poseData["RWrist"].z - poseData["Neck"].z))},
332 {"zDiffNeckL", new Variant(std::abs(poseData["LWrist"].z - poseData["Neck"].z))}});
333 }
334
335
336 Eigen::Vector3f headIkTarget = getHeadIKTarget(poseData);
337 FramedPositionPtr globalHeadIkTarget =
338 FramedPosition(headIkTarget, in.getCameraFrameName(), robot->getName())
339 .toGlobal(cameraRobot);
340 globalHeadIkTarget->z = std::max(in.getMinimumGazeZPosition(), globalHeadIkTarget->z);
341
342 if (validKeypoints > 3 && !in.getHeadIKNodeSet().empty() && headIkTarget.norm() > 0)
343 {
344 if (drawDebugInfos)
345 {
346#if ENABLE_DEBUG_DRAWER
347 this->getDebugDrawerTopic()->setSphereVisu("HandOverState",
348 "Median",
349 globalHeadIkTarget,
350 DrawColor{1.0f, 1.0f, 0.0f, 1.0f},
351 50);
352#else
353 vizLayer.add(viz::Sphere("Median")
354 .position(globalHeadIkTarget->toEigen())
355 .color(simox::Color::yellow())
356 .radius(50));
357#endif
358 }
359 headIKTargetFilter.update(now.toMicroSeconds(), new Variant(globalHeadIkTarget));
360 auto tmp = headIKTargetFilter.getValue();
362 FramedPositionPtr globalFilteredMedianKeypoint =
363 VariantPtr::dynamicCast(tmp)->get<FramedPosition>();
364 ARMARX_CHECK_EXPRESSION(globalFilteredMedianKeypoint);
365 if ((TimeUtil::GetTime() - startTime).toSecondsDouble() > 1.3)
366 {
367 if (!lastIKTarget ||
368 (lastIKTarget->toEigen() - globalFilteredMedianKeypoint->toEigen()).norm() >
369 100)
370 {
371 getHeadIKUnit()->setHeadTarget(in.getHeadIKNodeSet(),
372 globalFilteredMedianKeypoint);
373 lastIKTarget = globalFilteredMedianKeypoint;
374 // ARMARX_INFO << deactivateSpam(1) << "HeadIK Target: " << *globalFilteredMedianKeypoint;
375 }
376 }
377 }
378 else
379 {
380#if ENABLE_DEBUG_DRAWER
381 this->getDebugDrawerTopic()->removeSphereVisu("HandOverState", "Median");
382#else
383 // Don't add Median to the layer.
384#endif
385 }
386
387
388 float currentHumanReachDistance =
389 headIkTarget.norm() == 0 && currentHandPosition->toEigen().norm() > 100
390 ? 0
391 : std::abs((currentHandPosition->toEigen() - headIkTarget)(2));
392 bool humanIsReachingOut = currentHumanReachDistance > in.getHumanMinimumReachOutDistance();
393 // ARMARX_INFO << deactivateSpam(1) << VAROUT(currentHumanReachDistance) << VAROUT(humanIsReachingOut);
394 Eigen::Vector3f currentTargetVec = currentHandPosition->toEigen();
395 for (int i = 0; i < 3; ++i)
396 {
397 targetPositionFilter.at(i).update(now.toMicroSeconds(),
398 new Variant(currentTargetVec(i)));
399 }
400 Eigen::Vector3f currentFilteredTargetPositionVec;
401 for (int i = 0; i < 3; ++i)
402 {
403 currentFilteredTargetPositionVec(i) = targetPositionFilter.at(i).getValue()->getFloat();
404 }
405 // ARMARX_INFO << deactivateSpam(1) << "Filtered target position ";
406 FramedPositionPtr targetPositioninRootFrame = new FramedPosition(
407 currentFilteredTargetPositionVec, in.getCameraFrameName(), cameraRobot->getName());
408 targetPositioninRootFrame->changeFrame(robot, robot->getRootNode()->getName());
409
410 // FramedPositionPtr localFramedPosition;
412 // float currentReachDistance = tcp->getTransformationFrom(nodeset->getKinematicRoot()).block<3,1>(0,3).norm();
413 FramedPositionPtr targetInKinematicRootFrame =
414 new FramedPosition(*targetPositioninRootFrame);
415 targetInKinematicRootFrame->changeFrame(robot, kinematicRootName);
416 float reachDistanceToTarget = targetInKinematicRootFrame->toEigen().norm();
417 ARMARX_INFO << deactivateSpam(1) << VAROUT(reachDistanceToTarget);
418 getDebugObserver()->setDebugDatafield(
419 "ReachOutToHuman", "reachDistanceToTarget", new Variant(reachDistanceToTarget));
420 float reachDistanceToTargetClamped = reachDistanceToTarget;
421 if (reachDistanceToTarget > in.getDistanceThresholdSoft() &&
422 reachDistanceToTarget < in.getDistanceThreshold())
423 {
424 Eigen::Vector3f targetPositioninKinematicRootFrameClamped =
425 targetInKinematicRootFrame->toEigen().normalized() * in.getDistanceThresholdSoft();
426 targetPositioninRootFrame =
427 new FramedPosition(targetPositioninKinematicRootFrameClamped,
428 targetInKinematicRootFrame->frame,
429 targetInKinematicRootFrame->agent);
430 targetPositioninRootFrame->changeFrame(robot, robot->getRootNode()->getName());
431 reachDistanceToTargetClamped = targetPositioninKinematicRootFrameClamped.norm();
432 }
433 if (drawDebugInfos)
434 {
435 getDebugObserver()->setDebugChannel(
436 "ReachOutToHuman",
437 {{"targetPositioninRootFrameX", new Variant(targetPositioninRootFrame->x)},
438 {"targetPositioninRootFrameY", new Variant(targetPositioninRootFrame->y)},
439 {"targetPositioninRootFrameZ", new Variant(targetPositioninRootFrame->z)},
440 {"targetPositioninRootNorm",
441 new Variant(targetPositioninRootFrame->toEigen().norm())},
442 {"reachDistanceToTargetClamped", new Variant(reachDistanceToTargetClamped)}});
443 }
444
445 float distanceToTarget =
446 (tcp->getPositionInRootFrame() - targetPositioninRootFrame->toEigen()).norm();
447
448 bool returnToIdlePose =
449 reachDistanceToTarget > in.getDistanceThreshold() || !validTarget ||
450 !humanIsReachingOut || validKeypoints < 5 ||
451 timeSinceSinceStart.toMilliSeconds() < in.getMinWaitBeforeReachTime();
452 if (returnToIdlePose)
453 {
454 targetPositioninRootFrame = in.getIdlePosition();
455 }
456 else
457 {
458 idlePosition = in.getIdlePosition();
459 targetPositioninRootFrame->y -= in.getTargetYOffset();
460 targetPositioninRootFrame->z += in.getTargetZOffset();
461 }
462 // ARMARX_CHECK_EXPRESSION(lwristPosition);
463 // ARMARX_CHECK_EXPRESSION(lwristPosition);
464 ARMARX_CHECK_EXPRESSION(lwristPosition);
465
466 FramedPositionPtr globalTargetPosition = targetPositioninRootFrame->toGlobal(robot);
467 if (drawDebugInfos)
468 {
469#if ENABLE_DEBUG_DRAWER
470 getDebugDrawerTopic()->setSphereVisu("HandOverState",
471 "TargetPosition",
472 globalTargetPosition,
473 DrawColor{0.0f, 1.0f, 1.0f, 1.0},
474 30);
475 getDebugDrawerTopic()->setLineVisu("HandOverState",
476 "ReachOutLine",
477 globalTargetPosition,
478 globalHeadIkTarget,
479 5,
480 humanIsReachingOut ? DrawColor{0.0f, 1.0f, 0.0f, 1.0}
481 : DrawColor{1.0f, 0, 0, 1.0});
482#else
483 vizLayer.add(viz::Sphere("TargetPosition")
484 .position(globalTargetPosition->toEigen())
485 .color(simox::Color::cyan())
486 .radius(30));
487 vizLayer.add(
488 viz::Cylinder("ReachOutLine")
489 .fromTo(globalTargetPosition->toEigen(), globalHeadIkTarget->toEigen())
490 .radius(5)
491 .color(humanIsReachingOut ? simox::Color::green() : simox::Color::red()));
492#endif
493 }
494
495
496 pid.update(duration.toMicroSecondsDouble(),
497 tcp->getPositionInRootFrame(),
498 targetPositioninRootFrame->toEigen());
499 Eigen::Vector3f targetVelocityVec = pid.getControlValue();
500 if (targetVelocityVec.norm() > maxTCPVelocity)
501 {
502 targetVelocityVec = targetVelocityVec.normalized() * maxTCPVelocity;
503 }
504 if (distanceToTarget < considerForceDistanceThreshold)
505 {
506 targetVelocityVec = Eigen::Vector3f::Zero();
507 if (!nulledForceTorqueRef)
508 {
509 nulledForceTorqueRef = DatafieldRefPtr::dynamicCast(
510 getForceTorqueObserver()->createNulledDatafield(forceTorqueRef));
511 }
512 FramedDirectionPtr nulledFT =
513 nulledForceTorqueRef->getDataField()->get<FramedDirection>();
514 float forceMagnitude = nulledFT->toEigen().norm();
515 if (drawDebugInfos)
516 {
517 getDebugObserver()->setDebugChannel(
518 "ReachOutToHuman",
519 {{"ForceX", new Variant(nulledFT->x)},
520 {"ForceZ", new Variant(nulledFT->z)},
521 {"ForceMagnitude", new Variant(forceMagnitude)}});
522 }
523 forceMagnitudeAvgFilter.update(now.toMicroSeconds(), new Variant(forceMagnitude));
524 float forceMagnitudeFiltered = forceMagnitudeAvgFilter.getValue()->getFloat();
525 if (drawDebugInfos)
526 {
527 getDebugObserver()->setDebugDatafield("ReachOutToHuman",
528 "forceMagnitudeFiltered",
529 new Variant(forceMagnitudeFiltered));
530 }
531
532 ARMARX_INFO << deactivateSpam(1) << VAROUT(forceMagnitude)
533 << " threshold: " << in.getForceThreshold();
534 if (forceMagnitude > in.getForceThreshold())
535 {
536 ARMARX_IMPORTANT << "ForceThresholdReached: " << forceMagnitude;
537 this->emitForceThresholdReached();
538 break;
539 }
540 }
541 else
542 {
543 nulledForceTorqueRef = nullptr;
544 }
545 // Eigen::Vector3f filteredTargetVelocityVec;
546 // for (int i = 0; i < 3; ++i)
547 // {
548 // targetVelocityFilter.at(i).update(now.toMicroSeconds(), new Variant(targetVelocityVec(i)));
549 // filteredTargetVelocityVec(i) = targetVelocityFilter.at(i).getValue()->getFloat();
550 // }
551 // ARMARX_INFO << deactivateSpam(1) << VAROUT(*targetPositioninRootFrame) << VAROUT(*lwristPosition) << VAROUT(*rwristPosition);
552 // ARMARX_INFO << deactivateSpam(1) << VAROUT(distanceToTarget) << VAROUT(targetVelocityVec);
553 // Eigen::AngleAxisf aaOriErr(targetOrientation->toEigenQuaternion() * Eigen::Quaternionf(tcp->getPoseInRootFrame().block<3,3>(0,0)).inverse());
554 // Eigen::Vector3f angleVel = aaOriErr.axis() * VirtualRobot::MathTools::angleModPI(aaOriErr.angle());
555 // angleVel *= in.getKpOrientation();
556
557 Eigen::VectorXf cv = posController.calculate(
558 Pose(targetOrientation->toEigen(), targetPositioninRootFrame->toEigen()).toEigen(),
559 VirtualRobot::IKSolver::All);
560 ctrl->setTargetVelocity(cv(0), cv(1), cv(2), cv(3), cv(4), cv(5));
561
562
563 // targetVelocity = new FramedDirection(filteredTargetVelocityVec, robot->getRootNode()->getName(), robot->getName());
564 // getTcpControlUnit()->setTCPVelocity(kinematicChainName, "", targetVelocity, nullptr);
565
566 // ctrl->setTargetVelocity(targetVelocityVec(0),
567 // targetVelocityVec(1),
568 // targetVelocityVec(2),
569 // angleVel(0), angleVel(1), angleVel(2));
570
571 arviz.commit({vizLayer});
572 cycle.waitForCycleDuration();
573 }
574 ctrl->deactivateAndDeleteController();
575 // c->getOpenPoseEstimation()->stop();
576 // usleep(100000);
577 // c->getOpenPoseEstimation()->stop();
578
579 if (in.isObjectIDSet() && in.getObjectID().find("/") != std::string::npos)
580 {
581 objpose::DetachObjectFromRobotNodeInput input;
582 input.objectID = toIce(armarx::ObjectID(in.getObjectID()));
583 ARMARX_IMPORTANT << "Detaching object '" << input.objectID << "' in ObjectPoseStorage.";
584 objpose::DetachObjectFromRobotNodeOutput result =
585 getObjectPoseStorage()->detachObjectFromRobotNode(input);
586 (void)result;
587 }
588 else if (in.isObjectIDSet())
589 {
590 ARMARX_IMPORTANT << "Not detaching object '" << in.getObjectID()
591 << " because it does not look like an ObjectID.";
592 }
593 else
594 {
596 << "Not detaching object in ObjectPoseStorage because 'ObjectID' is not set.";
597 }
598}
599
600//void ReachOutToHumanPose::onBreak()
601//{
602// // put your user code for the breaking point here
603// // execution time should be short (<100ms)
604//}
605
606void
608{
609 // put your user code for the exit point here
610 // execution time should be short (<100ms)
611#if ENABLE_DEBUG_DRAWER
612 getDebugDrawerTopic()->removeLayer("HandOverState");
613#endif
614 if (in.getStopOpenPoseAfterRun())
615 {
616 ARMARX_INFO << "Stopping OpenPose...";
617 getOpenPoseEstimation()->stop();
618 }
619 // getHeadIKUnit()->release();
620
621 // FramedDirectionPtr targetVelocity = new FramedDirection(Eigen::Vector3f::Zero(), getLocalRobot()->getRootNode()->getName(), getLocalRobot()->getName());
622 // getTcpControlUnit()->setTCPVelocity(in.getKinematicChainName(), "", targetVelocity, targetVelocity);
623}
624
625Eigen::Vector3f
626ReachOutToHumanPose::getHeadIKTarget(const Keypoint3DMap& keypointMap)
627{
628 //LAnkle -- -510.596 -1043.04 3889 0.267718
629 //LEar -- 0 0 0 0
630 //LElbow -- 0 0 0 0
631 //LEye -- 0 0 0 0
632 //LHip -- -657.189 -1591.2 3889 0.0951842
633 //LKnee -- -556.669 -1228.13 3604 0.281559
634 //LShoulder -- 0 0 0 0
635 //LWrist -- 0 0 0 0
636 //Neck -- 0 0 0 0
637 //Nose -- 0 0 0 0
638 //RAnkle -- 0 0 0 0
639 //REar -- 0 0 0 0
640 //RElbow -- 0 0 0 0
641 //REye -- 0 0 0 0
642 //RHip -- 0 0 0 0
643 //RKnee -- 0 0 0 0
644 //RShoulder -- 0 0 0 0
645 //RWrist -- 0 0 0 0
646
647 std::vector<std::pair<std::string, float>> keypointPriorityOrderWithOffset = {
648 {"Neck", 20},
649 {"RShoulder", 20},
650 {"LShoulder", 20},
651 {"Nose", 0},
652 {"RElbow", 300},
653 {"LElbow", 300},
654 {"RWrist", 500},
655 {"LWrist", 500},
656 {"LHip", 600},
657 {"RHip", 600},
658 {"RKnee", 1100},
659 {"LKnee", 1100},
660 };
661 for (auto& pair : keypointPriorityOrderWithOffset)
662 {
663 auto it = keypointMap.find(pair.first);
664 if (it != keypointMap.end() && isKeypointValid(it->second))
665 {
666 ARMARX_INFO << "Selected node for head ik target is: " << it->first
667 << deactivateSpam(3, it->first);
668 Eigen::Vector3f result(it->second.x, it->second.y - pair.second, it->second.z);
669 return result;
670 }
671 }
672
673 return Eigen::Vector3f::Zero();
674}
675
676Eigen::VectorXf
677ReachOutToHumanPose::calculateMedian(const Keypoint3DMap& keypointMap)
678{
679 if (keypointMap.empty())
680 {
681 return Eigen::Vector3f::Zero();
682 }
683 Eigen::MatrixXf keypointPositions(keypointMap.size(), 3);
684 std::vector<std::vector<float>> values(3, Ice::FloatSeq(keypointMap.size(), 0.0));
685 int i = 0;
686 for (auto& pair : keypointMap)
687 {
688 values.at(0).at(i) = pair.second.x;
689 values.at(1).at(i) = pair.second.y;
690 values.at(2).at(i) = pair.second.z;
691 i++;
692 }
693
694 std::sort(values.at(0).begin(), values.at(0).end());
695 std::sort(values.at(1).begin(), values.at(1).end());
696 std::sort(values.at(2).begin(), values.at(2).end());
697
698 size_t center = keypointMap.size() / 2;
699 return Eigen::Vector3f(
700 values.at(0).at(center), values.at(1).at(center), values.at(2).at(center));
701}
702
703Eigen::VectorXf
704ReachOutToHumanPose::calculateCentroid(const Keypoint3DMap& keypointMap)
705{
706 Eigen::MatrixXf keypointPositions(keypointMap.size(), 3);
707 int i = 0;
708 for (auto& pair : keypointMap)
709 {
710 keypointPositions(i, 0) = pair.second.x;
711 keypointPositions(i, 1) = pair.second.y;
712 keypointPositions(i, 2) = pair.second.z;
713 i++;
714 }
715 return keypointPositions.colwise().mean();
716}
717
718Keypoint3DMap
719ReachOutToHumanPose::getClosestPerson(const std::vector<Keypoint3DMap>& trackingData)
720{
721 float minDistance = std::numeric_limits<float>::max();
722 Keypoint3DMap result;
723 for (auto& keypointMap : trackingData)
724 {
725 if (keypointMap.empty())
726 {
727 continue;
728 }
729 int validKeypoints = 0;
730 for (auto& pair : keypointMap)
731 {
732 if (isKeypointValid(pair.second))
733 {
734 validKeypoints++;
735 }
736 }
737
738 float distance = calculateMedian(keypointMap).norm();
740 {
741 minDistance = distance;
742 result = keypointMap;
743 }
744 }
745 return result;
746}
747
748bool
749ReachOutToHumanPose::isKeypointValid(const Keypoint3D& point) const
750{
751 if (point.confidence < in.getMinimumKeypointConfidence())
752 {
753 return false;
754 }
755 //if values directly at the camera -> not valid
756 return Eigen::Vector3f(point.x, point.y, point.z).norm() > 100;
757 // return !(point.x == 0.0f && point.y == 0.0f && point.z == 0.0f);
758}
759
760// DO NOT EDIT NEXT FUNCTION
std::string timestamp()
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition Logging.cpp:75
#define VAROUT(x)
constexpr T c
Eigen::VectorXf calculate(const Eigen::Matrix4f &targetPose, VirtualRobot::IKSolver::CartesianSelection mode) const
This util class helps with keeping a cycle time during a control cycle.
Definition CycleUtil.h:41
IceUtil::Time waitForCycleDuration()
This function will wait (virtual or system time) until the cycle time is reached.
Definition CycleUtil.cpp:53
DataFieldIdentifier provide the basis to identify data field within a distributed ArmarX scenario.
void update(Ice::Long timestamp, const VariantBasePtr &value, const Ice::Current &c=Ice::emptyCurrent) override
Adds the given value to the data map, erases old values if maximum size was reached,...
VariantBasePtr getValue(const Ice::Current &c=Ice::emptyCurrent) const override
Retrieves the current, filtered value.
FramedDirection is a 3 dimensional direction vector with a reference frame.
Definition FramedPose.h:87
The FramedPosition class.
Definition FramedPose.h:158
FramedPositionPtr toGlobal(const SharedRobotInterfacePrx &referenceRobot) const
Eigen::VectorXf calculateMedian(const armarx::Keypoint3DMap &keypointMap)
ReachOutToHumanPose(const XMLStateConstructorParams &stateData)
bool isKeypointValid(const armarx::Keypoint3D &point) const
Eigen::Vector3f getHeadIKTarget(const armarx::Keypoint3DMap &keypointMap)
armarx::Keypoint3DMap getClosestPerson(const std::vector< armarx::Keypoint3DMap > &trackingData)
static XMLStateFactoryBasePtr CreateInstance(XMLStateConstructorParams stateData)
Eigen::VectorXf calculateCentroid(const armarx::Keypoint3DMap &keypointMap)
void update(const double deltaSec, const PIDVectorX &measuredValue, const PIDVectorX &targetValue)
A known object ID of the form "Dataset/ClassName" or "Dataset/ClassName/InstanceName".
Definition ObjectID.h:11
The Pose class.
Definition Pose.h:243
virtual Eigen::Matrix4f toEigen() const
Definition Pose.cpp:334
static bool synchronizeLocalClone(VirtualRobot::RobotPtr robot, RobotStateComponentInterfacePrx robotStatePrx)
static bool synchronizeLocalCloneToTimestamp(VirtualRobot::RobotPtr robot, RobotStateComponentInterfacePrx robotStatePrx, Ice::Long timestamp)
Synchronizes a local robot to a robot state at timestamp.
void deleteNJointController(const std::string &name, const Ice::Current &=Ice::emptyCurrent) override
Queues the given NJointControllerBase for deletion.
NJointControllerInterfacePrx createNJointController(const std::string &className, const std::string &instanceName, const NJointControllerConfigPtr &config, const Ice::Current &=Ice::emptyCurrent) override
Cretes a NJointControllerBase.
static IceUtil::Time GetTime(TimeMode timeMode=TimeMode::VirtualTime)
Get the current time.
Definition TimeUtil.cpp:42
static void MSSleep(int durationMS)
lock the calling thread for a given duration (like usleep(...) but using Timeserver time)
Definition TimeUtil.cpp:100
The Variant class is described here: Variants.
Definition Variant.h:224
The Vector3 class.
Definition Pose.h:113
The AverageFilter class provides a simple filter by calculating the average value of a window for dat...
The MedianFilter class provides an implementation for a median for datafields of type float,...
CommitResult commit(StagedCommit const &commit)
Definition Client.cpp:89
static Client createFromTopic(std::string const &componentName, armarx::viz::Topic::ProxyType const &topic)
Definition Client.cpp:40
DerivedT & color(Color color)
Definition ElementOps.h:218
viz::Client that will delete (clear) committed layers when destroyed.
Layer layer(std::string const &name) const override
#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 TIMING_START(name)
Helper macro to do timing tests.
Definition TimeUtil.h:289
#define TIMING_END(name)
Prints duration.
Definition TimeUtil.h:306
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceInternal::Handle< Vector3 > Vector3Ptr
Definition Pose.h:165
RobotUnit * getRobotUnit(RobotUnitModule::ControllerManagement *cmngr)
MultiDimPIDControllerTemplate<> MultiDimPIDController
IceInternal::Handle< FramedDirection > FramedDirectionPtr
Definition FramedPose.h:84
IceInternal::Handle< DatafieldRef > DatafieldRefPtr
Definition Observer.h:43
IceInternal::Handle< FramedPosition > FramedPositionPtr
Definition FramedPose.h:149
IceInternal::Handle< XMLStateFactoryBase > XMLStateFactoryBasePtr
Definition XMLState.h:64
void toIce(std::map< IceKeyT, IceValueT > &iceMap, const boost::container::flat_map< CppKeyT, CppValueT > &cppMap)
Definition helper.h:35
ArmarX headers.
double distance(const Point &a, const Point &b)
Definition point.hpp:95
Cylinder & radius(float r)
Definition Elements.h:76
void add(ElementT const &element)
Definition Layer.h:31
Sphere & radius(float r)
Definition Elements.h:138