25#include <SimoxUtility/color/Color.h>
26#include <VirtualRobot/MathTools.h>
27#include <VirtualRobot/RobotNodeSet.h>
55 template <
typename NJo
intTaskspaceControllerType>
58 const std::string& nodeSetName,
63 arm->kinematicChainName = nodeSetName;
64 VirtualRobot::RobotNodeSetPtr rtRns =
65 rtGetRobot()->getRobotNodeSet(arm->kinematicChainName);
66 VirtualRobot::RobotNodeSetPtr nonRtRns =
67 nonRtRobotPtr->getRobotNodeSet(arm->kinematicChainName);
70 ARMARX_IMPORTANT <<
"--> Creating Taskspace controller with kinematic chain: "
71 << arm->kinematicChainName <<
" with num of joints: (RT robot) "
72 << rtRns->getSize() <<
", and (non-RT robot) " << nonRtRns->getSize();
74 std::vector<size_t> jointIDTorqueMode;
75 std::vector<size_t> jointIDVelocityMode;
76 arm->jointNames.clear();
77 for (
size_t i = 0; i < rtRns->getSize(); ++i)
79 std::string jointName = rtRns->getNode(i)->getName();
80 arm->jointNames.push_back(jointName);
82 bool foundControlDevice =
false;
84 cfg.jointNameListTorque.begin(), cfg.jointNameListTorque.end(), jointName);
85 if (it != cfg.jointNameListTorque.end())
89 auto* casted_ct = ct->
asA<ControlTarget1DoFActuatorTorque>();
91 arm->targetsTorque.push_back(casted_ct);
92 jointIDTorqueMode.push_back(i);
93 foundControlDevice =
true;
97 cfg.jointNameListVelocity.begin(), cfg.jointNameListVelocity.end(), jointName);
98 if (it != cfg.jointNameListVelocity.end())
102 auto* casted_ct = ct->
asA<ControlTarget1DoFActuatorVelocity>();
104 arm->targetsVel.push_back(casted_ct);
105 jointIDVelocityMode.push_back(i);
106 foundControlDevice =
true;
108 if (not foundControlDevice)
113 ARMARX_ERROR <<
"Does not found valid control device for joint name: " << jointName
114 <<
"Please check torque controlled joints: [" << namesTorque
115 <<
"] and velocity controlled joints: [" << namesVelocity <<
"].";
120 arm->sensorDevices.append(sv, jointName);
122 ARMARX_DEBUG <<
"Number of torque controlled joints " << jointIDTorqueMode.size();
123 ARMARX_DEBUG <<
"Number of velocity controlled joints " << jointIDVelocityMode.size();
125 jointIDTorqueMode.size() + jointIDVelocityMode.size());
127 arm->controller.initialize(nonRtRns, rtRns);
128 arm->controller.ftsensor.initialize(rtRns,
robotUnit, cfg.ftConfig);
132 arm->nonRtConfig = cfg;
133 arm->rtStatus.reset(rtRns->getSize(), jointIDTorqueMode, jointIDVelocityMode);
134 ARMARX_INFO <<
"<-- Limb " << arm->kinematicChainName <<
" created";
137 template <
typename NJo
intTaskspaceControllerType>
140 const NJointControllerConfigPtr& config,
144 ARMARX_INFO <<
"================ creating controller ============================";
170 template <
typename NJo
intTaskspaceControllerType>
176 limb.emplace(pair.first, std::make_unique<ArmData>());
181 if (not userConfig.hands.empty())
202 template <
typename NJo
intTaskspaceControllerType>
204 NJointTaskspaceController<NJointTaskspaceControllerType>::createHands()
208 for (
auto& [name, hand_cfg] :
userConfig.hands)
210 ARMARX_INFO <<
"-- Creating hand: " <<
hands->hands.at(name)->kinematicChainName;
215 template <
typename NJo
intTaskspaceControllerType>
219 std::string taskName =
getClassName() +
"AdditionalTask";
237 c.waitForCycleDuration();
242 template <
typename NJo
intTaskspaceControllerType>
246 arm->bufferConfigNonRtToRt.getWriteBuffer() = arm->nonRtConfig;
247 arm->bufferConfigNonRtToRt.commitWrite();
250 template <
typename NJo
intTaskspaceControllerType>
257 if (not rtTargetSafe)
263 template <
typename NJo
intTaskspaceControllerType>
264 std::tuple<bool, bool>
269 bool rtTargetSafe =
true;
270 bool forceTorqueSafe =
true;
271 for (
auto& pair :
limb)
273 auto& arm = pair.second;
274 arm->nonRtConfig = arm->bufferConfigUserToNonRt.getUpToDateReadBuffer();
275 arm->rtStatusInNonRT = arm->bufferRtStatusToNonRt.getUpToDateReadBuffer();
276 rtSafe = rtSafe and pair.second->rtStatusInNonRT.rtSafe;
277 rtTargetSafe = rtTargetSafe and pair.second->rtStatusInNonRT.rtTargetSafe;
278 forceTorqueSafe = forceTorqueSafe and pair.second->rtStatusInNonRT.forceTorqueSafe;
282 hands->nonRTUpdateStatus();
284 return std::make_tuple(rtTargetSafe, forceTorqueSafe);
287 template <
typename NJo
intTaskspaceControllerType>
291 bool rtDesiredPoseSafe =
true;
292 for (
auto& [_, arm] :
limb)
294 rtDesiredPoseSafe = rtDesiredPoseSafe and arm->rtStatusInNonRT.rtTargetSafe;
296 return rtDesiredPoseSafe;
299 template <
typename NJo
intTaskspaceControllerType>
304 bool rtDesiredPoseSafe =
true;
305 for (
auto& [_, arm] :
limb)
307 rtDesiredPoseSafe = rtDesiredPoseSafe and arm->desiredPoseSafeOnActivation.load();
309 return rtDesiredPoseSafe;
312 template <
typename NJo
intTaskspaceControllerType>
316 for (
auto& [_, arm] :
limb)
322 hands->nonRTSetTarget();
326 template <
typename NJo
intTaskspaceControllerType>
330 for (
auto& pair :
limb)
332 if (not pair.second->rtReady)
337 if (not pair.second->rtStatusInNonRT.rtTargetSafe)
340 pair.second->rtStatusInNonRT.currentPose,
341 pair.second->rtStatusInNonRT.desiredPoseUnsafe,
349 template <
typename NJo
intTaskspaceControllerType>
355 arm->rtConfig = arm->bufferConfigNonRtToRt.getUpToDateReadBuffer();
356 arm->rtStatus.deltaT = deltaT;
357 arm->rtStatus.accumulateTime += deltaT;
358 arm->rtStatus.globalPose =
rtGetRobot()->getGlobalPose();
360 arm->controller.ftsensor.updateStatus(arm->rtConfig.ftConfig,
361 arm->rtStatus.currentForceTorque,
362 arm->rtStatus.deltaT,
363 arm->rtFirstRun.load());
364 arm->rtStatus.safeFTGuardOffset.template head<3>() =
365 arm->controller.ftsensor.getSafeGuardForceOffset();
367 arm->sensorDevices.updateJointValues(
368 arm->rtStatus.jointPosition, arm->rtStatus.jointVelocity, arm->rtStatus.jointTorque);
372 arm->bufferRtStatusToNonRt.getWriteBuffer() = arm->rtStatus;
373 arm->bufferRtStatusToNonRt.commitWrite();
374 arm->bufferRtStatusToUser.getWriteBuffer() = arm->rtStatus;
375 arm->bufferRtStatusToUser.commitWrite();
378 template <
typename NJo
intTaskspaceControllerType>
382 const size_t nDoFTorque,
383 const size_t nDoFVelocity,
384 const Eigen::VectorXf& targetTorque,
385 const Eigen::VectorXf& targetVelocity)
387 for (
size_t i = 0; i < nDoFTorque; i++)
390 auto jointIdx = arm->rtStatus.jointIDTorqueMode[i];
391 arm->targetsTorque.at(i)->torque = targetTorque(jointIdx);
392 if (!arm->targetsTorque.at(i)->isValid())
394 arm->targetsTorque.at(i)->torque = 0;
397 for (
size_t i = 0; i < nDoFVelocity; i++)
399 auto jointIdx = arm->rtStatus.jointIDVelocityMode[i];
400 arm->targetsVel.at(i)->velocity = targetVelocity(jointIdx);
402 if (!arm->targetsVel.at(i)->isValid())
404 arm->targetsVel.at(i)->velocity = 0;
407 arm->bufferRtStatusToOnPublish.getWriteBuffer() = arm->rtStatus;
408 arm->bufferRtStatusToOnPublish.commitWrite();
410 arm->bufferConfigRtToOnPublish.getWriteBuffer() = arm->rtConfig;
411 arm->bufferConfigRtToOnPublish.commitWrite();
413 arm->bufferConfigRtToUser.getWriteBuffer() = arm->rtConfig;
414 arm->bufferConfigRtToUser.commitWrite();
416 if (arm->rtFirstRun.load())
418 arm->rtFirstRun.store(
false);
419 arm->rtReady.store(
true);
423 template <
typename NJo
intTaskspaceControllerType>
428 double time_measure = IceUtil::Time::now().toMicroSecondsDouble();
432 arm->controller.run(arm->rtConfig, arm->rtStatus);
433 double time_run_rt = IceUtil::Time::now().toMicroSecondsDouble() - time_measure;
436 arm->rtStatus.nDoFTorque,
437 arm->rtStatus.nDoFVelocity,
438 arm->rtStatus.desiredJointTorque,
439 arm->rtStatus.desiredJointVelocity);
441 double time_set_target = IceUtil::Time::now().toMicroSecondsDouble() - time_measure;
442 time_measure = IceUtil::Time::now().toMicroSecondsDouble() - time_measure;
444 if (time_measure > 200)
447 "run_rt_limb: %.2f\n"
448 "set_target_limb: %.2f\n"
450 time_run_rt - time_measure,
451 time_set_target - time_run_rt,
453 .deactivateSpam(1.0f);
458 template <
typename NJo
intTaskspaceControllerType>
461 const std::string& key,
462 const Eigen::Matrix4f& targetPose,
464 const Eigen::Matrix4f& pose,
474 data.targetPose = targetPose;
475 data.targetPoseMode = targetPoseMode;
478 data.stiffness = stiffness;
484 targetPose, targetPoseMode, pose, vel, ft, stiffness));
488 template <
typename NJo
intTaskspaceControllerType>
497 bool rtReady =
false;
498 for (
const auto& nodeset :
coordinator->getNodesetList())
500 auto& rts =
limb.at(nodeset)->rtStatus;
501 auto& rtc =
limb.at(nodeset)->rtConfig;
502 rtReady =
limb.at(nodeset)->rtReady.load();
504 if constexpr (NJointTaskspaceControllerType::IsCompliant)
508 rtc.desiredPoseFrameMode,
511 rts.currentForceTorque,
516 ARMARX_WARNING <<
"Not implemented yet for controller types without kpImpedance";
525 for (
const auto& nodeset :
coordinator->getNodesetList())
528 limb.at(nodeset)->rtConfig.desiredPoseFrameMode = PoseFrameMode::root;
532 template <
typename NJo
intTaskspaceControllerType>
535 const IceUtil::Time& ,
536 const IceUtil::Time& timeSinceLastIteration)
538 double deltaT = timeSinceLastIteration.toSecondsDouble();
539 for (
auto& pair :
limb)
546 for (
auto& pair :
limb)
548 limbRT(pair.second, deltaT);
552 hands->updateRTStatus(deltaT);
558 template <
typename NJo
intTaskspaceControllerType>
561 const ::armarx::aron::data::dto::DictPtr& dto,
562 const Ice::Current& )
569 auto& arm =
limb.at(pair.first);
571 bool desiredPoseFrameModeSame = prevCfg.limbs.at(pair.first).desiredPoseFrameMode ==
572 pair.second.desiredPoseFrameMode;
574 pair.second.desiredPose,
575 prevCfg.limbs.at(pair.first).desiredPose,
577 "previous desired pose",
578 pair.second.safeDistanceMMToGoal,
579 pair.second.safeRotAngleDegreeToGoal,
580 "updateConfig_" + pair.first))
583 pair.second.desiredPose = prevCfg.limbs.at(pair.first).desiredPose;
585 arm->bufferConfigUserToNonRt.getWriteBuffer() = pair.second;
588 arm->nonRtConfig = arm->bufferConfigUserToNonRt.getWriteBuffer();
590 arm->bufferConfigUserToNonRt.commitWrite();
597 arm->rtConfig = arm->nonRtConfig;
614 template <
typename NJo
intTaskspaceControllerType>
617 const Ice::Current& )
619 for (
auto& pair :
limb)
622 pair.second->bufferConfigRtToUser.getUpToDateReadBuffer();
631 template <
typename NJo
intTaskspaceControllerType>
634 const Ice::Current& )
636 for (
auto& pair :
limb)
639 pair.second->bufferConfigRtToUser.getUpToDateReadBuffer();
648 template <
typename NJo
intTaskspaceControllerType>
651 const std::string& nodeSetName,
652 const bool forceGuard,
653 const bool torqueGuard,
654 const Ice::Current& )
659 it->second.ftConfig.enableSafeGuardForce = forceGuard;
660 it->second.ftConfig.enableSafeGuardTorque = torqueGuard;
661 limb.at(nodeSetName)->controller.ftsensor.enableSafeGuard(forceGuard, torqueGuard);
663 <<
"reset safe guard with force torque sensors: safe? "
664 <<
limb.at(nodeSetName)->controller.ftsensor.isSafe(it->second.ftConfig);
665 limb.at(nodeSetName)->bufferConfigUserToNonRt.getWriteBuffer() = it->second;
666 limb.at(nodeSetName)->bufferConfigUserToNonRt.commitWrite();
671 <<
" found in the controllers.";
676 template <
typename NJo
intTaskspaceControllerType>
679 const std::string& nodeSetName,
680 const Ice::Current& )
685 return limb.at(nodeSetName)->controller.ftsensor.ftSafe.load();
689 <<
" found in the controllers.";
693 template <
typename NJo
intTaskspaceControllerType>
696 const std::string& nodeSetName,
697 const Ice::Current& )
702 return limb.at(nodeSetName)->controller.ftsensor.ftWasNotSafe.load();
706 <<
" found in the controllers.";
710 template <
typename NJo
intTaskspaceControllerType>
713 const std::string& rns,
714 const Ice::Current& )
716 std::vector<float> tcpVel;
717 auto& arm =
limb.at(rns);
718 auto s = arm->bufferRtStatusToUser.getUpToDateReadBuffer();
719 tcpVel.reserve(s.currentTwist.size());
720 for (
int i = 0; i < s.currentTwist.size(); i++)
722 tcpVel.push_back(s.currentTwist[i]);
727 template <
typename NJo
intTaskspaceControllerType>
730 const std::string& nodeSetName,
731 const Ice::Current& )
733 auto search =
limb.find(nodeSetName);
734 if (search ==
limb.end())
737 <<
"does not exist in the controller";
738 return std::vector<double>{};
741 auto& arm =
limb.at(nodeSetName);
742 auto currentPose = arm->bufferRtStatusToOnPublish.getUpToDateReadBuffer().currentPose;
747 template <
typename NJo
intTaskspaceControllerType>
752 const Ice::Current& )
756 for (
size_t i = 0; i < 4; ++i)
758 for (
int j = 0; j < 4; ++j)
760 pair.second.desiredPose(i, j) = targetPoseMap.at(pair.first)[i][j];
763 if (targetNullspaceMap.at(pair.first).size() > 0)
765 const size_t nDoF = pair.second.desiredNullspaceJointAngles.value().size();
767 <<
"the joint numbers does not match";
768 for (
size_t i = 0; i < nDoF; ++i)
770 pair.second.desiredNullspaceJointAngles.value()(i) =
771 targetNullspaceMap.at(pair.first)[i];
774 limb.at(pair.first)->bufferConfigUserToNonRt.getWriteBuffer() = pair.second;
775 limb.at(pair.first)->bufferConfigUserToNonRt.commitWrite();
780 template <
typename NJo
intTaskspaceControllerType>
785 const auto nDoF = arm->jointNames.size();
786 if (!configData.desiredNullspaceJointAngles.has_value())
790 ARMARX_INFO <<
"-- No user defined nullspace target, reset to zero with "
792 configData.desiredNullspaceJointAngles = Eigen::VectorXf::Zero(nDoF);
793 arm->reInitPreActivate.store(
true);
798 arm->bufferConfigRtToUser.getUpToDateReadBuffer().desiredNullspaceJointAngles;
800 <<
"Controller is active, but no user defined nullspace target. \n"
801 "You should first get up-to-date config of this controller and then "
804 " auto cfg = ctrl->getConfig(); \n"
805 " cfg.desiredPose = xxx;\n"
806 " ctrl->updateConfig(cfg);\n"
807 "Now, I decide by myself to use the existing values of nullspace "
809 << currentValue.value();
810 configData.desiredNullspaceJointAngles = currentValue;
817 template <
typename NJo
intTaskspaceControllerType>
824 auto rtStatus = arm->bufferRtStatusToOnPublish.getUpToDateReadBuffer();
825 auto cfgNonRt = arm->bufferConfigNonRtToPublish.getUpToDateReadBuffer();
829 datafields[
"nDoFTorque"] =
new Variant(rtStatus.nDoFTorque);
830 datafields[
"nDoFVelocity"] =
new Variant(rtStatus.nDoFVelocity);
840 datafields[
"cfg.velocity_limit"] =
new Variant(cfgNonRt.velocityLimit);
841 datafields[
"cfg.torque_limit"] =
new Variant(cfgNonRt.torqueLimit);
842 datafields[
"ft.safeGuardForceThreshold"] =
843 new Variant(cfgNonRt.ftConfig.safeGuardForceThreshold);
844 datafields[
"ft.safeGuardTorqueThreshold"] =
845 new Variant(cfgNonRt.ftConfig.safeGuardTorqueThreshold);
848 float positionError =
852 datafields[
"poseError_position"] =
new Variant(positionError);
853 datafields[
"poseError_angle"] =
new Variant(angleError);
865 datafields,
"inertiaInvVelCtrlJoints", rtStatus.inertiaInvVelCtrlJoints);
870 float currentForceNorm = rtStatus.currentForceTorque.template head<3>().norm();
871 float currentTorqueNorm = rtStatus.currentForceTorque.template tail<3>().norm();
872 float safeForceGuardOffsetNorm = rtStatus.safeFTGuardOffset.template head<3>().norm();
873 float safeTorqueGuardOffsetNorm = rtStatus.safeFTGuardOffset.template tail<3>().norm();
874 datafields[
"currentForceNorm"] =
new Variant(currentForceNorm);
875 datafields[
"currentTorqueNorm"] =
new Variant(currentTorqueNorm);
876 datafields[
"safeForceGuardOffsetNorm"] =
new Variant(safeForceGuardOffsetNorm);
877 datafields[
"safeTorqueGuardOffsetNorm"] =
new Variant(safeTorqueGuardOffsetNorm);
878 datafields[
"safeForceGuardDifference"] =
879 new Variant(currentForceNorm - safeForceGuardOffsetNorm);
880 datafields[
"safeTorqueGuardDifference"] =
881 new Variant(currentTorqueNorm - safeTorqueGuardOffsetNorm);
883 datafields[
"rtSafe"] =
new Variant(rtStatus.rtSafe * 1.0);
884 datafields[
"rtTargetSafe"] =
new Variant(rtStatus.rtTargetSafe * 1.0);
885 bool forceTrigger = (not rtStatus.rtSafe) and rtStatus.rtTargetSafe;
886 datafields[
"forceTrigger"] =
new Variant(forceTrigger * 1.0);
887 datafields[
"forceTorqueSafe"] =
new Variant(rtStatus.forceTorqueSafe * 1.0);
896 debugObs->setDebugChannel(
getClassName() +
"_" + arm->kinematicChainName, datafields);
899 template <
typename NJo
intTaskspaceControllerType>
906 for (
auto& pair :
limb)
908 if (not pair.second->rtReady.load())
916 hands->onPublish(debugObs);
920 if (++skipStepCountArviz_ >= skipStepsArviz_)
922 skipStepCountArviz_ = 0;
927 template <
typename NJo
intTaskspaceControllerType>
937 auto& cfg =
coordinator->bufferUserCfgToPublish.getUpToDateReadBuffer();
938 auto data =
coordinator->bufferDataRtToPublish.getUpToDateReadBuffer();
949 using namespace armarx::control::common::coordination::arondto;
950 auto followerIsolation = cfg.followerConnectionMode == ConnectionMode::follower_isolated;
951 auto leftAsLeader = cfg.leadershipMode == LeadershipMode::left_as_leader;
952 auto rightAsLeader = cfg.leadershipMode == LeadershipMode::right_as_leader;
953 auto followerInLeaderLocalFrame =
954 cfg.followerFrameMode == common::arondto::PoseFrameMode::leader;
955 datafields[
"followerIsolation"] =
new Variant(followerIsolation);
956 datafields[
"leftAsLeader"] =
new Variant(leftAsLeader);
957 datafields[
"rightAsLeader"] =
new Variant(rightAsLeader);
958 datafields[
"followerInLeaderLocalFrame"] =
new Variant(followerInLeaderLocalFrame);
960 debugObs->setDebugChannel(
"SyncModeCoordinator", datafields);
963 template <
typename NJo
intTaskspaceControllerType>
974 storedArvizLayers.clear();
981 template <
typename NJo
intTaskspaceControllerType>
991 const double arrowWidth = 2.5F;
994 const auto& rtStatus =
coordinator->bufferDataRtToPublish.getUpToDateReadBuffer();
995 const Eigen::Matrix4f globalPose = Eigen::Matrix4f::Identity();
999 viz::Pose(
"targetPose").pose(globalPose * rtStatus.targetPose).
scale(1.5f));
1001 viz::Pose(
"virtualPose").pose(globalPose * rtStatus.virtualPose).
scale(1.25f));
1003 viz::Pose(
"currentPose").pose(globalPose * rtStatus.currentPose).
scale(1.0f));
1007 const auto objCenter =
common::getPos(globalPose * rtStatus.currentPose);
1012 .fromTo(objCenter, objCenter + 1000.0f * rtStatus.virtualVel.head<3>())
1013 .
color(simox::Color::blue())
1014 .
width(arrowWidth));
1016 .fromTo(objCenter, objCenter + 1000.0f * rtStatus.poseError.head<3>())
1017 .
color(simox::Color::black())
1018 .
width(arrowWidth));
1024 .fromTo(objCenter, objCenter + 100.0f * rtStatus.currentFT.head<3>())
1025 .
color(simox::Color::yellow())
1026 .
width(arrowWidth));
1028 .fromTo(objCenter, objCenter + 100.0f * rtStatus.currentFT.tail<3>())
1029 .
color(simox::Color::green())
1030 .
width(arrowWidth));
1036 for (
const auto& [_, arm] :
limb)
1038 const auto& cfgNonRt = arm->bufferConfigNonRtToPublish.getUpToDateReadBuffer();
1039 const auto& rtStatus = arm->bufferRtStatusToOnPublish.getUpToDateReadBuffer();
1041 const Eigen::Matrix4f& globalPose = rtStatus.globalPose;
1042 auto addPose = [&](
viz::Layer& layer,
const std::string& suffix =
"")
1045 .pose(globalPose * rtStatus.desiredPose)
1048 .pose(globalPose * rtStatus.currentPose)
1051 const float positionError = (
common::getPos(rtStatus.currentPose) -
1054 const float positionErrorNormalized =
1055 std::fmin((positionError / cfgNonRt.safeDistanceMMToGoal), 1.);
1059 .
color(simox::Color(positionErrorNormalized,
1060 1.0f - positionErrorNormalized,
1062 .
width(arrowWidth));
1070 const bool enableTrajVisualization =
false;
1071 if (enableTrajVisualization)
1073 const std::string name =
"Traj_" + arm->kinematicChainName;
1074 if (storedArvizLayers.count(name) == 0)
1076 storedArvizLayers[name] =
scopedArviz->layer(name);
1078 viz::Layer& layer = storedArvizLayers.at(name);
1080 addPose(layer, std::to_string(
index));
1088 rtStatus.forceImpedance.template head<3>() * 5.0)
1089 .
color(simox::Color::cyan())
1090 .
width(arrowWidth));
1116 template <
typename NJo
intTaskspaceControllerType>
1120 for (
auto& pair :
limb)
1122 pair.second->rtReady.store(
false);
1126 template <
typename NJo
intTaskspaceControllerType>
1129 const std::string& type,
1130 const ::armarx::aron::data::dto::DictPtr& dto,
1131 const Ice::Current& )
1133 ARMARX_INFO <<
"Adding coordinator of type " << type;
1139 coordinator = std::make_shared<common::coordination::SyncCoordination>(dto);
1146 for (
const auto& nodeset :
coordinator->getNodesetList())
1148 if (
limb.find(nodeset) ==
limb.end())
1151 ARMARX_WARNING <<
"The requested nodeset by coordinator " << nodeset
1152 <<
" does not exist in the current controller, disable coordinator";
1163 for (
const auto& nodeset :
coordinator->getNodesetList())
1180 template <
typename NJo
intTaskspaceControllerType>
1183 const Ice::Current& )
1188 ARMARX_INFO <<
"Coordinator is not created yet, use `useCoordinator` to create!!";
1191 for (
const auto& nodeset :
coordinator->getNodesetList())
1193 auto& arm =
limb.at(nodeset);
1194 auto& cfgRT = arm->bufferConfigRtToUser.getUpToDateReadBuffer();
1195 arm->bufferConfigUserToNonRt.getWriteBuffer().desiredPose = cfgRT.desiredPose;
1196 arm->bufferConfigUserToNonRt.commitWrite();
1203 template <
typename NJo
intTaskspaceControllerType>
1212 ARMARX_RT_LOGF_INFO(
"--> rtPreActivateController for %s", arm->kinematicChainName.c_str());
1213 VirtualRobot::RobotNodeSetPtr rns =
rtGetRobot()->getRobotNodeSet(arm->kinematicChainName);
1214 Eigen::Matrix4f currentPose = rns->getTCP()->getPoseInRootFrame();
1215 auto quat = VirtualRobot::MathTools::eigen4f2quat(currentPose);
1217 "[ %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f ].",
1226 arm->desiredPoseSafeOnActivation =
1228 arm->rtConfig.desiredPose,
1229 arm->rtConfig.safeDistanceMMToGoal,
1230 arm->rtConfig.safeRotAngleDegreeToGoal);
1233 if (arm->reInitPreActivate.load())
1240 arm->rtConfig.desiredNullspaceJointAngles = rns->getJointValuesEigen();
1242 arm->reInitPreActivate.store(
false);
1246 arm->rtConfig.desiredPose = currentPose;
1247 arm->nonRtConfig = arm->rtConfig;
1249 arm->bufferConfigUserToNonRt.reinitAllBuffers(arm->rtConfig);
1250 arm->bufferConfigNonRtToRt.reinitAllBuffers(arm->rtConfig);
1251 arm->bufferConfigRtToOnPublish.reinitAllBuffers(arm->rtConfig);
1252 arm->bufferConfigNonRtToPublish.reinitAllBuffers(arm->rtConfig);
1253 arm->bufferConfigRtToUser.reinitAllBuffers(arm->rtConfig);
1256 arm->sensorDevices.updateJointValues(arm->rtStatus.jointPosition,
1257 arm->rtStatus.jointVelocity,
1258 arm->rtStatus.jointTorque);
1259 arm->rtStatus.rtPreActivate(currentPose);
1260 arm->rtStatus.globalPose =
rtGetRobot()->getGlobalPose();
1261 arm->rtStatusInNonRT = arm->rtStatus;
1262 arm->nonRTDeltaT = 0.0;
1263 arm->nonRTAccumulateTime = 0.0;
1264 arm->bufferRtStatusToOnPublish.reinitAllBuffers(arm->rtStatus);
1265 arm->bufferRtStatusToNonRt.reinitAllBuffers(arm->rtStatus);
1266 arm->bufferRtStatusToUser.reinitAllBuffers(arm->rtStatus);
1273 template <
typename NJo
intTaskspaceControllerType>
1276 const Ice::Current& current)
1279 <<
"NJointTaskspaceController<NJointTaskspaceControllerType>::activateController";
1284 scopedArviz->updateComponentName(
"NJointTaskspaceController");
1290 ARMARX_INFO <<
"Calling hands->nonRtActivateController()";
1291 hands->nonRtActivateController();
1296 template <
typename NJo
intTaskspaceControllerType>
1299 const Ice::Current& current)
1302 <<
"NJointTaskspaceController<NJointTaskspaceControllerType>::deactivateController";
1309 template <
typename NJo
intTaskspaceControllerType>
1314 for (
auto& pair :
limb)
1318 userConfig.limbs.at(pair.first) = pair.second->rtConfig;
1322 hands->rtPreActivate();
1327 template <
typename NJo
intTaskspaceControllerType>
1333 limb.at(pair.first)->rtPostDeactivate();
1346 template <
typename NJo
intTaskspaceControllerType>
1359 template <
typename NJo
intTaskspaceControllerType>
1363 const std::map<std::string, ConstControlDevicePtr>& ,
1364 const std::map<std::string, ConstSensorDevicePtr>&)
1370 ::armarx::WidgetDescription::WidgetSeq widgets;
1373 LabelPtr label =
new Label;
1374 label->text =
"select a controller config";
1376 StringComboBoxPtr cfgBox =
new StringComboBox;
1377 cfgBox->name =
"config_box";
1378 cfgBox->defaultIndex = 0;
1379 cfgBox->multiSelect =
false;
1381 cfgBox->options = std::vector<std::string>{
1382 "default_a7_with_hands",
1385 "default_a7_zero_torque",
1387 "default_a6_with_hands",
1389 "default_a6_zero_torque",
1393 layout->children.emplace_back(label);
1394 layout->children.emplace_back(cfgBox);
1397 layout->children.insert(layout->children.end(), widgets.begin(), widgets.end());
1402 template <
typename NJo
intTaskspaceControllerType>
1407 auto cfgName = values.at(
"config_box")->getString();
1410 "controller_config/" + std::string(NJointTaskspaceControllerType::TypeName) +
"/" +
1418 return new ConfigurableNJointControllerConfig{cfgDTO.toAronDTO()};
1429 const NJointControllerConfigPtr& config,
1439 return "TSMixImpVel";
1445 const auto nDoF =
static_cast<Eigen::Index
>(arm->jointNames.size());
1447 const auto checkSize = [nDoF](
const auto& v) {
ARMARX_CHECK_EQUAL(v.rows(), nDoF); };
1448 const auto checkNonNegative = [](
const auto& v) {
ARMARX_CHECK((v.array() >= 0).all()); };
1449 checkSize(configData.desiredNullspaceJointAngles.value());
1450 checkSize(configData.kdNullspaceTorque);
1451 checkSize(configData.kpNullspaceTorque);
1452 checkSize(configData.kdNullspaceVel);
1453 checkSize(configData.kpNullspaceVel);
1455 checkNonNegative(configData.kdNullspaceTorque);
1456 checkNonNegative(configData.kpNullspaceTorque);
1457 checkNonNegative(configData.kpNullspaceVel);
1458 checkNonNegative(configData.kdNullspaceVel);
1459 checkNonNegative(configData.kdImpedance);
1460 checkNonNegative(configData.kpImpedance);
1466 auto cfg = arm->bufferConfigRtToOnPublish.getUpToDateReadBuffer();
1471 if (cfg.desiredNullspaceJointAngles.has_value())
1474 datafields,
"desiredNullspaceJointAngles", cfg.desiredNullspaceJointAngles.value());
1477 datafields[
"poseError_threshold_position"] =
new Variant(cfg.safeDistanceMMToGoal);
1478 datafields[
"poseError_threshold_angle"] =
new Variant(cfg.safeRotAngleDegreeToGoal);
1479 datafields[
"safeForceGuardThreshold"] =
new Variant(cfg.ftConfig.safeGuardForceThreshold);
1480 datafields[
"safeTorqueGuardThreshold"] =
new Variant(cfg.ftConfig.safeGuardTorqueThreshold);
1490 const NJointControllerConfigPtr& config,
1507 const auto nDoF =
static_cast<Eigen::Index
>(arm->jointNames.size());
1509 const auto checkSize = [nDoF](
const auto& v) {
ARMARX_CHECK_EQUAL(v.rows(), nDoF); };
1510 const auto checkNonNegative = [](
const auto& v) {
ARMARX_CHECK((v.array() >= 0).all()); };
1511 checkSize(configData.desiredNullspaceJointAngles.value());
1512 checkSize(configData.kdNullspaceTorque);
1513 checkSize(configData.kpNullspaceTorque);
1515 checkNonNegative(configData.kdNullspaceTorque);
1516 checkNonNegative(configData.kpNullspaceTorque);
1517 checkNonNegative(configData.kdImpedance);
1518 checkNonNegative(configData.kpImpedance);
1524 auto cfg = arm->bufferConfigRtToOnPublish.getUpToDateReadBuffer();
1527 if (cfg.desiredNullspaceJointAngles.has_value())
1530 datafields,
"desiredNullspaceJointAngles", cfg.desiredNullspaceJointAngles.value());
1533 datafields[
"poseError_threshold_position"] =
new Variant(cfg.safeDistanceMMToGoal);
1534 datafields[
"poseError_threshold_angle"] =
new Variant(cfg.safeRotAngleDegreeToGoal);
1535 datafields[
"safeForceGuardThreshold"] =
new Variant(cfg.ftConfig.safeGuardForceThreshold);
1536 datafields[
"safeTorqueGuardThreshold"] =
new Variant(cfg.ftConfig.safeGuardTorqueThreshold);
1546 const NJointControllerConfigPtr& config,
1563 const auto nDoF =
static_cast<Eigen::Index
>(arm->jointNames.size());
1565 const auto checkSize = [nDoF](
const auto& v) {
ARMARX_CHECK_EQUAL(v.rows(), nDoF); };
1566 const auto checkNonNegative = [](
const auto& v) {
ARMARX_CHECK((v.array() >= 0).all()); };
1567 checkSize(configData.desiredNullspaceJointAngles.value());
1568 checkSize(configData.kdNullspaceTorque);
1569 checkSize(configData.kpNullspaceTorque);
1571 checkNonNegative(configData.kdNullspaceTorque);
1572 checkNonNegative(configData.kpNullspaceTorque);
1573 checkNonNegative(configData.kdImpedance);
1574 checkNonNegative(configData.kpImpedance);
1580 auto cfg = arm->bufferConfigRtToOnPublish.getUpToDateReadBuffer();
1583 if (cfg.desiredNullspaceJointAngles.has_value())
1586 datafields,
"desiredNullspaceJointAngles", cfg.desiredNullspaceJointAngles.value());
1589 datafields[
"poseError_threshold_position"] =
new Variant(cfg.safeDistanceMMToGoal);
1590 datafields[
"poseError_threshold_angle"] =
new Variant(cfg.safeRotAngleDegreeToGoal);
1591 datafields[
"safeForceGuardThreshold"] =
new Variant(cfg.ftConfig.safeGuardForceThreshold);
1592 datafields[
"safeTorqueGuardThreshold"] =
new Variant(cfg.ftConfig.safeGuardTorqueThreshold);
1602 const NJointControllerConfigPtr& config,
1618 const auto nDoF =
static_cast<Eigen::Index
>(arm->jointNames.size());
1620 const auto checkSize = [nDoF](
const auto& v) {
ARMARX_CHECK_EQUAL(v.rows(), nDoF); };
1621 const auto checkNonNegative = [](
const auto& v) {
ARMARX_CHECK((v.array() >= 0).all()); };
1622 checkSize(configData.desiredNullspaceJointAngles.value());
1623 checkSize(configData.kdNullspaceVel);
1624 checkSize(configData.kpNullspaceVel);
1626 checkNonNegative(configData.kpNullspaceVel);
1627 checkNonNegative(configData.kdNullspaceVel);
1633 auto cfg = arm->bufferConfigRtToOnPublish.getUpToDateReadBuffer();
1636 if (cfg.desiredNullspaceJointAngles.has_value())
1639 datafields,
"desiredNullspaceJointAngles", cfg.desiredNullspaceJointAngles.value());
1642 datafields[
"poseError_threshold_position"] =
new Variant(cfg.safeDistanceMMToGoal);
1643 datafields[
"poseError_threshold_angle"] =
new Variant(cfg.safeRotAngleDegreeToGoal);
1644 datafields[
"safeForceGuardThreshold"] =
new Variant(cfg.ftConfig.safeGuardForceThreshold);
1645 datafields[
"safeTorqueGuardThreshold"] =
new Variant(cfg.ftConfig.safeGuardTorqueThreshold);
#define ARMARX_RT_LOGF_IMPORTANT(...)
#define ARMARX_RT_LOGF_WARN(...)
#define ARMARX_RT_LOGF_INFO(...)
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
armarx::viz::Client createArVizClient()
Brief description of class JointControlTargetBase.
This util class helps with keeping a cycle time during a control cycle.
ArmarXObjectSchedulerPtr getObjectScheduler() const
int getState() const
Retrieve current state of the ManagedIceObject.
bool isControllerActive(const Ice::Current &=Ice::emptyCurrent) const final override
void runTask(const std::string &taskName, Task &&task)
Executes a given task in a separate thread from the Application ThreadPool.
std::string getClassName(const Ice::Current &=Ice::emptyCurrent) const override=0
void deactivateController(const Ice::Current &=Ice::emptyCurrent) override
const VirtualRobot::RobotPtr & useSynchronizedRtRobot(bool updateCollisionModel=false)
Requests a VirtualRobot for use in rtRun *.
const VirtualRobot::RobotPtr & rtGetRobot()
TODO make protected and use attorneys.
void activateController(const Ice::Current &=Ice::emptyCurrent) override
ControlTargetBase * useControlTarget(const std::string &deviceName, const std::string &controlMode)
Declares to calculate the ControlTarget for the given ControlDevice in the given ControlMode when rtR...
static std::filesystem::path toSystemPath(const data::PackagePath &pp)
The SensorValueBase class.
The Variant class is described here: Variants.
static bool pinThreadToCPU(unsigned int cpu)
Pins the calling thread to the CPU with the given id.
static bool elevateThreadPriority(int priority)
Elevate the thread priority of the calling thread to the given priority.
static constexpr int RT_THREAD_PRIORITY
The thread priority for rt-threads.
std::string getClassName(const Ice::Current &=Ice::emptyCurrent) const override
void limbPublishConfig(StringVariantBaseMap &datafields, ArmPtr &arm) override
void validateConfigDataCheckSize(Config &configData, ArmPtr &arm) override
NJointTSAdmController(const RobotUnitPtr &robotUnit, const NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &robot)
std::string getClassName(const Ice::Current &=Ice::emptyCurrent) const override
================================== TSImp ==================================
NJointTSImpController(const RobotUnitPtr &robotUnit, const NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &robot)
void limbPublishConfig(StringVariantBaseMap &datafields, ArmPtr &arm) override
void validateConfigDataCheckSize(Config &configData, ArmPtr &arm) override
std::string getClassName(const Ice::Current &=Ice::emptyCurrent) const override
================================== TSMixImpVel ==================================
NJointTSMixImpVelController(const RobotUnitPtr &robotUnit, const NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &robot)
void limbPublishConfig(StringVariantBaseMap &datafields, ArmPtr &arm) override
void validateConfigDataCheckSize(Config &configData, ArmPtr &arm) override
std::string getClassName(const Ice::Current &=Ice::emptyCurrent) const override
NJointTSVelController(const RobotUnitPtr &robotUnit, const NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &robot)
void limbPublishConfig(StringVariantBaseMap &datafields, ArmPtr &arm) override
void validateConfigDataCheckSize(Config &configData, ArmPtr &arm) override
Brief description of class NJointTaskspaceController.
std::map< std::string, VirtualRobot::RobotNodeSetPtr > controllableNodeSets
void onPublish(const SensorAndControl &, const DebugDrawerInterfacePrx &, const DebugObserverInterfacePrx &) override
static WidgetDescription::WidgetPtr GenerateConfigDescription(const VirtualRobot::RobotPtr &, const std::map< std::string, ConstControlDevicePtr > &, const std::map< std::string, ConstSensorDevicePtr > &)
--------------------------------— GUI Widget ------------------------------------------—
void onInitNJointController() override
ConfigurableNJointControllerConfigPtr ConfigPtrT
void limbRT(ArmPtr &arm, const double deltaT)
Ice::DoubleSeq getCurrentTCPPose(const std::string &nodeSetName, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
std::shared_ptr< common::coordination::SyncCoordination > coordinator
void limbNonRT(ArmPtr &arm)
void onPublishCoordinator(const DebugObserverInterfacePrx &debugObs)
::armarx::aron::data::dto::DictPtr getConfig(const Ice::Current &iceCurrent=Ice::emptyCurrent) override
virtual void collectArviz(viz::StagedCommit &stage) const
NJointTaskspaceController(const RobotUnitPtr &robotUnit, const NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &)
Ice::FloatSeq getTCPVel(const std::string &rns, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
void limbReInit(ArmPtr &arm)
void useCoordinator(const std::string &type, const ::armarx::aron::data::dto::DictPtr &dto, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
bool rtGetDesiredPoseSafeStatus()
std::map< std::string, ArmPtr > limb
bool isSafeForceTorque(const std::string &nodeSetName, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
-----------------------------— Other interaces ----------------------------------------—
typename NJointTaskspaceControllerType::Config Config
std::atomic_bool coordinatorEnabled
coordinator
bool wasNotSafeForceTorque(const std::string &nodeSetName, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
void validateConfigData(Config &config, ArmPtr &arm)
void limbRTSetTarget(ArmPtr &arm, const size_t nDoFTorque, const size_t nDoFVelocity, const Eigen::VectorXf &targetTorque, const Eigen::VectorXf &targetVelocity)
core::HandControlPtr hands
void enableSafeGuardForceTorque(const std::string &nodeSetName, const bool forceGuard, const bool torqueGuard, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
std::optional< viz::ScopedClient > scopedArviz
bool rtGetDesiredPoseSafeStatusOnActivation()
std::tuple< bool, bool > additionalTaskUpdateStatus()
void rtPostDeactivateController() override
This function is called after the controller is deactivated.
void updateInputData(const std::string &key, const Eigen::Matrix4f &targetPose, const PoseFrameMode &targetPoseMode, const Eigen::Matrix4f &pose, const Eigen::Vector6f &vel, const Eigen::Vector6f &ft, const Eigen::Vector6f &stiffness)
some method for coordinator
void rtRunCoordinator(double deltaT)
coordinator
virtual void additionalTask()
void rtRun(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration) override
TODO make protected and use attorneys.
void activateController(const Ice::Current ¤t=Ice::emptyCurrent) final
NJointControllerBase interface.
std::unique_ptr< ArmData > ArmPtr
void additionalTaskSetTarget()
std::map< std::string, common::coordination::InputData > coordinatorInputData
void updateConfig(const ::armarx::aron::data::dto::DictPtr &dto, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
NJointController interface.
virtual void validateConfigDataCheckSize(Config &configData, ArmPtr &arm)=0
bool updateTargetPose(const TargetPoseMap &targetPoseMap, const TargetNullspaceMap &targetNullspaceMap, const Ice::Current &=Ice::emptyCurrent) override
static ConfigPtrT GenerateConfigFromVariants(const StringVariantBaseMap &values)
virtual void limbPublishConfig(StringVariantBaseMap &datafields, ArmPtr &arm)=0
void limbPublish(ArmPtr &arm, const DebugObserverInterfacePrx &debugObs)
void handleRTNotSafeInNonRT()
armarx::control::common::arondto::PoseFrameMode PoseFrameMode
void deactivateController(const Ice::Current ¤t=Ice::emptyCurrent) final
VirtualRobot::RobotPtr nonRtRobot
void rtPreActivateController() override
This function is called before the controller is activated.
void limbRTUpdateStatus(ArmPtr &arm, const double deltaT)
-----------------------------— Real time cotnrol --------------------------------------—
void limbInit(const std::string &nodeSetName, ArmPtr &arm, Config &cfg, VirtualRobot::RobotPtr &nonRtRobotPtr)
DerivedT & color(Color color)
DerivedT & scale(Eigen::Vector3f scale)
#define ARMARX_CHECK_GREATER(lhs, rhs)
This macro evaluates whether lhs is greater (>) than rhs and if it turns out to be false it will thro...
#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_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
#define ARMARX_INFO
The normal logging level.
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
armarx::aron::data::dto::Dict getRTStatus()
void disableCoordinator()
void calibrateFTSensor()
ft sensor
Matrix< float, 6, 1 > Vector6f
std::shared_ptr< class Robot > RobotPtr
::IceInternal::Handle< Dict > DictPtr
void reportPoseDeviationWarning(const std::string &who, const Eigen::Matrix4f &pose1, const Eigen::Matrix4f &pose2, const std::string &namePose1, const std::string &namePose2)
bool detectAndReportPoseDeviationWarning(const Eigen::Matrix4f &pose1, const Eigen::Matrix4f &pose2, const std::string &namePose1, const std::string &namePose2, float positionThrMM, float angleThrDeg, const std::string &who)
bool poseDeviationTooLarge(const Eigen::Matrix4f ¤tPose, const Eigen::Matrix4f &desiredPose, float positionThrMM, float angleThrDeg)
void debugEigenVec(StringVariantBaseMap &datafields, const std::string &name, Eigen::VectorXf vec)
float getDeltaAngleBetweenPose(const Eigen::Matrix4f &pose1, const Eigen::Matrix4f &pose2)
void debugEigenPose(StringVariantBaseMap &datafields, const std::string &name, Eigen::Matrix4f pose)
DVec mat4ToDVec(const Eigen::Matrix4f &mat)
convert Eigen:Matrix4f to 7D double vector.
void debugEigenMat(StringVariantBaseMap &datafields, const std::string &name, const Eigen::MatrixXd &mat)
std::string sVecToString(const std::vector< std::string > &vec, const std::string &delimiter)
Eigen::Block< Eigen::Matrix4f, 3, 1 > getPos(Eigen::Matrix4f &matrix)
NJointControllerRegistration< NJointTSAdmController > registrationControllerNJointTSAdmController("TSAdm")
NJointControllerRegistration< NJointTSImpController > registrationControllerNJointTSImpController("TSImp")
NJointControllerRegistration< NJointTSMixImpVelController > registrationControllerNJointTSMixImpVelController("TSMixImpVel")
NJointControllerRegistration< NJointTSVelController > registrationControllerNJointTSVelController("TSVel")
dictionary< string, Ice::FloatSeq > TargetNullspaceMap
dictionary< string, FloatSeqSeq > TargetPoseMap
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugObserverInterface > DebugObserverInterfacePrx
std::map< std::string, VariantBasePtr > StringVariantBaseMap
AronDTO readFromJson(const std::filesystem::path &filename)
IceUtil::Handle< class RobotUnit > RobotUnitPtr
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugDrawerInterface > DebugDrawerInterfacePrx
detail::ControlThreadOutputBufferEntry SensorAndControl
double norm(const Point &a)
TripleBuffer< Config > bufferConfigUserToNonRt
TripleBuffer< Config > bufferConfigNonRtToPublish
TripleBuffer< Config > bufferConfigNonRtToRt
TripleBuffer< Config > bufferConfigRtToUser
TripleBuffer< Config > bufferConfigRtToOnPublish
std::size_t size() const noexcept
void add(ElementT const &element)
A staged commit prepares multiple layers to be committed.
void add(Layer const &layer)
Stage a layer to be committed later via client.apply(*this)