31 NJointControllerRegistration<NJointWipingMixImpVelColMPController>
33 "NJointWipingMixImpVelColMPController");
37 const NJointControllerConfigPtr& config,
48 return "NJointWipingMixImpVelColMPController";
54 const Ice::Current& iceCurrent)
58 for (
auto& pair :
limb)
60 pair.second->rtFirstRun.store(
true);
68 const Ice::Current& iceCurrent)
70 adaptionCfg = arondto::WipingAdaptionConfigs::FromAron(dto);
71 for (
auto& pair :
limb)
73 auto search = adaptionCfg.cfg.find(pair.first);
74 if (search == adaptionCfg.cfg.end())
76 ARMARX_ERROR <<
"Arm " << pair.first <<
" is not included in the adaption config";
80 adaptionReady.store(
true);
92 for (
auto& pair :
limb)
101 if (not adaptionReady.load())
105 std::lock_guard<std::recursive_mutex> lock(
mtx_mps);
109 std::map<std::string, bool> flagMPToStop;
110 for (
auto& pair :
limb)
112 flagMPToStop[pair.first] =
limb.at(pair.first)->controller.ftsensor.ftSafe.load();
115 std::map<std::string, bool> mpRunning;
116 for (
auto& _mp :
mps)
118 const auto mpNodeSet = _mp.second.mp->getNodeSetName();
119 auto search = flagMPToStop.find(mpNodeSet);
120 if (search != flagMPToStop.end() and flagMPToStop.at(mpNodeSet) and
121 _mp.second.mp->isRunning() and
122 (
limb.at(mpNodeSet)->controller.ftsensor.isForceGuardEnabled() or
123 limb.at(mpNodeSet)->controller.ftsensor.isTorqueGuardEnabled()))
125 _mp.second.mp->stop();
126 ARMARX_INFO <<
"Due to force/torque safe guard, MP " << _mp.second.mp->getMPName()
127 <<
" is stopped at " << _mp.second.mp->getCanonicalValue();
129 mpRunning[_mp.second.mp->getMPName()] = _mp.second.mp->isRunning();
130 if (_mp.second.mp->isFinished())
134 if (_mp.second.mp->getRole() ==
"taskspace")
136 auto& arm =
limb.at(_mp.second.mp->getNodeSetName());
137 if (_mp.second.mp->isFirstRun())
142 const std::vector<double> mpStart = _mp.second.mp->getStartVec();
145 arm->rtStatusInNonRT.currentPose,
148 "TSMP initial start pose",
149 arm->nonRtConfig.safeDistanceMMToGoal,
150 arm->nonRtConfig.safeRotAngleDegreeToGoal,
151 _mp.second.mp->getMPName() +
"mp_set_target"))
154 <<
"-- deviation from current pose too large, reset MP start pose";
155 _mp.second.mp->validateInitialState(
160 mp::TSMPInputPtr in = std::dynamic_pointer_cast<mp::TSMPInput>(_mp.second.input);
161 in->pose = arm->rtStatusInNonRT.currentPose;
162 in->vel = arm->rtStatusInNonRT.currentTwist;
163 in->deltaT = arm->rtStatusInNonRT.deltaT;
165 else if (_mp.second.mp->getRole() ==
"nullspace")
167 auto& arm =
limb.at(_mp.second.mp->getNodeSetName());
168 mp::JSMPInputPtr in = std::dynamic_pointer_cast<mp::JSMPInput>(_mp.second.input);
170 arm->rtStatusInNonRT.jointPos.size());
171 in->angleRadian = arm->rtStatusInNonRT.jointPos;
172 in->angularVel = arm->rtStatusInNonRT.qvelFiltered;
173 in->deltaT = arm->rtStatusInNonRT.deltaT;
175 else if (_mp.second.mp->getRole() ==
"hand")
177 auto&
hand =
hands->hands.at(_mp.second.mp->getNodeSetName());
178 mp::JSMPInputPtr in = std::dynamic_pointer_cast<mp::JSMPInput>(_mp.second.input);
180 hand->bufferRTToNonRT.getUpToDateReadBuffer().jointPosition.value();
181 in->deltaT =
hand->bufferRTToNonRT.getReadBuffer().deltaT;
195 std::lock_guard<std::recursive_mutex> adaptLock(adaptionMtx);
197 for (
auto& _mp :
mps)
199 if (not mpRunning.at(_mp.second.mp->getMPName()))
203 for (
auto& ftGuard :
mpConfig.ftGuard)
205 if (ftGuard.mpName == _mp.second.mp->getMPName())
207 bool const forceGuard =
208 (ftGuard.force.has_value() and
209 ftGuard.force.value() >= _mp.second.mp->getCanonicalValue());
210 bool const torqueGuard =
211 (ftGuard.torque.has_value() and
212 ftGuard.torque.value() >= _mp.second.mp->getCanonicalValue());
214 auto& arm =
limb.at(_mp.second.mp->getNodeSetName());
215 bool const resetForce =
216 not arm->controller.ftsensor.isForceGuardEnabled() and forceGuard;
217 bool const resetTorque =
218 not arm->controller.ftsensor.isTorqueGuardEnabled() and torqueGuard;
219 if (resetForce or resetTorque)
221 ARMARX_INFO <<
"Triggering force torque safety guard for "
222 << arm->kinematicChainName <<
" at can value "
223 << _mp.second.mp->getCanonicalValue();
226 arm->nonRtConfig.ftConfig.enableSafeGuardForce = forceGuard;
227 arm->nonRtConfig.ftConfig.enableSafeGuardTorque = torqueGuard;
228 arm->controller.ftsensor.enableSafeGuard(resetForce, resetTorque);
232 if (_mp.second.mp->getRole() ==
"taskspace")
234 auto& nodeSetName = _mp.second.mp->getNodeSetName();
235 auto& cfg = adaptionCfg.cfg.at(nodeSetName);
236 auto&
s = adaptionStatus.at(nodeSetName);
237 auto& arm =
limb.at(nodeSetName);
239 std::dynamic_pointer_cast<mp::TSMPOutput>(_mp.second.output);
244 arm->rtStatusInNonRT.currentPose,
245 arm->nonRtConfig.desiredPose,
247 "desiredPose for RT",
248 arm->nonRtConfig.safeDistanceMMToGoal,
249 arm->nonRtConfig.safeRotAngleDegreeToGoal,
250 _mp.second.mp->getMPName() +
"mp_set_target");
251 arm->nonRtConfig.desiredPose = out->pose;
252 arm->nonRtConfig.desiredTwist = out->vel;
256 cfg.kpf * (cfg.targetForce - arm->rtStatusInNonRT.currentForceTorque(2));
257 arm->nonRtConfig.desiredTwist(2) -= desiredVelZ;
258 arm->nonRtConfig.desiredTwist.tail<3>().setZero();
260 float dT =
static_cast<float>(arm->rtStatusInNonRT.deltaT);
263 auto& adaptKImp = arm->nonRtConfig.kpImpedance;
264 auto& adaptKVel = arm->nonRtConfig.kpCartesianVel;
270 Eigen::Vector2f currentForceXY =
271 arm->rtStatusInNonRT.currentForceTorque.head<2>();
272 Eigen::Vector2f dragForce =
273 currentForceXY - cfg.deadZoneForce * currentForceXY / currentForceXY.norm();
274 adaptKImp.head<2>() =
275 (adaptKImp.head<2>().array() - dT * cfg.adaptForceCoeff * dragForce.norm())
277 adaptKVel.head<2>() =
278 (adaptKVel.head<2>().array() - dT * cfg.adaptForceCoeff * dragForce.norm())
284 adaptKImp.head<2>() = (adaptKImp.head<2>().array() + dT * cfg.adaptCoeff)
285 .
min(originalKpImp.head<2>().array());
286 adaptKVel.head<2>() = (adaptKVel.head<2>().array() + dT * cfg.adaptCoeff)
287 .
min(originalKpVel.head<2>().array());
289 adaptKImp(2) = originalKpImp(2);
290 adaptKImp(2) = originalKpVel(2);
293 arm->nonRtConfig.desiredPose.block<3, 1>(0, 3) +=
294 dT * arm->nonRtConfig.desiredTwist.head<3>();
299 Eigen::Vector2f currentXY = arm->rtStatusInNonRT.currentPose.block<2, 1>(0, 3);
300 if ((
s.lastPosition - currentXY).norm() < cfg.changePositionTolerance)
306 s.lastPosition = currentXY;
310 if (
s.changeTimer > cfg.changeTimerThreshold)
312 arm->nonRtConfig.desiredPose.block<2, 1>(0, 3) = currentXY;
322 else if (_mp.second.mp->getRole() ==
"nullspace")
324 auto& arm =
limb.at(_mp.second.mp->getNodeSetName());
326 std::dynamic_pointer_cast<mp::JSMPOutput>(_mp.second.output);
328 arm->nonRtConfig.desiredNullspaceJointAngles.value() = out->angleRadian;
330 else if (_mp.second.mp->getRole() ==
"hand")
333 std::dynamic_pointer_cast<mp::JSMPOutput>(_mp.second.output);
334 auto&
hand =
hands->hands.at(_mp.second.mp->getNodeSetName());
335 mp::JSMPInputPtr in = std::dynamic_pointer_cast<mp::JSMPInput>(_mp.second.input);
337 out->angleRadian.size());
338 hand->targetNonRT.jointPosition.value() = out->angleRadian;
340 if (mpRunning.at(_mp.second.mp->getMPName()) and _mp.second.mp->isFinished())
342 ARMARX_INFO <<
"reset buffer for nonRtConfig of " << _mp.second.mp->getMPName();
343 for (
auto& pair :
limb)
345 auto& arm = pair.second;
346 arm->bufferConfigUserToNonRt.reinitAllBuffers(arm->nonRtConfig);
348 for (
auto& pair :
limb)
350 userConfig.limbs.at(pair.first) = pair.second->nonRtConfig;