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())
187 template <
typename NJo
intTaskspaceControllerType>
189 NJointTaskspaceController<NJointTaskspaceControllerType>::createHands()
195 ARMARX_INFO <<
"-- Creating hand: " <<
hands->hands.at(name)->kinematicChainName;
200 template <
typename NJo
intTaskspaceControllerType>
204 std::string taskName =
getClassName() +
"AdditionalTask";
216 while (
getState() == eManagedIceObjectStarted)
222 c.waitForCycleDuration();
227 template <
typename NJo
intTaskspaceControllerType>
231 arm->bufferConfigNonRtToRt.getWriteBuffer() = arm->nonRtConfig;
232 arm->bufferConfigNonRtToRt.commitWrite();
235 template <
typename NJo
intTaskspaceControllerType>
242 if (not rtTargetSafe)
248 template <
typename NJo
intTaskspaceControllerType>
249 std::tuple<bool, bool>
254 bool rtTargetSafe =
true;
255 bool forceTorqueSafe =
true;
256 for (
auto& pair :
limb)
258 auto& arm = pair.second;
259 arm->nonRtConfig = arm->bufferConfigUserToNonRt.getUpToDateReadBuffer();
260 arm->rtStatusInNonRT = arm->bufferRtStatusToNonRt.getUpToDateReadBuffer();
261 rtSafe = rtSafe and pair.second->rtStatusInNonRT.rtSafe;
262 rtTargetSafe = rtTargetSafe and pair.second->rtStatusInNonRT.rtTargetSafe;
263 forceTorqueSafe = forceTorqueSafe and pair.second->rtStatusInNonRT.forceTorqueSafe;
267 hands->nonRTUpdateStatus();
269 return std::make_tuple(rtTargetSafe, forceTorqueSafe);
272 template <
typename NJo
intTaskspaceControllerType>
276 bool rtDesiredPoseSafe =
true;
277 for (
auto& [_, arm] :
limb)
279 rtDesiredPoseSafe = rtDesiredPoseSafe and arm->rtStatusInNonRT.rtTargetSafe;
281 return rtDesiredPoseSafe;
284 template <
typename NJo
intTaskspaceControllerType>
289 bool rtDesiredPoseSafe =
true;
290 for (
auto& [_, arm] :
limb)
292 rtDesiredPoseSafe = rtDesiredPoseSafe and arm->desiredPoseSafeOnActivation.load();
294 return rtDesiredPoseSafe;
297 template <
typename NJo
intTaskspaceControllerType>
301 for (
auto& [_, arm] :
limb)
307 hands->nonRTSetTarget();
311 template <
typename NJo
intTaskspaceControllerType>
315 for (
auto& pair :
limb)
317 if (not pair.second->rtReady)
322 if (not pair.second->rtStatusInNonRT.rtTargetSafe)
325 pair.second->rtStatusInNonRT.currentPose,
326 pair.second->rtStatusInNonRT.desiredPoseUnsafe,
334 template <
typename NJo
intTaskspaceControllerType>
340 arm->rtConfig = arm->bufferConfigNonRtToRt.getUpToDateReadBuffer();
341 arm->rtStatus.deltaT = deltaT;
342 arm->rtStatus.accumulateTime += deltaT;
343 arm->rtStatus.globalPose =
rtGetRobot()->getGlobalPose();
345 arm->controller.ftsensor.updateStatus(arm->rtConfig.ftConfig,
346 arm->rtStatus.currentForceTorque,
347 arm->rtStatus.deltaT,
348 arm->rtFirstRun.load());
349 arm->rtStatus.safeFTGuardOffset.template head<3>() =
350 arm->controller.ftsensor.getSafeGuardForceOffset();
352 arm->sensorDevices.updateJointValues(
353 arm->rtStatus.jointPosition, arm->rtStatus.jointVelocity, arm->rtStatus.jointTorque);
357 arm->bufferRtStatusToNonRt.getWriteBuffer() = arm->rtStatus;
358 arm->bufferRtStatusToNonRt.commitWrite();
359 arm->bufferRtStatusToUser.getWriteBuffer() = arm->rtStatus;
360 arm->bufferRtStatusToUser.commitWrite();
363 template <
typename NJo
intTaskspaceControllerType>
367 const size_t nDoFTorque,
368 const size_t nDoFVelocity,
369 const Eigen::VectorXf& targetTorque,
370 const Eigen::VectorXf& targetVelocity)
372 for (
size_t i = 0; i < nDoFTorque; i++)
375 auto jointIdx = arm->rtStatus.jointIDTorqueMode[i];
376 arm->targetsTorque.at(i)->torque = targetTorque(jointIdx);
377 if (!arm->targetsTorque.at(i)->isValid())
379 arm->targetsTorque.at(i)->torque = 0;
382 for (
size_t i = 0; i < nDoFVelocity; i++)
384 auto jointIdx = arm->rtStatus.jointIDVelocityMode[i];
385 arm->targetsVel.at(i)->velocity = targetVelocity(jointIdx);
387 if (!arm->targetsVel.at(i)->isValid())
389 arm->targetsVel.at(i)->velocity = 0;
392 arm->bufferRtStatusToOnPublish.getWriteBuffer() = arm->rtStatus;
393 arm->bufferRtStatusToOnPublish.commitWrite();
395 arm->bufferConfigRtToOnPublish.getWriteBuffer() = arm->rtConfig;
396 arm->bufferConfigRtToOnPublish.commitWrite();
398 arm->bufferConfigRtToUser.getWriteBuffer() = arm->rtConfig;
399 arm->bufferConfigRtToUser.commitWrite();
401 if (arm->rtFirstRun.load())
403 arm->rtFirstRun.store(
false);
404 arm->rtReady.store(
true);
408 template <
typename NJo
intTaskspaceControllerType>
413 double time_measure = IceUtil::Time::now().toMicroSecondsDouble();
417 arm->controller.run(arm->rtConfig, arm->rtStatus);
418 double time_run_rt = IceUtil::Time::now().toMicroSecondsDouble() - time_measure;
421 arm->rtStatus.nDoFTorque,
422 arm->rtStatus.nDoFVelocity,
423 arm->rtStatus.desiredJointTorque,
424 arm->rtStatus.desiredJointVelocity);
426 double time_set_target = IceUtil::Time::now().toMicroSecondsDouble() - time_measure;
427 time_measure = IceUtil::Time::now().toMicroSecondsDouble() - time_measure;
429 if (time_measure > 200)
432 "run_rt_limb: %.2f\n"
433 "set_target_limb: %.2f\n"
435 time_run_rt - time_measure,
436 time_set_target - time_run_rt,
438 .deactivateSpam(1.0f);
443 template <
typename NJo
intTaskspaceControllerType>
446 const std::string& key,
447 const Eigen::Matrix4f& targetPose,
449 const Eigen::Matrix4f& pose,
459 data.targetPose = targetPose;
460 data.targetPoseMode = targetPoseMode;
463 data.stiffness = stiffness;
469 targetPose, targetPoseMode, pose, vel, ft, stiffness));
473 template <
typename NJo
intTaskspaceControllerType>
482 bool rtReady =
false;
483 for (
const auto& nodeset :
coordinator->getNodesetList())
485 auto& rts =
limb.at(nodeset)->rtStatus;
486 auto& rtc =
limb.at(nodeset)->rtConfig;
487 rtReady =
limb.at(nodeset)->rtReady.load();
489 if constexpr (NJointTaskspaceControllerType::IsCompliant)
493 rtc.desiredPoseFrameMode,
496 rts.currentForceTorque,
501 ARMARX_WARNING <<
"Not implemented yet for controller types without kpImpedance";
510 for (
const auto& nodeset :
coordinator->getNodesetList())
513 limb.at(nodeset)->rtConfig.desiredPoseFrameMode = PoseFrameMode::root;
517 template <
typename NJo
intTaskspaceControllerType>
520 const IceUtil::Time& ,
521 const IceUtil::Time& timeSinceLastIteration)
523 double deltaT = timeSinceLastIteration.toSecondsDouble();
524 for (
auto& pair :
limb)
531 for (
auto& pair :
limb)
533 limbRT(pair.second, deltaT);
537 hands->updateRTStatus(deltaT);
543 template <
typename NJo
intTaskspaceControllerType>
546 const ::armarx::aron::data::dto::DictPtr& dto,
547 const Ice::Current& )
554 auto& arm =
limb.at(pair.first);
556 bool desiredPoseFrameModeSame = prevCfg.limbs.at(pair.first).desiredPoseFrameMode ==
557 pair.second.desiredPoseFrameMode;
559 pair.second.desiredPose,
560 prevCfg.limbs.at(pair.first).desiredPose,
562 "previous desired pose",
563 pair.second.safeDistanceMMToGoal,
564 pair.second.safeRotAngleDegreeToGoal,
565 "updateConfig_" + pair.first))
568 pair.second.desiredPose = prevCfg.limbs.at(pair.first).desiredPose;
570 arm->bufferConfigUserToNonRt.getWriteBuffer() = pair.second;
573 arm->nonRtConfig = arm->bufferConfigUserToNonRt.getWriteBuffer();
575 arm->bufferConfigUserToNonRt.commitWrite();
582 arm->rtConfig = arm->nonRtConfig;
599 template <
typename NJo
intTaskspaceControllerType>
602 const Ice::Current& )
604 for (
auto& pair :
limb)
607 pair.second->bufferConfigRtToUser.getUpToDateReadBuffer();
616 template <
typename NJo
intTaskspaceControllerType>
619 const Ice::Current& )
621 for (
auto& pair :
limb)
624 pair.second->bufferConfigRtToUser.getUpToDateReadBuffer();
633 template <
typename NJo
intTaskspaceControllerType>
636 const std::string& nodeSetName,
637 const bool forceGuard,
638 const bool torqueGuard,
639 const Ice::Current& )
644 it->second.ftConfig.enableSafeGuardForce = forceGuard;
645 it->second.ftConfig.enableSafeGuardTorque = torqueGuard;
646 limb.at(nodeSetName)->controller.ftsensor.enableSafeGuard(forceGuard, torqueGuard);
648 <<
"reset safe guard with force torque sensors: safe? "
649 <<
limb.at(nodeSetName)->controller.ftsensor.isSafe(it->second.ftConfig);
650 limb.at(nodeSetName)->bufferConfigUserToNonRt.getWriteBuffer() = it->second;
651 limb.at(nodeSetName)->bufferConfigUserToNonRt.commitWrite();
656 <<
" found in the controllers.";
661 template <
typename NJo
intTaskspaceControllerType>
664 const std::string& nodeSetName,
665 const Ice::Current& )
670 return limb.at(nodeSetName)->controller.ftsensor.ftSafe.load();
674 <<
" found in the controllers.";
678 template <
typename NJo
intTaskspaceControllerType>
681 const std::string& nodeSetName,
682 const Ice::Current& )
687 return limb.at(nodeSetName)->controller.ftsensor.ftWasNotSafe.load();
691 <<
" found in the controllers.";
695 template <
typename NJo
intTaskspaceControllerType>
698 const std::string& rns,
699 const Ice::Current& )
701 std::vector<float> tcpVel;
702 auto& arm =
limb.at(rns);
703 auto s = arm->bufferRtStatusToUser.getUpToDateReadBuffer();
704 tcpVel.reserve(s.currentTwist.size());
705 for (
int i = 0; i < s.currentTwist.size(); i++)
707 tcpVel.push_back(s.currentTwist[i]);
712 template <
typename NJo
intTaskspaceControllerType>
715 const std::string& nodeSetName,
716 const Ice::Current& )
718 auto search =
limb.find(nodeSetName);
719 if (search ==
limb.end())
722 <<
"does not exist in the controller";
723 return std::vector<double>{};
726 auto& arm =
limb.at(nodeSetName);
727 auto currentPose = arm->bufferRtStatusToOnPublish.getUpToDateReadBuffer().currentPose;
732 template <
typename NJo
intTaskspaceControllerType>
737 const Ice::Current& )
741 for (
size_t i = 0; i < 4; ++i)
743 for (
int j = 0; j < 4; ++j)
745 pair.second.desiredPose(i, j) = targetPoseMap.at(pair.first)[i][j];
748 if (targetNullspaceMap.at(pair.first).size() > 0)
750 const size_t nDoF = pair.second.desiredNullspaceJointAngles.value().size();
752 <<
"the joint numbers does not match";
753 for (
size_t i = 0; i < nDoF; ++i)
755 pair.second.desiredNullspaceJointAngles.value()(i) =
756 targetNullspaceMap.at(pair.first)[i];
759 limb.at(pair.first)->bufferConfigUserToNonRt.getWriteBuffer() = pair.second;
760 limb.at(pair.first)->bufferConfigUserToNonRt.commitWrite();
765 template <
typename NJo
intTaskspaceControllerType>
770 const auto nDoF = arm->jointNames.size();
771 if (!configData.desiredNullspaceJointAngles.has_value())
775 ARMARX_INFO <<
"-- No user defined nullspace target, reset to zero with "
777 configData.desiredNullspaceJointAngles = Eigen::VectorXf::Zero(nDoF);
778 arm->reInitPreActivate.store(
true);
783 arm->bufferConfigRtToUser.getUpToDateReadBuffer().desiredNullspaceJointAngles;
785 <<
"Controller is active, but no user defined nullspace target. \n"
786 "You should first get up-to-date config of this controller and then "
789 " auto cfg = ctrl->getConfig(); \n"
790 " cfg.desiredPose = xxx;\n"
791 " ctrl->updateConfig(cfg);\n"
792 "Now, I decide by myself to use the existing values of nullspace "
794 << currentValue.value();
795 configData.desiredNullspaceJointAngles = currentValue;
802 template <
typename NJo
intTaskspaceControllerType>
809 auto rtStatus = arm->bufferRtStatusToOnPublish.getUpToDateReadBuffer();
810 auto cfgNonRt = arm->bufferConfigNonRtToPublish.getUpToDateReadBuffer();
814 datafields[
"nDoFTorque"] =
new Variant(rtStatus.nDoFTorque);
815 datafields[
"nDoFVelocity"] =
new Variant(rtStatus.nDoFVelocity);
825 datafields[
"cfg.velocity_limit"] =
new Variant(cfgNonRt.velocityLimit);
826 datafields[
"cfg.torque_limit"] =
new Variant(cfgNonRt.torqueLimit);
827 datafields[
"ft.safeGuardForceThreshold"] =
828 new Variant(cfgNonRt.ftConfig.safeGuardForceThreshold);
829 datafields[
"ft.safeGuardTorqueThreshold"] =
830 new Variant(cfgNonRt.ftConfig.safeGuardTorqueThreshold);
833 float positionError =
837 datafields[
"poseError_position"] =
new Variant(positionError);
838 datafields[
"poseError_angle"] =
new Variant(angleError);
850 datafields,
"inertiaInvVelCtrlJoints", rtStatus.inertiaInvVelCtrlJoints);
855 float currentForceNorm = rtStatus.currentForceTorque.template head<3>().norm();
856 float currentTorqueNorm = rtStatus.currentForceTorque.template tail<3>().norm();
857 float safeForceGuardOffsetNorm = rtStatus.safeFTGuardOffset.template head<3>().norm();
858 float safeTorqueGuardOffsetNorm = rtStatus.safeFTGuardOffset.template tail<3>().norm();
859 datafields[
"currentForceNorm"] =
new Variant(currentForceNorm);
860 datafields[
"currentTorqueNorm"] =
new Variant(currentTorqueNorm);
861 datafields[
"safeForceGuardOffsetNorm"] =
new Variant(safeForceGuardOffsetNorm);
862 datafields[
"safeTorqueGuardOffsetNorm"] =
new Variant(safeTorqueGuardOffsetNorm);
863 datafields[
"safeForceGuardDifference"] =
864 new Variant(currentForceNorm - safeForceGuardOffsetNorm);
865 datafields[
"safeTorqueGuardDifference"] =
866 new Variant(currentTorqueNorm - safeTorqueGuardOffsetNorm);
868 datafields[
"rtSafe"] =
new Variant(rtStatus.rtSafe * 1.0);
869 datafields[
"rtTargetSafe"] =
new Variant(rtStatus.rtTargetSafe * 1.0);
870 bool forceTrigger = (not rtStatus.rtSafe) and rtStatus.rtTargetSafe;
871 datafields[
"forceTrigger"] =
new Variant(forceTrigger * 1.0);
872 datafields[
"forceTorqueSafe"] =
new Variant(rtStatus.forceTorqueSafe * 1.0);
881 debugObs->setDebugChannel(
getClassName() +
"_" + arm->kinematicChainName, datafields);
884 template <
typename NJo
intTaskspaceControllerType>
891 for (
auto& pair :
limb)
893 if (not pair.second->rtReady.load())
901 hands->onPublish(debugObs);
905 if (++skipStepCountArviz_ >= skipStepsArviz_)
907 skipStepCountArviz_ = 0;
912 template <
typename NJo
intTaskspaceControllerType>
922 auto& cfg =
coordinator->bufferUserCfgToPublish.getUpToDateReadBuffer();
923 auto data =
coordinator->bufferDataRtToPublish.getUpToDateReadBuffer();
934 using namespace armarx::control::common::coordination::arondto;
935 auto followerIsolation = cfg.followerConnectionMode == ConnectionMode::follower_isolated;
936 auto leftAsLeader = cfg.leadershipMode == LeadershipMode::left_as_leader;
937 auto rightAsLeader = cfg.leadershipMode == LeadershipMode::right_as_leader;
938 auto followerInLeaderLocalFrame =
939 cfg.followerFrameMode == common::arondto::PoseFrameMode::leader;
940 datafields[
"followerIsolation"] =
new Variant(followerIsolation);
941 datafields[
"leftAsLeader"] =
new Variant(leftAsLeader);
942 datafields[
"rightAsLeader"] =
new Variant(rightAsLeader);
943 datafields[
"followerInLeaderLocalFrame"] =
new Variant(followerInLeaderLocalFrame);
945 debugObs->setDebugChannel(
"SyncModeCoordinator", datafields);
948 template <
typename NJo
intTaskspaceControllerType>
959 storedArvizLayers.clear();
966 template <
typename NJo
intTaskspaceControllerType>
976 const double arrowWidth = 2.5F;
979 const auto& rtStatus =
coordinator->bufferDataRtToPublish.getUpToDateReadBuffer();
980 const Eigen::Matrix4f globalPose = Eigen::Matrix4f::Identity();
984 viz::Pose(
"targetPose").pose(globalPose * rtStatus.targetPose).
scale(1.5f));
986 viz::Pose(
"virtualPose").pose(globalPose * rtStatus.virtualPose).
scale(1.25f));
988 viz::Pose(
"currentPose").pose(globalPose * rtStatus.currentPose).
scale(1.0f));
992 const auto objCenter =
common::getPos(globalPose * rtStatus.currentPose);
997 .fromTo(objCenter, objCenter + 1000.0f * rtStatus.virtualVel.head<3>())
998 .
color(simox::Color::blue())
1001 .fromTo(objCenter, objCenter + 1000.0f * rtStatus.poseError.head<3>())
1002 .
color(simox::Color::black())
1003 .
width(arrowWidth));
1009 .fromTo(objCenter, objCenter + 100.0f * rtStatus.currentFT.head<3>())
1010 .
color(simox::Color::yellow())
1011 .
width(arrowWidth));
1013 .fromTo(objCenter, objCenter + 100.0f * rtStatus.currentFT.tail<3>())
1014 .
color(simox::Color::green())
1015 .
width(arrowWidth));
1021 for (
const auto& [_, arm] :
limb)
1023 const auto& cfgNonRt = arm->bufferConfigNonRtToPublish.getUpToDateReadBuffer();
1024 const auto& rtStatus = arm->bufferRtStatusToOnPublish.getUpToDateReadBuffer();
1026 const Eigen::Matrix4f& globalPose = rtStatus.globalPose;
1027 auto addPose = [&](
viz::Layer& layer,
const std::string& suffix =
"")
1030 .pose(globalPose * rtStatus.desiredPose)
1033 .pose(globalPose * rtStatus.currentPose)
1036 const float positionError = (
common::getPos(rtStatus.currentPose) -
1039 const float positionErrorNormalized =
1040 std::fmin((positionError / cfgNonRt.safeDistanceMMToGoal), 1.);
1044 .
color(simox::Color(positionErrorNormalized,
1045 1.0f - positionErrorNormalized,
1047 .
width(arrowWidth));
1055 const bool enableTrajVisualization =
false;
1056 if (enableTrajVisualization)
1058 const std::string name =
"Traj_" + arm->kinematicChainName;
1059 if (storedArvizLayers.count(name) == 0)
1061 storedArvizLayers[name] =
scopedArviz->layer(name);
1063 viz::Layer& layer = storedArvizLayers.at(name);
1065 addPose(layer, std::to_string(
index));
1073 rtStatus.forceImpedance.template head<3>() * 5.0)
1074 .
color(simox::Color::cyan())
1075 .
width(arrowWidth));
1101 template <
typename NJo
intTaskspaceControllerType>
1105 for (
auto& pair :
limb)
1107 pair.second->rtReady.store(
false);
1111 template <
typename NJo
intTaskspaceControllerType>
1114 const std::string& type,
1115 const ::armarx::aron::data::dto::DictPtr& dto,
1116 const Ice::Current& )
1118 ARMARX_INFO <<
"Adding coordinator of type " << type;
1124 coordinator = std::make_shared<common::coordination::SyncCoordination>(dto);
1131 for (
const auto& nodeset :
coordinator->getNodesetList())
1133 if (
limb.find(nodeset) ==
limb.end())
1136 ARMARX_WARNING <<
"The requested nodeset by coordinator " << nodeset
1137 <<
" does not exist in the current controller, disable coordinator";
1148 for (
const auto& nodeset :
coordinator->getNodesetList())
1165 template <
typename NJo
intTaskspaceControllerType>
1168 const Ice::Current& )
1173 ARMARX_INFO <<
"Coordinator is not created yet, use `useCoordinator` to create!!";
1176 for (
const auto& nodeset :
coordinator->getNodesetList())
1178 auto& arm =
limb.at(nodeset);
1179 auto& cfgRT = arm->bufferConfigRtToUser.getUpToDateReadBuffer();
1180 arm->bufferConfigUserToNonRt.getWriteBuffer().desiredPose = cfgRT.desiredPose;
1181 arm->bufferConfigUserToNonRt.commitWrite();
1188 template <
typename NJo
intTaskspaceControllerType>
1197 ARMARX_RT_LOGF_INFO(
"--> rtPreActivateController for %s", arm->kinematicChainName.c_str());
1198 VirtualRobot::RobotNodeSetPtr rns =
rtGetRobot()->getRobotNodeSet(arm->kinematicChainName);
1199 Eigen::Matrix4f currentPose = rns->getTCP()->getPoseInRootFrame();
1200 auto quat = VirtualRobot::MathTools::eigen4f2quat(currentPose);
1202 "[ %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f ].",
1211 arm->desiredPoseSafeOnActivation =
1213 arm->rtConfig.desiredPose,
1214 arm->rtConfig.safeDistanceMMToGoal,
1215 arm->rtConfig.safeRotAngleDegreeToGoal);
1218 if (arm->reInitPreActivate.load())
1225 arm->rtConfig.desiredNullspaceJointAngles = rns->getJointValuesEigen();
1227 arm->reInitPreActivate.store(
false);
1231 arm->rtConfig.desiredPose = currentPose;
1232 arm->nonRtConfig = arm->rtConfig;
1234 arm->bufferConfigUserToNonRt.reinitAllBuffers(arm->rtConfig);
1235 arm->bufferConfigNonRtToRt.reinitAllBuffers(arm->rtConfig);
1236 arm->bufferConfigRtToOnPublish.reinitAllBuffers(arm->rtConfig);
1237 arm->bufferConfigNonRtToPublish.reinitAllBuffers(arm->rtConfig);
1238 arm->bufferConfigRtToUser.reinitAllBuffers(arm->rtConfig);
1241 arm->sensorDevices.updateJointValues(arm->rtStatus.jointPosition,
1242 arm->rtStatus.jointVelocity,
1243 arm->rtStatus.jointTorque);
1244 arm->rtStatus.rtPreActivate(currentPose);
1245 arm->rtStatus.globalPose =
rtGetRobot()->getGlobalPose();
1246 arm->rtStatusInNonRT = arm->rtStatus;
1247 arm->nonRTDeltaT = 0.0;
1248 arm->nonRTAccumulateTime = 0.0;
1249 arm->bufferRtStatusToOnPublish.reinitAllBuffers(arm->rtStatus);
1250 arm->bufferRtStatusToNonRt.reinitAllBuffers(arm->rtStatus);
1251 arm->bufferRtStatusToUser.reinitAllBuffers(arm->rtStatus);
1258 template <
typename NJo
intTaskspaceControllerType>
1261 const Ice::Current& current)
1264 <<
"NJointTaskspaceController<NJointTaskspaceControllerType>::activateController";
1269 scopedArviz->updateComponentName(
"NJointTaskspaceController");
1276 hands->nonRtActivateController();
1281 template <
typename NJo
intTaskspaceControllerType>
1284 const Ice::Current& current)
1287 <<
"NJointTaskspaceController<NJointTaskspaceControllerType>::deactivateController";
1294 template <
typename NJo
intTaskspaceControllerType>
1299 for (
auto& pair :
limb)
1303 userConfig.limbs.at(pair.first) = pair.second->rtConfig;
1307 hands->rtPreActivate();
1312 template <
typename NJo
intTaskspaceControllerType>
1318 limb.at(pair.first)->rtPostDeactivate();
1331 template <
typename NJo
intTaskspaceControllerType>
1344 template <
typename NJo
intTaskspaceControllerType>
1348 const std::map<std::string, ConstControlDevicePtr>& ,
1349 const std::map<std::string, ConstSensorDevicePtr>&)
1355 ::armarx::WidgetDescription::WidgetSeq widgets;
1358 LabelPtr label =
new Label;
1359 label->text =
"select a controller config";
1361 StringComboBoxPtr cfgBox =
new StringComboBox;
1362 cfgBox->name =
"config_box";
1363 cfgBox->defaultIndex = 0;
1364 cfgBox->multiSelect =
false;
1366 cfgBox->options = std::vector<std::string>{
1367 "default_a7_with_hands",
1370 "default_a7_zero_torque",
1372 "default_a6_with_hands",
1374 "default_a6_zero_torque",
1378 layout->children.emplace_back(label);
1379 layout->children.emplace_back(cfgBox);
1382 layout->children.insert(layout->children.end(), widgets.begin(), widgets.end());
1387 template <
typename NJo
intTaskspaceControllerType>
1392 auto cfgName = values.at(
"config_box")->getString();
1395 "controller_config/" + std::string(NJointTaskspaceControllerType::TypeName) +
"/" +
1403 return new ConfigurableNJointControllerConfig{cfgDTO.toAronDTO()};
1414 const NJointControllerConfigPtr& config,
1424 return "TSMixImpVel";
1430 const auto nDoF =
static_cast<Eigen::Index
>(arm->jointNames.size());
1432 const auto checkSize = [nDoF](
const auto& v) {
ARMARX_CHECK_EQUAL(v.rows(), nDoF); };
1433 const auto checkNonNegative = [](
const auto& v) {
ARMARX_CHECK((v.array() >= 0).all()); };
1434 checkSize(configData.desiredNullspaceJointAngles.value());
1435 checkSize(configData.kdNullspaceTorque);
1436 checkSize(configData.kpNullspaceTorque);
1437 checkSize(configData.kdNullspaceVel);
1438 checkSize(configData.kpNullspaceVel);
1440 checkNonNegative(configData.kdNullspaceTorque);
1441 checkNonNegative(configData.kpNullspaceTorque);
1442 checkNonNegative(configData.kpNullspaceVel);
1443 checkNonNegative(configData.kdNullspaceVel);
1444 checkNonNegative(configData.kdImpedance);
1445 checkNonNegative(configData.kpImpedance);
1451 auto cfg = arm->bufferConfigRtToOnPublish.getUpToDateReadBuffer();
1456 if (cfg.desiredNullspaceJointAngles.has_value())
1459 datafields,
"desiredNullspaceJointAngles", cfg.desiredNullspaceJointAngles.value());
1462 datafields[
"poseError_threshold_position"] =
new Variant(cfg.safeDistanceMMToGoal);
1463 datafields[
"poseError_threshold_angle"] =
new Variant(cfg.safeRotAngleDegreeToGoal);
1464 datafields[
"safeForceGuardThreshold"] =
new Variant(cfg.ftConfig.safeGuardForceThreshold);
1465 datafields[
"safeTorqueGuardThreshold"] =
new Variant(cfg.ftConfig.safeGuardTorqueThreshold);
1475 const NJointControllerConfigPtr& config,
1492 const auto nDoF =
static_cast<Eigen::Index
>(arm->jointNames.size());
1494 const auto checkSize = [nDoF](
const auto& v) {
ARMARX_CHECK_EQUAL(v.rows(), nDoF); };
1495 const auto checkNonNegative = [](
const auto& v) {
ARMARX_CHECK((v.array() >= 0).all()); };
1496 checkSize(configData.desiredNullspaceJointAngles.value());
1497 checkSize(configData.kdNullspaceTorque);
1498 checkSize(configData.kpNullspaceTorque);
1500 checkNonNegative(configData.kdNullspaceTorque);
1501 checkNonNegative(configData.kpNullspaceTorque);
1502 checkNonNegative(configData.kdImpedance);
1503 checkNonNegative(configData.kpImpedance);
1509 auto cfg = arm->bufferConfigRtToOnPublish.getUpToDateReadBuffer();
1512 if (cfg.desiredNullspaceJointAngles.has_value())
1515 datafields,
"desiredNullspaceJointAngles", cfg.desiredNullspaceJointAngles.value());
1518 datafields[
"poseError_threshold_position"] =
new Variant(cfg.safeDistanceMMToGoal);
1519 datafields[
"poseError_threshold_angle"] =
new Variant(cfg.safeRotAngleDegreeToGoal);
1520 datafields[
"safeForceGuardThreshold"] =
new Variant(cfg.ftConfig.safeGuardForceThreshold);
1521 datafields[
"safeTorqueGuardThreshold"] =
new Variant(cfg.ftConfig.safeGuardTorqueThreshold);
1531 const NJointControllerConfigPtr& config,
1548 const auto nDoF =
static_cast<Eigen::Index
>(arm->jointNames.size());
1550 const auto checkSize = [nDoF](
const auto& v) {
ARMARX_CHECK_EQUAL(v.rows(), nDoF); };
1551 const auto checkNonNegative = [](
const auto& v) {
ARMARX_CHECK((v.array() >= 0).all()); };
1552 checkSize(configData.desiredNullspaceJointAngles.value());
1553 checkSize(configData.kdNullspaceTorque);
1554 checkSize(configData.kpNullspaceTorque);
1556 checkNonNegative(configData.kdNullspaceTorque);
1557 checkNonNegative(configData.kpNullspaceTorque);
1558 checkNonNegative(configData.kdImpedance);
1559 checkNonNegative(configData.kpImpedance);
1565 auto cfg = arm->bufferConfigRtToOnPublish.getUpToDateReadBuffer();
1568 if (cfg.desiredNullspaceJointAngles.has_value())
1571 datafields,
"desiredNullspaceJointAngles", cfg.desiredNullspaceJointAngles.value());
1574 datafields[
"poseError_threshold_position"] =
new Variant(cfg.safeDistanceMMToGoal);
1575 datafields[
"poseError_threshold_angle"] =
new Variant(cfg.safeRotAngleDegreeToGoal);
1576 datafields[
"safeForceGuardThreshold"] =
new Variant(cfg.ftConfig.safeGuardForceThreshold);
1577 datafields[
"safeTorqueGuardThreshold"] =
new Variant(cfg.ftConfig.safeGuardTorqueThreshold);
1587 const NJointControllerConfigPtr& config,
1603 const auto nDoF =
static_cast<Eigen::Index
>(arm->jointNames.size());
1605 const auto checkSize = [nDoF](
const auto& v) {
ARMARX_CHECK_EQUAL(v.rows(), nDoF); };
1606 const auto checkNonNegative = [](
const auto& v) {
ARMARX_CHECK((v.array() >= 0).all()); };
1607 checkSize(configData.desiredNullspaceJointAngles.value());
1608 checkSize(configData.kdNullspaceVel);
1609 checkSize(configData.kpNullspaceVel);
1611 checkNonNegative(configData.kpNullspaceVel);
1612 checkNonNegative(configData.kdNullspaceVel);
1618 auto cfg = arm->bufferConfigRtToOnPublish.getUpToDateReadBuffer();
1621 if (cfg.desiredNullspaceJointAngles.has_value())
1624 datafields,
"desiredNullspaceJointAngles", cfg.desiredNullspaceJointAngles.value());
1627 datafields[
"poseError_threshold_position"] =
new Variant(cfg.safeDistanceMMToGoal);
1628 datafields[
"poseError_threshold_angle"] =
new Variant(cfg.safeRotAngleDegreeToGoal);
1629 datafields[
"safeForceGuardThreshold"] =
new Variant(cfg.ftConfig.safeGuardForceThreshold);
1630 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.
#define ARMARX_VERBOSE
The logging level for verbose information.
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)