31 NJointControllerRegistration<NJointWipingVelMPController>
36 const NJointControllerConfigPtr& config,
46 return "NJointWipingVelMPController";
51 const Ice::Current& iceCurrent)
55 for (
auto& pair :
limb)
57 pair.second->rtFirstRun.store(
true);
64 const Ice::Current& iceCurrent)
66 adaptionCfg = arondto::WipingAdaptionConfigs::FromAron(dto);
67 for (
auto& pair :
limb)
69 auto search = adaptionCfg.cfg.find(pair.first);
70 if (search == adaptionCfg.cfg.end())
72 ARMARX_ERROR <<
"Arm " << pair.first <<
" is not included in the adaption config";
76 adaptionReady.store(
true);
87 for (
auto& pair :
limb)
90 adaptionStatus[pair.first].lastPosition =
98 if (not adaptionReady.load())
102 std::lock_guard<std::recursive_mutex> lock(
mtx_mps);
106 std::map<std::string, bool> flagMPToStop;
108 for (
auto& pair :
limb)
110 flagMPToStop[pair.first] = not
limb.at(pair.first)->controller.ftsensor.ftSafe.load();
111 pair.second->nonRTDeltaT =
112 pair.second->rtStatusInNonRT.accumulateTime - pair.second->nonRTAccumulateTime;
114 pair.second->nonRTAccumulateTime = pair.second->rtStatusInNonRT.accumulateTime;
117 std::map<std::string, bool> mpRunning;
118 for (
auto& _mp :
mps)
120 const auto mpNodeSet = _mp.second.mp->getNodeSetName();
121 mpRunning[_mp.second.mp->getMPName()] = _mp.second.mp->isRunning();
123 auto search = flagMPToStop.find(mpNodeSet);
124 if (search != flagMPToStop.end() and flagMPToStop.at(mpNodeSet) and
125 _mp.second.mp->isRunning() and
126 (
limb.at(mpNodeSet)->controller.ftsensor.isForceGuardEnabled() or
127 limb.at(mpNodeSet)->controller.ftsensor.isTorqueGuardEnabled()))
129 _mp.second.mp->stop();
130 ARMARX_INFO <<
"Due to force/torque safe guard, MP " << _mp.second.mp->getMPName()
131 <<
" is stopped at " << _mp.second.mp->getCanonicalValue();
134 if (_mp.second.mp->isFinished())
138 if (_mp.second.mp->getRole() ==
"taskspace")
140 auto& arm =
limb.at(_mp.second.mp->getNodeSetName());
141 if (_mp.second.mp->isFirstRun())
146 const std::vector<double> mpStart = _mp.second.mp->getStartVec();
148 if (_mp.second.mp->getStartFromPrevTarget() or
150 arm->rtStatusInNonRT.currentPose,
153 "TSMP initial start pose",
154 arm->nonRtConfig.safeDistanceMMToGoal,
155 arm->nonRtConfig.safeRotAngleDegreeToGoal,
156 _mp.second.mp->getMPName() +
"mp_set_target"))
158 if (_mp.second.mp->getStartFromPrevTarget())
160 ARMARX_INFO <<
"User requested to start the current TS MP from the "
161 "previous target pose";
166 <<
"deviation from current pose too large, reset MP start pose";
168 _mp.second.mp->validateInitialState(
173 mp::TSMPInputPtr in = std::dynamic_pointer_cast<mp::TSMPInput>(_mp.second.input);
174 in->pose = arm->rtStatusInNonRT.currentPose;
175 in->vel = arm->rtStatusInNonRT.currentTwist;
177 in->deltaT = arm->nonRTDeltaT;
179 else if (_mp.second.mp->getRole() ==
"nullspace")
181 auto& arm =
limb.at(_mp.second.mp->getNodeSetName());
182 mp::JSMPInputPtr in = std::dynamic_pointer_cast<mp::JSMPInput>(_mp.second.input);
184 arm->rtStatusInNonRT.jointPos.size());
185 in->angleRadian = arm->rtStatusInNonRT.jointPos;
186 in->angularVel = arm->rtStatusInNonRT.qvelFiltered;
188 in->deltaT = arm->nonRTDeltaT;
190 else if (_mp.second.mp->getRole() ==
"hand")
192 auto&
hand =
hands->hands.at(_mp.second.mp->getNodeSetName());
193 mp::JSMPInputPtr in = std::dynamic_pointer_cast<mp::JSMPInput>(_mp.second.input);
195 hand->bufferRTToNonRT.getUpToDateReadBuffer().jointPosition.value();
196 hand->nonRTDeltaT =
hand->bufferRTToNonRT.getReadBuffer().accumulateTime -
197 hand->nonRTAccumulateTime;
198 hand->nonRTAccumulateTime =
hand->bufferRTToNonRT.getReadBuffer().accumulateTime;
200 in->deltaT =
hand->nonRTDeltaT;
215 std::lock_guard<std::recursive_mutex> adaptLock(adaptionMtx);
217 for (
auto& _mp :
mps)
219 if (not mpRunning.at(_mp.second.mp->getMPName()))
223 for (
auto& ftGuard :
mpConfig.ftGuard)
225 if (ftGuard.mpName == _mp.second.mp->getMPName())
227 bool const forceGuard =
228 (ftGuard.force.has_value() and
229 ftGuard.force.value() >= _mp.second.mp->getCanonicalValue());
230 bool const torqueGuard =
231 (ftGuard.torque.has_value() and
232 ftGuard.torque.value() >= _mp.second.mp->getCanonicalValue());
234 auto& arm =
limb.at(_mp.second.mp->getNodeSetName());
235 bool const resetForce =
236 not arm->controller.ftsensor.isForceGuardEnabled() and forceGuard;
237 bool const resetTorque =
238 not arm->controller.ftsensor.isTorqueGuardEnabled() and torqueGuard;
239 if (resetForce or resetTorque)
241 ARMARX_INFO <<
"Triggering force torque safety guard for "
242 << arm->kinematicChainName <<
" at can value "
243 << _mp.second.mp->getCanonicalValue();
246 arm->nonRtConfig.ftConfig.enableSafeGuardForce = forceGuard;
247 arm->nonRtConfig.ftConfig.enableSafeGuardTorque = torqueGuard;
248 arm->controller.ftsensor.enableSafeGuard(resetForce, resetTorque);
252 if (_mp.second.mp->getRole() ==
"taskspace")
254 auto& nodeSetName = _mp.second.mp->getNodeSetName();
255 auto& cfg = adaptionCfg.cfg.at(nodeSetName);
256 auto&
s = adaptionStatus.at(nodeSetName);
257 auto& arm =
limb.at(nodeSetName);
259 std::dynamic_pointer_cast<mp::TSMPOutput>(_mp.second.output);
264 arm->rtStatusInNonRT.currentPose,
265 arm->nonRtConfig.desiredPose,
267 "desiredPose for RT",
268 arm->nonRtConfig.safeDistanceMMToGoal,
269 arm->nonRtConfig.safeRotAngleDegreeToGoal,
270 _mp.second.mp->getMPName() +
"mp_set_target");
271 arm->nonRtConfig.desiredPose = out->pose;
272 arm->nonRtConfig.desiredTwist = out->vel;
276 cfg.kpf * (cfg.targetForce - arm->rtStatusInNonRT.currentForceTorque(2));
277 arm->nonRtConfig.desiredTwist(2) -= desiredVelZ;
278 arm->nonRtConfig.desiredTwist.tail<3>().setZero();
281 float dT =
static_cast<float>(arm->nonRTDeltaT);
284 auto& adaptKVel = arm->nonRtConfig.kpCartesianVel;
285 if (not cfg.originalKpVel.has_value())
287 cfg.originalKpVel = adaptKVel;
292 Eigen::Vector2f currentForceXY =
293 arm->rtStatusInNonRT.currentForceTorque.head<2>();
294 Eigen::Vector2f dragForce =
295 currentForceXY - cfg.deadZoneForce * currentForceXY / currentForceXY.norm();
296 adaptKVel.head<2>() =
297 (adaptKVel.head<2>().array() - dT * cfg.adaptForceCoeff * dragForce.norm())
303 adaptKVel.head<2>() = (adaptKVel.head<2>().array() + dT * cfg.adaptCoeff)
304 .
min(originalKpVel.head<2>().array());
306 adaptKVel(2) = originalKpVel(2);
309 arm->nonRtConfig.desiredPose.block<3, 1>(0, 3) +=
310 dT * arm->nonRtConfig.desiredTwist.head<3>();
315 Eigen::Vector2f currentXY = arm->rtStatusInNonRT.currentPose.block<2, 1>(0, 3);
316 if ((
s.lastPosition - currentXY).norm() < cfg.changePositionTolerance)
322 s.lastPosition = currentXY;
326 if (
s.changeTimer > cfg.changeTimerThreshold)
328 arm->nonRtConfig.desiredPose.block<2, 1>(0, 3) = currentXY;
338 else if (_mp.second.mp->getRole() ==
"nullspace")
340 auto& arm =
limb.at(_mp.second.mp->getNodeSetName());
342 std::dynamic_pointer_cast<mp::JSMPOutput>(_mp.second.output);
344 arm->nonRtConfig.desiredNullspaceJointAngles.value() = out->angleRadian;
346 else if (_mp.second.mp->getRole() ==
"hand")
349 std::dynamic_pointer_cast<mp::JSMPOutput>(_mp.second.output);
350 auto&
hand =
hands->hands.at(_mp.second.mp->getNodeSetName());
351 mp::JSMPInputPtr in = std::dynamic_pointer_cast<mp::JSMPInput>(_mp.second.input);
353 out->angleRadian.size());
354 hand->targetNonRT.jointPosition.value() = out->angleRadian;
356 if (mpRunning.at(_mp.second.mp->getMPName()) and _mp.second.mp->isFinished())
358 ARMARX_INFO <<
"reset buffer for nonRtConfig of " << _mp.second.mp->getMPName();
359 for (
auto& pair :
limb)
361 auto& arm = pair.second;
362 arm->bufferConfigUserToNonRt.reinitAllBuffers(arm->nonRtConfig);
364 for (
auto& pair :
limb)
366 userConfig.limbs.at(pair.first) = pair.second->nonRtConfig;