25#include <VirtualRobot/MathTools.h>
26#include <VirtualRobot/Nodes/RobotNode.h>
27#include <VirtualRobot/RobotNodeSet.h>
47 "NJointTaskspaceAdmittanceController");
55 arm->kinematicChainName = nodeSetName;
56 VirtualRobot::RobotNodeSetPtr rtRns =
57 rtGetRobot()->getRobotNodeSet(arm->kinematicChainName);
58 VirtualRobot::RobotNodeSetPtr nonRtRns =
59 nonRtRobotPtr->getRobotNodeSet(arm->kinematicChainName);
62 ARMARX_IMPORTANT <<
"Creating Taskspace Impedance controller with kinematic chain: "
63 << arm->kinematicChainName <<
" with num of joints: (RT robot) "
64 << rtRns->getSize() <<
", and (non-RT robot) " << nonRtRns->getSize();
66 arm->controller.initialize(nonRtRns, rtRns);
67 arm->controller.ftsensor.initialize(rtRns,
robotUnit, cfg.ftConfig);
68 arm->jointNames.clear();
69 std::vector<size_t> jointIDTorqueMode;
70 std::vector<size_t> jointIDVelocityMode;
71 for (
size_t i = 0; i < rtRns->getSize(); ++i)
73 std::string jointName = rtRns->getNode(i)->getName();
74 arm->jointNames.push_back(jointName);
78 auto* casted_ct = ct->
asA<ControlTarget1DoFActuatorTorque>();
80 arm->targets.push_back(casted_ct);
84 arm->sensorDevices.append(sv, jointName);
85 jointIDTorqueMode.push_back(i);
90 arm->nonRtConfig = cfg;
91 auto nDoF = rtRns->getSize();
92 arm->rtStatus.reset(nDoF, jointIDTorqueMode, jointIDVelocityMode);
97 const NJointControllerConfigPtr& config,
103 ConfigPtrT cfg = ConfigPtrT::dynamicCast(config);
113 limb.emplace(pair.first, std::make_unique<ArmData>());
125 <<
hands->hands.at(pair.first)->kinematicChainName;
134 return "NJointTaskspaceAdmittanceController";
140 std::string taskName =
getClassName() +
"AdditionalTask";
152 while (
getState() == eManagedIceObjectStarted)
158 c.waitForCycleDuration();
166 arm->bufferConfigNonRtToRt.getWriteBuffer() = arm->nonRtConfig;
167 arm->bufferConfigNonRtToRt.commitWrite();
186 for (
auto& pair :
limb)
188 auto& arm = pair.second;
189 arm->nonRtConfig = arm->bufferConfigUserToNonRt.getUpToDateReadBuffer();
190 arm->rtStatusInNonRT = arm->bufferRtStatusToNonRt.getUpToDateReadBuffer();
191 rtSafe = rtSafe and pair.second->rtStatusInNonRT.rtSafe;
195 hands->nonRTUpdateStatus();
203 for (
auto& pair :
limb)
209 hands->nonRTSetTarget();
216 for (
auto& pair :
limb)
218 if (not pair.second->rtReady)
221 if (not pair.second->rtStatusInNonRT.rtTargetSafe)
223 pair.second->rtStatusInNonRT =
224 pair.second->bufferRtStatusToNonRt.getUpToDateReadBuffer();
226 pair.second->rtStatusInNonRT.currentPose,
227 pair.second->nonRtConfig.desiredPose,
238 arm->rtConfig = arm->bufferConfigNonRtToRt.getUpToDateReadBuffer();
239 arm->rtStatus.deltaT = deltaT;
240 arm->rtStatus.accumulateTime += deltaT;
242 if (arm->rtFirstRun.load())
244 arm->controller.firstRun();
247 arm->controller.ftsensor.updateStatus(arm->rtConfig.ftConfig,
248 arm->rtStatus.currentForceTorque,
249 arm->rtStatus.deltaT,
250 arm->rtFirstRun.load());
252 arm->sensorDevices.updateJointValues(
253 arm->rtStatus.jointPosition, arm->rtStatus.jointVelocity, arm->rtStatus.jointTorque);
256 arm->bufferRtStatusToNonRt.getWriteBuffer() = arm->rtStatus;
257 arm->bufferRtStatusToNonRt.commitWrite();
258 arm->bufferRtStatusToUser.getWriteBuffer() = arm->rtStatus;
259 arm->bufferRtStatusToUser.commitWrite();
264 const Eigen::VectorXf& targetTorque)
266 for (
unsigned int i = 0; i < targetTorque.size(); i++)
268 arm->targets.at(i)->torque = targetTorque(i);
269 if (!arm->targets.at(i)->isValid())
271 arm->targets.at(i)->torque = 0;
274 arm->bufferRtStatusToOnPublish.getWriteBuffer() = arm->rtStatus;
275 arm->bufferRtStatusToOnPublish.commitWrite();
277 arm->bufferConfigRtToOnPublish.getWriteBuffer() = arm->rtConfig;
278 arm->bufferConfigRtToOnPublish.commitWrite();
280 arm->bufferConfigRtToUser.getWriteBuffer() = arm->rtConfig;
281 arm->bufferConfigRtToUser.commitWrite();
283 if (arm->rtFirstRun.load())
285 arm->rtFirstRun.store(
false);
286 arm->rtReady.store(
true);
293 double time_measure = IceUtil::Time::now().toMicroSecondsDouble();
295 double time_update_status = IceUtil::Time::now().toMicroSecondsDouble() - time_measure;
297 arm->controller.run(arm->rtConfig, arm->rtStatus);
298 double time_run_rt = IceUtil::Time::now().toMicroSecondsDouble() - time_measure;
302 double time_set_target = IceUtil::Time::now().toMicroSecondsDouble() - time_measure;
303 time_measure = IceUtil::Time::now().toMicroSecondsDouble() - time_measure;
305 if (time_measure > 100)
308 "time_update_status: %.2f\n"
309 "run_rt_limb: %.2f\n"
310 "set_target_limb: %.2f\n"
313 time_run_rt - time_update_status,
314 time_set_target - time_run_rt,
316 .deactivateSpam(1.0f);
322 const IceUtil::Time& timeSinceLastIteration)
324 double deltaT = timeSinceLastIteration.toSecondsDouble();
325 for (
auto& pair :
limb)
327 limbRT(pair.second, deltaT);
331 hands->updateRTStatus(deltaT);
338 const Ice::Current& iceCurrent)
347 pair.second.desiredPose,
348 prevCfg.limbs.at(pair.first).desiredPose,
350 "previous desired pose",
351 pair.second.safeDistanceMMToGoal,
352 pair.second.safeRotAngleDegreeToGoal,
353 "updateConfig_" + pair.first))
356 pair.second.desiredPose = prevCfg.limbs.at(pair.first).desiredPose;
358 limb.at(pair.first)->bufferConfigUserToNonRt.getWriteBuffer() = pair.second;
359 limb.at(pair.first)->bufferConfigUserToNonRt.commitWrite();
370 for (
auto& pair :
limb)
373 pair.second->bufferConfigRtToUser.getUpToDateReadBuffer();
384 const bool forceGuard,
385 const bool torqueGuard,
386 const Ice::Current& iceCurrent)
391 it->second.ftConfig.enableSafeGuardForce = forceGuard;
392 it->second.ftConfig.enableSafeGuardTorque = torqueGuard;
393 limb.at(nodeSetName)->controller.ftsensor.enableSafeGuard(forceGuard, torqueGuard);
395 <<
"reset safe guard with force torque sensors: safe? "
396 <<
limb.at(nodeSetName)->controller.ftsensor.isSafe(it->second.ftConfig);
397 limb.at(nodeSetName)->bufferConfigUserToNonRt.getWriteBuffer() = it->second;
398 limb.at(nodeSetName)->bufferConfigUserToNonRt.commitWrite();
403 <<
" found in the controllers.";
410 const Ice::Current& iceCurrent)
415 return limb.at(nodeSetName)->controller.ftsensor.ftSafe.load();
420 <<
" found in the controllers.";
427 const Ice::Current& iceCurrent)
429 std::vector<float> tcpVel;
430 auto& arm =
limb.at(rns);
431 auto s = arm->bufferRtStatusToUser.getUpToDateReadBuffer();
432 for (
int i = 0; i < s.currentTwist.size(); i++)
434 tcpVel.push_back(s.currentTwist[i]);
443 const Ice::Current& iceCurrent)
447 for (
size_t i = 0; i < 4; ++i)
449 for (
int j = 0; j < 4; ++j)
451 pair.second.desiredPose(i, j) = targetPoseMap.at(pair.first)[i][j];
454 if (targetNullspaceMap.at(pair.first).size() > 0)
456 const size_t nDoF = pair.second.desiredNullspaceJointAngles.value().size();
458 <<
"the joint numbers does not match";
459 for (
size_t i = 0; i < nDoF; ++i)
461 pair.second.desiredNullspaceJointAngles.value()(i) =
462 targetNullspaceMap.at(pair.first)[i];
465 limb.at(pair.first)->bufferConfigUserToNonRt.getWriteBuffer() = pair.second;
466 limb.at(pair.first)->bufferConfigUserToNonRt.commitWrite();
474 const auto nDoF = arm->jointNames.size();
477 const auto checkNonNegative = [](
const auto& v) {
ARMARX_CHECK((v.array() >= 0).all()); };
479 if (!configData.desiredNullspaceJointAngles.has_value())
483 ARMARX_INFO <<
"No user defined nullspace target, reset to zero with "
485 configData.desiredNullspaceJointAngles = Eigen::VectorXf::Zero(nDoF);
486 arm->reInitPreActivate.store(
true);
491 arm->bufferConfigRtToUser.getUpToDateReadBuffer().desiredNullspaceJointAngles;
493 <<
"Controller is active, but no user defined nullspace target. \n"
494 "You should first get up-to-date config of this controller and then update "
496 " auto cfg = ctrl->getConfig(); \n"
497 " cfg.desiredPose = xxx;\n"
498 " ctrl->updateConfig(cfg);\n"
499 "Now, I decide by myself to use the existing values of nullspace target\n"
500 << currentValue.value();
501 configData.desiredNullspaceJointAngles = currentValue;
505 checkSize(configData.desiredNullspaceJointAngles.value());
506 checkSize(configData.kdNullspaceTorque);
507 checkSize(configData.kpNullspaceTorque);
509 checkNonNegative(configData.kdNullspaceTorque);
510 checkNonNegative(configData.kpNullspaceTorque);
511 checkNonNegative(configData.kdImpedance);
512 checkNonNegative(configData.kpImpedance);
520 auto rtData = arm->bufferConfigRtToOnPublish.getUpToDateReadBuffer();
521 auto rtStatus = arm->bufferRtStatusToOnPublish.getUpToDateReadBuffer();
537 debugObs->setDebugChannel(
getClassName() +
"_" + arm->kinematicChainName, datafields);
545 for (
auto& pair :
limb)
547 if (not pair.second->rtReady.load())
556 for (
auto& pair :
limb)
558 pair.second->rtReady.store(
false);
566 for (
auto& pair :
limb)
568 pair.second->rtReady.store(
false);
575 VirtualRobot::RobotNodeSetPtr rns =
rtGetRobot()->getRobotNodeSet(arm->kinematicChainName);
576 const auto& currentPose = rns->getTCP()->getPoseInRootFrame();
577 auto quat = VirtualRobot::MathTools::eigen4f2quat(currentPose);
579 "[ %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f ].",
588 if (arm->reInitPreActivate.load())
590 arm->rtConfig.desiredNullspaceJointAngles.value() = rns->getJointValuesEigen();
591 arm->rtConfig.desiredPose = currentPose;
593 arm->bufferConfigUserToNonRt.reinitAllBuffers(arm->rtConfig);
594 arm->reInitPreActivate.store(
false);
597 arm->nonRtConfig = arm->rtConfig;
598 arm->bufferConfigNonRtToRt.reinitAllBuffers(arm->rtConfig);
599 arm->bufferConfigRtToOnPublish.reinitAllBuffers(arm->rtConfig);
600 arm->bufferConfigRtToUser.reinitAllBuffers(arm->rtConfig);
603 arm->sensorDevices.updateJointValues(arm->rtStatus.jointPosition,
604 arm->rtStatus.jointVelocity,
605 arm->rtStatus.jointTorque);
606 arm->rtStatus.rtPreActivate(currentPose);
608 arm->rtStatusInNonRT = arm->rtStatus;
609 arm->nonRTDeltaT = 0.0;
610 arm->nonRTAccumulateTime = 0.0;
611 arm->bufferRtStatusToOnPublish.reinitAllBuffers(arm->rtStatus);
612 arm->bufferRtStatusToNonRt.reinitAllBuffers(arm->rtStatus);
613 arm->bufferRtStatusToUser.reinitAllBuffers(arm->rtStatus);
616 arm->controller.preactivateInit(rns);
622 for (
auto& pair :
limb)
626 userConfig.limbs.at(pair.first) = pair.second->rtConfig;
630 hands->rtPreActivate();
647 const std::map<std::string, ConstControlDevicePtr>& controlDevices,
648 const std::map<std::string, ConstSensorDevicePtr>&)
654 ::armarx::WidgetDescription::WidgetSeq widgets;
657 LabelPtr label =
new Label;
658 label->text =
"select a controller config";
660 StringComboBoxPtr cfgBox =
new StringComboBox;
661 cfgBox->name =
"config_box";
662 cfgBox->defaultIndex = 0;
663 cfgBox->multiSelect =
false;
665 cfgBox->options = std::vector<std::string>{
"default",
"default_right",
"default_right_a7"};
668 layout->children.emplace_back(label);
669 layout->children.emplace_back(cfgBox);
672 layout->children.insert(layout->children.end(), widgets.begin(), widgets.end());
681 auto cfgName = values.at(
"config_box")->getString();
684 "controller_config/NJointTaskspaceAdmittanceController/" + cfgName +
".json");
691 return new ConfigurableNJointControllerConfig{cfgDTO.toAronDTO()};
#define ARMARX_RT_LOGF_WARN(...)
#define ARMARX_RT_LOGF_INFO(...)
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
const SensorValueBase * useSensorValue(const std::string &sensorDeviceName) const
Get a const ptr to the given SensorDevice's SensorValue.
void runTask(const std::string &taskName, Task &&task)
Executes a given task in a separate thread from the Application ThreadPool.
const VirtualRobot::RobotPtr & useSynchronizedRtRobot(bool updateCollisionModel=false)
Requests a VirtualRobot for use in rtRun *.
const VirtualRobot::RobotPtr & rtGetRobot()
TODO make protected and use attorneys.
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.
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
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
NJointControllerBase interface.
ConfigurableNJointControllerConfigPtr ConfigPtrT
void limbRT(ArmPtr &arm, const double deltaT)
void limbNonRT(ArmPtr &arm)
static ConfigPtrT GenerateConfigFromVariants(const StringVariantBaseMap &values)
::armarx::aron::data::dto::DictPtr getConfig(const Ice::Current &iceCurrent=Ice::emptyCurrent) override
bool additionalTaskUpdateStatus()
Ice::FloatSeq getTCPVel(const std::string &rns, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
void limbReInit(ArmPtr &arm)
std::map< std::string, ArmPtr > limb
bool isSafeForceTorque(const std::string &nodeSetName, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
-----------------------------— Other interaces ----------------------------------------—
void limbRTSetTarget(ArmPtr &arm, const Eigen::VectorXf &targetTorque)
void validateConfigData(Config &config, ArmPtr &arm)
core::HandControlPtr hands
void enableSafeGuardForceTorque(const std::string &nodeSetName, const bool forceGuard, const bool torqueGuard, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
void rtPostDeactivateController() override
This function is called after the controller is deactivated.
virtual void additionalTask()
void rtRun(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration) override
TODO make protected and use attorneys.
void limbInit(const std::string nodeSetName, ArmPtr &arm, Config &cfg, VirtualRobot::RobotPtr &nonRtRobotPtr)
std::unique_ptr< ArmData > ArmPtr
void additionalTaskSetTarget()
void updateConfig(const ::armarx::aron::data::dto::DictPtr &dto, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
NJointController interface.
bool updateTargetPose(const TargetPoseMap &targetPoseMap, const TargetNullspaceMap &targetNullspaceMap, const Ice::Current &=Ice::emptyCurrent) override
NJointTaskspaceAdmittanceController(const RobotUnitPtr &robotUnit, const NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &)
void limbPublish(ArmPtr &arm, const DebugObserverInterfacePrx &debugObs)
void handleRTNotSafeInNonRT()
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 toggleGravityCompensation(const bool toggle, const Ice::Current &) override
ft sensor
law::TaskspaceAdmittanceController::Config Config
#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_WARNING
The logging level for unexpected behaviour, but not a serious problem.
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)
void debugEigenVec(StringVariantBaseMap &datafields, const std::string &name, Eigen::VectorXf vec)
void debugEigenPose(StringVariantBaseMap &datafields, const std::string &name, Eigen::Matrix4f pose)
NJointControllerRegistration< NJointTaskspaceAdmittanceController > registrationControllerNJointTaskspaceAdmittanceController("NJointTaskspaceAdmittanceController")
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