122 if (not adaptionReady.load())
126 adaptionCfg = bufferAdaptationConfigUserToNonRt.getUpToDateReadBuffer();
128 std::lock_guard<std::recursive_mutex> lock(
mtx_mps);
132 std::map<std::string, bool> flagMPToStop;
133 for (
auto& pair :
limb)
135 flagMPToStop[pair.first] =
limb.at(pair.first)->controller.ftsensor.ftSafe.load();
138 const double timeScalingFactor =
139 adaptionCfg.timeScalingFactor.has_value()
140 ? fmin(fmax(adaptionCfg.timeScalingFactor.value(), 0.25), 4.)
143 const double sizeScalingFactor =
144 adaptionCfg.sizeScalingFactor.has_value() ? adaptionCfg.sizeScalingFactor.value() : 1.;
146 std::map<std::string, bool> mpRunning;
147 for (
auto& _mp :
mps)
149 const auto mpNodeSet = _mp.second.mp->getNodeSetName();
150 auto search = flagMPToStop.find(mpNodeSet);
151 if (_mp.second.mp->isStopRequested())
153 _mp.second.mp->stop();
154 ARMARX_INFO <<
"user requested to stop mp execution at canonical value: "
155 << _mp.second.mp->getCanonicalValue();
157 if (search != flagMPToStop.end() and flagMPToStop.at(mpNodeSet) and
158 _mp.second.mp->isRunning() and
159 (
limb.at(mpNodeSet)->controller.ftsensor.isForceGuardEnabled() or
160 limb.at(mpNodeSet)->controller.ftsensor.isTorqueGuardEnabled()))
162 _mp.second.mp->stop();
163 ARMARX_INFO <<
"Due to force/torque safe guard, MP " << _mp.second.mp->getMPName()
164 <<
" is stopped at " << _mp.second.mp->getCanonicalValue();
166 mpRunning[_mp.second.mp->getMPName()] = _mp.second.mp->isRunning();
167 if (_mp.second.mp->isFinished())
171 if (_mp.second.mp->getRole() ==
"taskspace")
173 auto& arm =
limb.at(_mp.second.mp->getNodeSetName());
174 if (_mp.second.mp->isFirstRun())
179 const std::vector<double> mpStart = _mp.second.mp->getStartVec();
182 arm->rtStatusInNonRT.currentPose,
185 "TSMP initial start pose",
186 arm->nonRtConfig.safeDistanceMMToGoal,
187 arm->nonRtConfig.safeRotAngleDegreeToGoal,
188 _mp.second.mp->getMPName() +
"mp_set_target"))
191 <<
"-- deviation from current pose too large, reset MP start pose";
192 _mp.second.mp->validateInitialState(
197 mp::TSMPInputPtr in = std::dynamic_pointer_cast<mp::TSMPInput>(_mp.second.input);
198 in->pose = arm->rtStatusInNonRT.currentPose;
199 in->vel = arm->rtStatusInNonRT.currentTwist;
200 in->deltaT = arm->rtStatusInNonRT.deltaT * timeScalingFactor;
202 else if (_mp.second.mp->getRole() ==
"nullspace")
204 auto& arm =
limb.at(_mp.second.mp->getNodeSetName());
205 mp::JSMPInputPtr in = std::dynamic_pointer_cast<mp::JSMPInput>(_mp.second.input);
207 arm->rtStatusInNonRT.jointPosition.size());
208 in->angleRadian = arm->rtStatusInNonRT.jointPosition;
209 in->angularVel = arm->rtStatusInNonRT.qvelFiltered;
210 in->deltaT = arm->rtStatusInNonRT.deltaT * timeScalingFactor;
212 else if (_mp.second.mp->getRole() ==
"hand")
214 auto&
hand =
hands->hands.at(_mp.second.mp->getNodeSetName());
215 mp::JSMPInputPtr in = std::dynamic_pointer_cast<mp::JSMPInput>(_mp.second.input);
216 ARMARX_ERROR <<
"Fix the following line, see template.h";
219 in->deltaT =
hand->bufferRTToNonRT.getReadBuffer().deltaT * timeScalingFactor;
222 if (not rtTargetSafe)
235 for (
auto& _mp :
mps)
237 if (not mpRunning.at(_mp.second.mp->getMPName()))
241 for (
auto& ftGuard :
mpConfig.ftGuard)
243 if (ftGuard.mpName == _mp.second.mp->getMPName())
245 bool const forceGuard =
246 (ftGuard.force.has_value() and
247 ftGuard.force.value() >= _mp.second.mp->getCanonicalValue());
248 bool const torqueGuard =
249 (ftGuard.torque.has_value() and
250 ftGuard.torque.value() >= _mp.second.mp->getCanonicalValue());
252 auto& arm =
limb.at(_mp.second.mp->getNodeSetName());
253 bool const resetForce =
254 not arm->controller.ftsensor.isForceGuardEnabled() and forceGuard;
255 bool const resetTorque =
256 not arm->controller.ftsensor.isTorqueGuardEnabled() and torqueGuard;
257 if (resetForce or resetTorque)
259 ARMARX_INFO <<
"Triggering force torque safety guard for "
260 << arm->kinematicChainName <<
" at can value "
261 << _mp.second.mp->getCanonicalValue();
264 arm->nonRtConfig.ftConfig.enableSafeGuardForce = forceGuard;
265 arm->nonRtConfig.ftConfig.enableSafeGuardTorque = torqueGuard;
266 arm->controller.ftsensor.enableSafeGuard(resetForce, resetTorque);
270 if (_mp.second.mp->getRole() ==
"taskspace")
272 const auto& nodeSetName = _mp.second.mp->getNodeSetName();
273 auto& cfg = adaptionCfg.cfg.at(nodeSetName);
274 auto& s = adaptionStatus.at(nodeSetName);
275 auto& arm =
limb.at(nodeSetName);
277 std::dynamic_pointer_cast<mp::TSMPOutput>(_mp.second.output);
281 arm->nonRtConfig.desiredPose = s.desiredPose;
283 arm->rtStatusInNonRT.currentPose,
284 arm->nonRtConfig.desiredPose,
286 "desiredPose for RT",
287 arm->nonRtConfig.safeDistanceMMToGoal,
288 arm->nonRtConfig.safeRotAngleDegreeToGoal,
289 _mp.second.mp->getMPName() +
"mp_set_target");
290 arm->nonRtConfig.desiredTwist = out->vel;
293 if (arm->rtStatusInNonRT.rtTargetSafe)
295 const float desiredVelZ =
296 cfg.kpf * (cfg.targetForce - arm->rtStatusInNonRT.currentForceTorque(2));
297 arm->nonRtConfig.desiredTwist(2) -= desiredVelZ;
299 arm->nonRtConfig.desiredTwist.tail<3>().setZero();
301 const float dT =
static_cast<float>(arm->rtStatusInNonRT.deltaT);
304 auto& adaptKImp = s.kpImpedance;
305 auto& adaptKVel = s.kpCartesianVel;
307 const Eigen::Vector2f& currentForceXY =
308 arm->rtStatusInNonRT.currentForceTorque.head<2>();
309 if (currentForceXY.norm() > cfg.deadZoneForce)
312 const Eigen::Vector2f dragForce =
313 currentForceXY - cfg.deadZoneForce * currentForceXY / currentForceXY.norm();
314 adaptKImp.head<2>().array() -= dT * cfg.adaptForceCoeff * dragForce.norm();
315 adaptKVel.head<2>().array() -= dT * cfg.adaptForceCoeff * dragForce.norm();
320 adaptKImp.head<2>().array() += fabs(dT * cfg.adaptCoeff);
321 adaptKVel.head<2>().array() += fabs(dT * cfg.adaptCoeff);
325 adaptKImp.head<2>() = adaptKImp.head<2>()
327 .min(arm->nonRtConfig.kpImpedance.head<2>().array())
329 adaptKVel.head<2>() = adaptKVel.head<2>()
331 .min(arm->nonRtConfig.kpCartesianVel.head<2>().array())
334 arm->nonRtConfig.kpImpedance = adaptKImp;
335 arm->nonRtConfig.kpCartesianVel = adaptKVel;
338 arm->nonRtConfig.desiredTwist.head<2>() *= sizeScalingFactor * timeScalingFactor;
341 arm->nonRtConfig.desiredPose.block<3, 1>(0, 3) +=
342 dT * arm->nonRtConfig.desiredTwist.head<3>();
345 if (cfg.minX.has_value())
347 arm->nonRtConfig.desiredPose(0, 3) =
348 fmax(arm->nonRtConfig.desiredPose(0, 3), *cfg.minX);
350 if (cfg.maxX.has_value())
352 arm->nonRtConfig.desiredPose(0, 3) =
353 fmin(arm->nonRtConfig.desiredPose(0, 3), *cfg.maxX);
355 if (cfg.minY.has_value())
357 arm->nonRtConfig.desiredPose(1, 3) =
358 fmax(arm->nonRtConfig.desiredPose(1, 3), *cfg.minY);
360 if (cfg.maxY.has_value())
362 arm->nonRtConfig.desiredPose(1, 3) =
363 fmin(arm->nonRtConfig.desiredPose(1, 3), *cfg.maxY);
365 if (cfg.minZ.has_value())
367 arm->nonRtConfig.desiredPose(2, 3) =
368 fmax(arm->nonRtConfig.desiredPose(2, 3), *cfg.minZ);
371 if (cfg.desiredUserPosition.has_value() and not cfg.desiredUserPosition->isZero())
373 if (not(*cfg.desiredUserPosition - s.lastDesiredUserPosition).isZero())
375 if (s.openDistanceToDesiredUserPosition > 0.)
377 ARMARX_INFO <<
"Didn't reach previously defined desired position "
378 << s.lastDesiredUserPosition;
380 s.lastDesiredUserPosition = *cfg.desiredUserPosition;
382 s.lastDesiredUserPosition -
383 arm->nonRtConfig.desiredPose.block<2, 1>(0, 3);
384 s.openDistanceToDesiredUserPosition =
distance.norm();
385 if (cfg.distanceToUserPositionScalingFactor.has_value())
387 s.openDistanceToDesiredUserPosition *=
388 *cfg.distanceToUserPositionScalingFactor;
390 ARMARX_INFO <<
"Initialized new desired user position at "
391 << s.lastDesiredUserPosition <<
" which is "
392 << s.openDistanceToDesiredUserPosition
393 <<
" mm from current desired position";
396 if (s.openDistanceToDesiredUserPosition > 0.)
398 Eigen::Vector2f desiredLinearVelocity =
399 s.lastDesiredUserPosition -
400 arm->nonRtConfig.desiredPose.block<2, 1>(0, 3);
401 desiredLinearVelocity = dT * cfg.kpLinear * desiredLinearVelocity /
402 desiredLinearVelocity.norm();
403 s.openDistanceToDesiredUserPosition -= desiredLinearVelocity.norm();
404 arm->nonRtConfig.desiredPose.block<2, 1>(0, 3) += desiredLinearVelocity;
405 if (s.openDistanceToDesiredUserPosition < 0.)
408 << s.lastDesiredUserPosition;
416 const Eigen::Vector2f currentXY =
417 arm->rtStatusInNonRT.currentPose.block<2, 1>(0, 3);
418 if ((s.lastPosition - currentXY).norm() < cfg.changePositionTolerance)
424 s.lastPosition = currentXY;
428 if (s.changeTimer > cfg.changeTimerThreshold)
430 arm->nonRtConfig.desiredPose.block<2, 1>(0, 3) = currentXY;
434 << arm->nonRtConfig.desiredPose.block<3, 1>(0, 3).
transpose();
442 s.desiredPose = arm->nonRtConfig.desiredPose;
444 else if (_mp.second.mp->getRole() ==
"nullspace")
446 auto& arm =
limb.at(_mp.second.mp->getNodeSetName());
448 std::dynamic_pointer_cast<mp::JSMPOutput>(_mp.second.output);
450 arm->nonRtConfig.desiredNullspaceJointAngles.value() = out->angleRadian;
452 else if (_mp.second.mp->getRole() ==
"hand")
455 std::dynamic_pointer_cast<mp::JSMPOutput>(_mp.second.output);
456 auto&
hand =
hands->hands.at(_mp.second.mp->getNodeSetName());
457 mp::JSMPInputPtr in = std::dynamic_pointer_cast<mp::JSMPInput>(_mp.second.input);
459 out->angleRadian.size());
460 hand->targetNonRT.jointPosition.value() = out->angleRadian;
462 if (mpRunning.at(_mp.second.mp->getMPName()) and _mp.second.mp->isFinished())
464 ARMARX_INFO <<
"reset buffer for nonRtConfig of " << _mp.second.mp->getMPName();
465 for (
auto& pair :
limb)
467 auto& arm = pair.second;
468 arm->bufferConfigUserToNonRt.reinitAllBuffers(arm->nonRtConfig);
470 for (
auto& pair :
limb)
472 userConfig.limbs.at(pair.first) = pair.second->nonRtConfig;