29 const armarx::NJointControllerConfigPtr& config,
32 ARMARX_INFO <<
"creating periodic task-space impedance dmp controller";
35 cfg = DeprecatedNJointPeriodicTSDMPCompliantControllerConfigPtr::dynamicCast(config);
38 VirtualRobot::RobotNodeSetPtr rns =
rtGetRobot()->getRobotNodeSet(cfg->nodeSetName);
40 for (
size_t i = 0; i < rns->getSize(); ++i)
42 std::string jointName = rns->getNode(i)->getName();
46 targets.push_back(ct->
asA<ControlTarget1DoFActuatorTorque>());
48 const SensorValue1DoFActuatorVelocity* velocitySensor =
49 sv->
asA<SensorValue1DoFActuatorVelocity>();
50 const SensorValue1DoFActuatorPosition* positionSensor =
51 sv->
asA<SensorValue1DoFActuatorPosition>();
62 velocitySensors.push_back(velocitySensor);
63 positionSensors.push_back(positionSensor);
67 ik.reset(
new VirtualRobot::DifferentialIK(
68 rns, rns->getRobot()->getRootNode(), VirtualRobot::JacobiProvider::eSVDDamped));
69 ik->setDampedSvdLambda(0.0001);
70 numOfJoints = targets.size();
71 qvel_filtered.setZero(targets.size());
72 torqueLimit = cfg->jointTorqueLimit;
76 robUnit->getSensorDevice(cfg->forceSensorName)->getSensorValue();
80 Eigen::Vector3f tcpCoMInForceSensorFrame;
81 tcpCoMInForceSensorFrame.setZero();
83 enableTCPGravityCompensation.store(cfg->enableTCPGravityCompensation);
85 if (enableTCPGravityCompensation.load())
87 tcpMass = cfg->tcpMass;
88 tcpCoMInForceSensorFrame = cfg->tcpCoMInForceSensorFrame;
91 forceOffset.setZero();
92 torqueOffset.setZero();
93 filteredForce.setZero();
94 filteredTorque.setZero();
95 filteredForceInRoot.setZero();
96 filteredTorqueInRoot.setZero();
99 toolFrameInRoot = cfg->toolFrameInRoot;
101 cfg->pidForce[0], cfg->pidForce[1], cfg->pidForce[2], cfg->pidForce[3]));
108 taskSpaceDMPConfig.
DMPMode =
"Linear";
109 taskSpaceDMPConfig.
DMPStyle =
"Periodic";
121 kinematic_chain = cfg->nodeSetName;
133 CtrlParams initParams = {cfg->kpImpedance,
139 tcpCoMInForceSensorFrame};
140 ctrlParams.reinitAllBuffers(initParams);
148 if (!cfg->ignoreWSLimitChecks)
227 if (!dmpCtrl || !rt2MPBuffer.updateReadBuffer())
233 bool isPhaseStop = rt2MPBuffer.getUpToDateReadBuffer().isPhaseStop;
234 if (!isPhaseStop && mpRunning.load())
236 double deltaT = rt2MPBuffer.getUpToDateReadBuffer().deltaT;
237 Eigen::Matrix4f currentPose = rt2MPBuffer.getUpToDateReadBuffer().currentPose;
238 Eigen::VectorXf currentTwist = rt2MPBuffer.getUpToDateReadBuffer().currentTwist;
242 dmpCtrl->flow(deltaT, currentPose, currentTwist);
244 targetVels = dmpCtrl->getTargetVelocity();
246 debugMPBuffer.getWriteBuffer().currentPose[
"currentPose_x"] = currentPose(0, 3);
247 debugMPBuffer.getWriteBuffer().currentPose[
"currentPose_y"] = currentPose(1, 3);
248 debugMPBuffer.getWriteBuffer().currentPose[
"currentPose_z"] = currentPose(2, 3);
249 VirtualRobot::MathTools::Quaternion currentQ =
250 VirtualRobot::MathTools::eigen4f2quat(currentPose);
251 debugMPBuffer.getWriteBuffer().currentPose[
"currentPose_qw"] = currentQ.w;
252 debugMPBuffer.getWriteBuffer().currentPose[
"currentPose_qx"] = currentQ.x;
253 debugMPBuffer.getWriteBuffer().currentPose[
"currentPose_qy"] = currentQ.y;
254 debugMPBuffer.getWriteBuffer().currentPose[
"currentPose_qz"] = currentQ.z;
255 debugMPBuffer.getWriteBuffer().currentCanVal = dmpCtrl->debugData.canVal;
256 debugMPBuffer.getWriteBuffer().mpcFactor = dmpCtrl->debugData.mpcFactor;
257 debugMPBuffer.getWriteBuffer().error = dmpCtrl->debugData.poseError;
258 debugMPBuffer.getWriteBuffer().posError = dmpCtrl->debugData.posiError;
259 debugMPBuffer.getWriteBuffer().oriError = dmpCtrl->debugData.oriError;
260 debugMPBuffer.getWriteBuffer().deltaT = deltaT;
274 rt2MPBuffer.getUpToDateReadBuffer().currentPose;
281 debugMPBuffer.getWriteBuffer().latestTargetVelocities[
"x_vel"] = targetVels(0);
282 debugMPBuffer.getWriteBuffer().latestTargetVelocities[
"y_vel"] = targetVels(1);
283 debugMPBuffer.getWriteBuffer().latestTargetVelocities[
"z_vel"] = targetVels(2);
284 debugMPBuffer.getWriteBuffer().latestTargetVelocities[
"roll_vel"] = targetVels(3);
285 debugMPBuffer.getWriteBuffer().latestTargetVelocities[
"pitch_vel"] = targetVels(4);
286 debugMPBuffer.getWriteBuffer().latestTargetVelocities[
"yaw_vel"] = targetVels(5);
287 debugMPBuffer.commitWrite();
293 const IceUtil::Time& sensorValuesTimestamp,
294 const IceUtil::Time& timeSinceLastIteration)
297 Eigen::Matrix4f currentPose = tcp->getPoseInRootFrame();
298 Eigen::MatrixXf jacobi =
299 ik->getJacobianMatrix(tcp, VirtualRobot::IKSolver::CartesianSelection::All);
301 Eigen::VectorXf qpos(positionSensors.size());
302 Eigen::VectorXf qvel(velocitySensors.size());
303 for (
size_t i = 0; i < positionSensors.size(); ++i)
305 qpos(i) = positionSensors[i]->position;
306 qvel(i) = velocitySensors[i]->velocity;
308 qvel_filtered = (1 - cfg->qvelFilter) * qvel_filtered + cfg->qvelFilter * qvel;
309 Eigen::VectorXf currentTwist = jacobi * qvel_filtered;
310 jacobi.block(0, 0, 3, numOfJoints) =
311 0.001 * jacobi.block(0, 0, 3, numOfJoints);
313 double deltaT = timeSinceLastIteration.toSecondsDouble();
316 Eigen::Vector6f kpImpedance = ctrlParams.getUpToDateReadBuffer().kpImpedance;
317 Eigen::Vector6f kdImpedance = ctrlParams.getUpToDateReadBuffer().kdImpedance;
318 Eigen::VectorXf knull = ctrlParams.getUpToDateReadBuffer().knull;
319 Eigen::VectorXf dnull = ctrlParams.getUpToDateReadBuffer().dnull;
320 Eigen::Vector4f pidForce = ctrlParams.getUpToDateReadBuffer().pidForce;
321 forcePID->Kp = pidForce(0);
322 forcePID->Ki = pidForce(1);
323 forcePID->Kd = pidForce(2);
324 forcePID->maxControlValue = pidForce(3);
326 float tcpMass = ctrlParams.getUpToDateReadBuffer().tcpMass;
327 Eigen::Vector3f tcpCoMInFTFrame =
328 ctrlParams.getUpToDateReadBuffer().tcpCoMInForceSensorFrame;
332 Eigen::Vector3f forceBaseline = Eigen::Vector3f::Zero();
333 Eigen::Vector3f torqueBaseline = Eigen::Vector3f::Zero();
336 forceTorque.setZero();
337 tcpGravityCompensation.setZero();
340 Eigen::Matrix4f targetPose;
342 Eigen::VectorXf targetNullSpaceJointValues =
344 Eigen::Vector3f targetVelInTool = Eigen::Vector3f::Zero();
345 Eigen::Matrix3f currentToolOriInRoot = Eigen::Matrix3f::Identity();
347 float targetForce = 0.0f;
348 if (rtFirstRun.load())
350 rtReady.store(
false);
351 rtFirstRun.store(
false);
352 timeForCalibration = 0;
353 forceOffset.setZero();
354 torqueOffset.setZero();
357 Eigen::Matrix4f forceFrameInRoot =
358 rtGetRobot()->getRobotNode(cfg->forceFrameName)->getPoseInRootFrame();
359 forceFrameInTCP.block<3, 3>(0, 0) =
360 currentPose.block<3, 3>(0, 0).transpose() * forceFrameInRoot.block<3, 3>(0, 0);
361 tcpCoMInTCPFrame = forceFrameInTCP.block<3, 3>(0, 0) * tcpCoMInFTFrame;
363 targetPose = currentPose;
364 previousTargetPose = currentPose;
366 currentPose.block<3, 3>(0, 0).
transpose() * toolFrameInRoot.block<3, 3>(0, 0);
376 if (enableTCPGravityCompensation.load())
382 targetPose = previousTargetPose;
384 (1 - cfg->forceFilter) * forceOffset +
385 cfg->forceFilter * (forceSensor->force - tcpGravityCompensation.head<3>());
387 (1 - cfg->forceFilter) * torqueOffset +
388 cfg->forceFilter * (forceSensor->torque - tcpGravityCompensation.tail<3>());
389 timeForCalibration = timeForCalibration + deltaT;
390 if (timeForCalibration > cfg->waitTimeForCalibration)
394 <<
VAROUT(forceOffset) <<
"\n"
395 <<
VAROUT(torqueOffset) <<
"\n"
403 currentToolOriInRoot = currentPose.block<3, 3>(0, 0) * toolOriInHand;
406 Eigen::VectorXf ftInTool = forceTorque;
407 ftInTool.head<3>() = currentToolOriInRoot.transpose() * ftInTool.head<3>();
413 forcePID->update(deltaT, ftInTool(2), targetForce);
415 -1000.0f * (
float)forcePID->getControlValue();
417 targetVelInTool(2) = forcePIDVel;
418 targetVel.head<3>() += currentToolOriInRoot * targetVelInTool;
421 targetPose.block<3, 1>(0, 3) =
422 targetPose.block<3, 1>(0, 3) + (
float)deltaT * targetVel.block<3, 1>(0, 0);
423 if ((previousTargetPose.block<3, 1>(0, 3) - targetPose.block<3, 1>(0, 3)).norm() >
427 <<
VAROUT(targetPose) <<
"\nis too far away from\n"
428 <<
VAROUT(previousTargetPose);
429 targetPose = previousTargetPose;
431 previousTargetPose = targetPose;
435 bool isPhaseStop =
false;
436 float diff = (targetPose.block<2, 1>(0, 3) - currentPose.block<2, 1>(0, 3)).
norm();
437 if (diff > cfg->phaseDist0)
444 Eigen::Vector2f currentXY = currentPose.block<2, 1>(0, 3);
445 if ((lastPosition - currentXY).
norm() < cfg->changePositionTolerance)
447 changeTimer += deltaT;
451 lastPosition = currentPose.block<2, 1>(0, 3);
455 if (changeTimer > cfg->changeTimerThreshold)
457 targetPose(0, 3) = currentPose(0, 3);
458 targetPose(1, 3) = currentPose(1, 3);
468 targetPose(0, 3) = std::clamp(targetPose(0, 3), cfg->ws_x[0], cfg->ws_x[1]);
469 targetPose(1, 3) = std::clamp(targetPose(1, 3), cfg->ws_y[0], cfg->ws_y[1]);
470 targetPose(2, 3) = std::clamp(targetPose(2, 3), cfg->ws_z[0], cfg->ws_z[1]);
474 rt2InterfaceBuffer.getWriteBuffer().currentTcpPose = currentPose;
475 rt2InterfaceBuffer.getWriteBuffer().waitTimeForCalibration += deltaT;
476 rt2InterfaceBuffer.commitWrite();
478 debugRTBuffer.getWriteBuffer().targetPose = targetPose;
479 debugRTBuffer.getWriteBuffer().currentPose = currentPose;
480 debugRTBuffer.getWriteBuffer().filteredForce = filteredForceInRoot;
481 debugRTBuffer.getWriteBuffer().targetVel = targetVel;
482 debugRTBuffer.getWriteBuffer().isPhaseStop = isPhaseStop;
483 debugRTBuffer.getWriteBuffer().targetVelInTool = targetVelInTool;
485 rt2MPBuffer.getWriteBuffer().currentPose = currentPose;
486 rt2MPBuffer.getWriteBuffer().currentTwist = currentTwist;
487 rt2MPBuffer.getWriteBuffer().deltaT = deltaT;
488 rt2MPBuffer.getWriteBuffer().currentTime += deltaT;
489 rt2MPBuffer.getWriteBuffer().isPhaseStop = isPhaseStop;
490 rt2MPBuffer.commitWrite();
498 Eigen::Matrix3f diffMat =
499 targetPose.block<3, 3>(0, 0) * currentPose.block<3, 3>(0, 0).transpose();
500 poseErrorImp.head<3>() =
501 0.001 * (targetPose.block<3, 1>(0, 3) - currentPose.block<3, 1>(0, 3));
502 currentTwist.head<3>() *= 0.001;
503 poseErrorImp.tail<3>() = VirtualRobot::MathTools::eigen3f2rpy(diffMat);
505 kpImpedance.cwiseProduct(poseErrorImp) - kdImpedance.cwiseProduct(currentTwist);
508 Eigen::VectorXf nullspaceTorque =
509 knull.cwiseProduct(targetNullSpaceJointValues - qpos) - dnull.cwiseProduct(qvel);
512 Eigen::MatrixXf I = Eigen::MatrixXf::Identity(targets.size(), targets.size());
513 Eigen::MatrixXf jtpinv = ik->computePseudoInverseJacobianMatrix(jacobi.transpose(), 2.0);
514 Eigen::VectorXf jointDesiredTorques = jacobi.transpose() * forceImpedance +
515 (I - jacobi.transpose() * jtpinv) * nullspaceTorque;
519 for (
size_t i = 0; i < targets.size(); ++i)
521 targets.at(i)->torque = jointDesiredTorques(i);
522 if (!targets.at(i)->isValid() || isnan(targets.at(i)->torque))
524 targets.at(i)->torque = 0.0f;
528 if (fabs(targets.at(i)->torque) > fabs(torqueLimit))
530 targets.at(i)->torque =
531 fabs(torqueLimit) * (targets.at(i)->torque / fabs(targets.at(i)->torque));
536 debugRTBuffer.commitWrite();