31 const armarx::NJointControllerConfigPtr& config,
36 cfg = NJointTaskSpaceImpedanceDMPControllerConfigPtr::dynamicCast(config);
39 rns =
rtGetRobot()->getRobotNodeSet(cfg->nodeSetName);
42 for (
size_t i = 0; i < rns->getSize(); ++i)
44 std::string jointName = rns->getNode(i)->getName();
45 jointNames.push_back(jointName);
48 targets.push_back(ct->
asA<ControlTarget1DoFActuatorTorque>());
49 const SensorValue1DoFActuatorVelocity* velocitySensor =
50 sv->
asA<SensorValue1DoFActuatorVelocity>();
51 const SensorValue1DoFActuatorPosition* positionSensor =
52 sv->
asA<SensorValue1DoFActuatorPosition>();
63 velocitySensors.push_back(velocitySensor);
64 positionSensors.push_back(positionSensor);
67 robotUnit->getSensorDevice(cfg->forceSensorName)->getSensorValue();
71 forceOffset.setZero();
72 filteredForce.setZero();
73 filteredForceInRoot.setZero();
75 forceThreshold.reinitAllBuffers(cfg->forceThreshold);
77 ik.reset(
new VirtualRobot::DifferentialIK(
78 rns,
rtGetRobot()->getRootNode(), VirtualRobot::JacobiProvider::eSVDDamped));
79 ik->setDampedSvdLambda(0.0001);
82 numOfJoints = targets.size();
87 taskSpaceDMPConfig.
DMPMode = cfg->dmpMode;
88 taskSpaceDMPConfig.
DMPStyle = cfg->dmpType;
104 useNullSpaceJointDMP = cfg->useNullSpaceJointDMP;
105 nullSpaceJointDMPPtr.reset(
new DMP::UMIDMP(100));
107 isNullSpaceJointDMPLearned =
false;
109 Eigen::VectorXf nullspaceValues(targets.size());
113 for (
size_t i = 0; i < targets.size(); ++i)
115 nullspaceValues(i) = cfg->defaultNullSpaceJointValues.at(i);
117 defaultNullSpaceJointValues.reinitAllBuffers(nullspaceValues);
120 Eigen::Vector3f kpos(cfg->Kpos[0], cfg->Kpos[1], cfg->Kpos[2]);
121 Eigen::Vector3f dpos(cfg->Dpos[0], cfg->Dpos[1], cfg->Dpos[2]);
122 Eigen::Vector3f kori(cfg->Kori[0], cfg->Kori[1], cfg->Kori[2]);
123 Eigen::Vector3f dori(cfg->Dori[0], cfg->Dori[1], cfg->Dori[2]);
124 Eigen::VectorXf knull(targets.size());
125 Eigen::VectorXf dnull(targets.size());
130 for (
size_t i = 0; i < targets.size(); ++i)
132 knull(i) = cfg->Knull.at(i);
133 dnull(i) = cfg->Dnull.at(i);
136 CtrlParams initParams = {kpos, dpos, kori, dori, knull, dnull};
137 ctrlParams.reinitAllBuffers(initParams);
139 torqueLimit = cfg->torqueLimit;
140 timeDuration = cfg->timeDuration;
142 NJointTaskSpaceImpedanceDMPControllerInterfaceData initInterfaceData;
143 initInterfaceData.currentTcpPose = Eigen::Matrix4f::Identity();
144 interfaceData.reinitAllBuffers(initInterfaceData);
146 NJointTaskSpaceImpedanceDMPControllerSensorData initControllerSensorData;
147 initControllerSensorData.currentPose = Eigen::Matrix4f::Identity();
148 initControllerSensorData.currentTime = 0;
149 initControllerSensorData.deltaT = 0;
150 initControllerSensorData.currentTwist.setZero();
151 controllerSensorData.reinitAllBuffers(initControllerSensorData);
154 useForceStop =
false;
276 const IceUtil::Time& timeSinceLastIteration)
279 Eigen::Matrix4f currentPose = tcp->getPoseInRootFrame();
281 double deltaT = timeSinceLastIteration.toSecondsDouble();
282 Eigen::Matrix4f targetPose;
283 Eigen::VectorXf targetVel;
284 Eigen::VectorXf desiredNullSpaceJointValues;
288 targetPose = currentPose;
289 stopPose = currentPose;
290 targetVel.setZero(6);
291 desiredNullSpaceJointValues = defaultNullSpaceJointValues.getUpToDateReadBuffer();
297 targetPose = stopPose;
298 targetVel.setZero(6);
299 desiredNullSpaceJointValues = defaultNullSpaceJointValues.getUpToDateReadBuffer();
301 (1 - cfg->forceFilter) * forceOffset + cfg->forceFilter * forceSensor->force;
302 timeForCalibration = timeForCalibration + timeSinceLastIteration.toSecondsDouble();
313 filteredForce = (1 - cfg->forceFilter) * filteredForce +
314 cfg->forceFilter * (forceSensor->force - forceOffset);
316 for (
size_t i = 0; i < 3; ++i)
318 if (fabs(filteredForce(i)) > cfg->forceDeadZone)
321 (filteredForce(i) / fabs(filteredForce(i))) * cfg->forceDeadZone;
325 filteredForce(i) = 0;
328 Eigen::Matrix4f forceFrameInRoot =
329 rtGetRobot()->getRobotNode(cfg->forceFrameName)->getPoseInRootFrame();
330 filteredForceInRoot = forceFrameInRoot.block<3, 3>(0, 0) * filteredForce;
332 for (
size_t i = 0; i < 3; ++i)
334 if (fabs(filteredForceInRoot[i]) >
335 forceThreshold.getUpToDateReadBuffer()[i])
337 stopPose = currentPose;
338 targetVel.setZero(6);
339 desiredNullSpaceJointValues =
340 defaultNullSpaceJointValues.getUpToDateReadBuffer();
350 Eigen::MatrixXf jacobi =
351 ik->getJacobianMatrix(tcp, VirtualRobot::IKSolver::CartesianSelection::All);
353 Eigen::VectorXf qpos(positionSensors.size());
354 Eigen::VectorXf qvel(velocitySensors.size());
355 for (
size_t i = 0; i < positionSensors.size(); ++i)
357 qpos(i) = positionSensors[i]->position;
358 qvel(i) = velocitySensors[i]->velocity;
361 Eigen::VectorXf currentTwist = jacobi * qvel;
363 controllerSensorData.getWriteBuffer().currentPose = currentPose;
364 controllerSensorData.getWriteBuffer().currentTwist = currentTwist;
365 controllerSensorData.getWriteBuffer().deltaT = deltaT;
366 controllerSensorData.getWriteBuffer().currentTime += deltaT;
367 controllerSensorData.commitWrite();
369 interfaceData.getWriteBuffer().currentTcpPose = currentPose;
370 interfaceData.commitWrite();
372 jacobi.block(0, 0, 3, numOfJoints) =
373 0.001 * jacobi.block(0, 0, 3, numOfJoints);
375 Eigen::Vector3f kpos = ctrlParams.getUpToDateReadBuffer().kpos;
376 Eigen::Vector3f dpos = ctrlParams.getUpToDateReadBuffer().dpos;
377 Eigen::Vector3f kori = ctrlParams.getUpToDateReadBuffer().kori;
378 Eigen::Vector3f dori = ctrlParams.getUpToDateReadBuffer().dori;
379 Eigen::VectorXf knull = ctrlParams.getUpToDateReadBuffer().knull;
380 Eigen::VectorXf dnull = ctrlParams.getUpToDateReadBuffer().dnull;
384 Eigen::Vector3f targetTCPLinearVelocity;
385 targetTCPLinearVelocity << 0.001 * targetVel(0), 0.001 * targetVel(1),
386 0.001 * targetVel(2);
387 Eigen::Vector3f currentTCPLinearVelocity;
388 currentTCPLinearVelocity << 0.001 * currentTwist(0), 0.001 * currentTwist(1),
389 0.001 * currentTwist(2);
390 Eigen::Vector3f currentTCPPosition = currentPose.block<3, 1>(0, 3);
391 Eigen::Vector3f desiredPosition = targetPose.block<3, 1>(0, 3);
392 Eigen::Vector3f tcpDesiredForce =
393 0.001 * kpos.cwiseProduct(desiredPosition - currentTCPPosition) +
394 dpos.cwiseProduct(targetTCPLinearVelocity - currentTCPLinearVelocity);
396 Eigen::Vector3f currentTCPAngularVelocity;
397 currentTCPAngularVelocity << currentTwist(3), currentTwist(4), currentTwist(5);
398 Eigen::Matrix3f currentRotMat = currentPose.block<3, 3>(0, 0);
399 Eigen::Matrix3f diffMat = targetPose.block<3, 3>(0, 0) * currentRotMat.inverse();
400 Eigen::Vector3f rpy = VirtualRobot::MathTools::eigen3f2rpy(diffMat);
401 Eigen::Vector3f tcpDesiredTorque =
402 kori.cwiseProduct(rpy) - dori.cwiseProduct(currentTCPAngularVelocity);
403 jointControlWrench << tcpDesiredForce, tcpDesiredTorque;
406 Eigen::MatrixXf I = Eigen::MatrixXf::Identity(targets.size(), targets.size());
408 Eigen::VectorXf nullspaceTorque =
409 knull.cwiseProduct(desiredNullSpaceJointValues - qpos) - dnull.cwiseProduct(qvel);
410 Eigen::MatrixXf jtpinv = ik->computePseudoInverseJacobianMatrix(jacobi.transpose(), 2.0);
411 Eigen::VectorXf jointDesiredTorques = jacobi.transpose() * jointControlWrench +
412 (I - jacobi.transpose() * jtpinv) * nullspaceTorque;
418 for (
size_t i = 0; i < targets.size(); ++i)
420 float desiredTorque = jointDesiredTorques(i);
422 if (isnan(desiredTorque))
427 desiredTorque = (desiredTorque > torqueLimit) ? torqueLimit : desiredTorque;
428 desiredTorque = (desiredTorque < -torqueLimit) ? -torqueLimit : desiredTorque;
430 debugOutputData.getWriteBuffer().desired_torques[jointNames[i]] =
431 jointDesiredTorques(i);
432 debugOutputData.getWriteBuffer().desired_nullspaceJoint[jointNames[i]] =
433 desiredNullSpaceJointValues(i);
435 targets.at(i)->torque = desiredTorque;
436 if (!targets.at(i)->isValid())
439 <<
"Torque controller target is invalid - setting to zero! set value: "
440 << targets.at(i)->torque;
441 targets.at(i)->torque = 0.0f;
446 debugOutputData.getWriteBuffer().forceDesired_x = jointControlWrench(0);
447 debugOutputData.getWriteBuffer().forceDesired_y = jointControlWrench(1);
448 debugOutputData.getWriteBuffer().forceDesired_z = jointControlWrench(2);
449 debugOutputData.getWriteBuffer().forceDesired_rx = jointControlWrench(3);
450 debugOutputData.getWriteBuffer().forceDesired_ry = jointControlWrench(4);
451 debugOutputData.getWriteBuffer().forceDesired_rz = jointControlWrench(5);
456 debugOutputData.getWriteBuffer().targetPose_x = targetPose(0, 3);
457 debugOutputData.getWriteBuffer().targetPose_y = targetPose(1, 3);
458 debugOutputData.getWriteBuffer().targetPose_z = targetPose(2, 3);
459 VirtualRobot::MathTools::Quaternion targetQuat =
460 VirtualRobot::MathTools::eigen4f2quat(targetPose);
461 debugOutputData.getWriteBuffer().targetPose_qw = targetQuat.w;
462 debugOutputData.getWriteBuffer().targetPose_qx = targetQuat.x;
463 debugOutputData.getWriteBuffer().targetPose_qy = targetQuat.y;
464 debugOutputData.getWriteBuffer().targetPose_qz = targetQuat.z;
467 debugOutputData.getWriteBuffer().currentPose_x = currentPose(0, 3);
468 debugOutputData.getWriteBuffer().currentPose_y = currentPose(1, 3);
469 debugOutputData.getWriteBuffer().currentPose_z = currentPose(2, 3);
470 VirtualRobot::MathTools::Quaternion currentQuat =
471 VirtualRobot::MathTools::eigen4f2quat(currentPose);
472 debugOutputData.getWriteBuffer().currentPose_qw = currentQuat.w;
473 debugOutputData.getWriteBuffer().currentPose_qx = currentQuat.x;
474 debugOutputData.getWriteBuffer().currentPose_qy = currentQuat.y;
475 debugOutputData.getWriteBuffer().currentPose_qz = currentQuat.z;
476 debugOutputData.getWriteBuffer().deltaT = deltaT;
478 debugOutputData.getWriteBuffer().currentKpos_x = kpos.x();
479 debugOutputData.getWriteBuffer().currentKpos_y = kpos.y();
480 debugOutputData.getWriteBuffer().currentKpos_z = kpos.z();
481 debugOutputData.getWriteBuffer().currentKori_x = kori.x();
482 debugOutputData.getWriteBuffer().currentKori_y = kori.y();
483 debugOutputData.getWriteBuffer().currentKori_z = kori.z();
484 debugOutputData.getWriteBuffer().currentKnull_x = knull.x();
485 debugOutputData.getWriteBuffer().currentKnull_y = knull.y();
486 debugOutputData.getWriteBuffer().currentKnull_z = knull.z();
488 debugOutputData.getWriteBuffer().currentDpos_x = dpos.x();
489 debugOutputData.getWriteBuffer().currentDpos_y = dpos.y();
490 debugOutputData.getWriteBuffer().currentDpos_z = dpos.z();
491 debugOutputData.getWriteBuffer().currentDori_x = dori.x();
492 debugOutputData.getWriteBuffer().currentDori_y = dori.y();
493 debugOutputData.getWriteBuffer().currentDori_z = dori.z();
494 debugOutputData.getWriteBuffer().currentDnull_x = dnull.x();
495 debugOutputData.getWriteBuffer().currentDnull_y = dnull.y();
496 debugOutputData.getWriteBuffer().currentDnull_z = dnull.z();
498 debugOutputData.commitWrite();
653 auto values = debugOutputData.getUpToDateReadBuffer().desired_torques;
654 for (
auto& pair : values)
656 datafields[
"torqueDesired_" + pair.first] =
new Variant(pair.second);
659 auto values_null = debugOutputData.getUpToDateReadBuffer().desired_nullspaceJoint;
660 for (
auto& pair : values_null)
662 datafields[
"nullspaceDesired_" + pair.first] =
new Variant(pair.second);
665 datafields[
"canVal"] =
new Variant(debugOutputData.getUpToDateReadBuffer().currentCanVal);
666 datafields[
"mpcfactor"] =
new Variant(debugOutputData.getUpToDateReadBuffer().mpcfactor);
667 datafields[
"targetPose_x"] =
668 new Variant(debugOutputData.getUpToDateReadBuffer().targetPose_x);
669 datafields[
"targetPose_y"] =
670 new Variant(debugOutputData.getUpToDateReadBuffer().targetPose_y);
671 datafields[
"targetPose_z"] =
672 new Variant(debugOutputData.getUpToDateReadBuffer().targetPose_z);
673 datafields[
"targetPose_qw"] =
674 new Variant(debugOutputData.getUpToDateReadBuffer().targetPose_qw);
675 datafields[
"targetPose_qx"] =
676 new Variant(debugOutputData.getUpToDateReadBuffer().targetPose_qx);
677 datafields[
"targetPose_qy"] =
678 new Variant(debugOutputData.getUpToDateReadBuffer().targetPose_qy);
679 datafields[
"targetPose_qz"] =
680 new Variant(debugOutputData.getUpToDateReadBuffer().targetPose_qz);
682 datafields[
"currentPose_x"] =
683 new Variant(debugOutputData.getUpToDateReadBuffer().currentPose_x);
684 datafields[
"currentPose_y"] =
685 new Variant(debugOutputData.getUpToDateReadBuffer().currentPose_y);
686 datafields[
"currentPose_z"] =
687 new Variant(debugOutputData.getUpToDateReadBuffer().currentPose_z);
688 datafields[
"currentPose_qw"] =
689 new Variant(debugOutputData.getUpToDateReadBuffer().currentPose_qw);
690 datafields[
"currentPose_qx"] =
691 new Variant(debugOutputData.getUpToDateReadBuffer().currentPose_qx);
692 datafields[
"currentPose_qy"] =
693 new Variant(debugOutputData.getUpToDateReadBuffer().currentPose_qy);
694 datafields[
"currentPose_qz"] =
695 new Variant(debugOutputData.getUpToDateReadBuffer().currentPose_qz);
697 datafields[
"currentKpos_x"] =
698 new Variant(debugOutputData.getUpToDateReadBuffer().currentKpos_x);
699 datafields[
"currentKpos_y"] =
700 new Variant(debugOutputData.getUpToDateReadBuffer().currentKpos_y);
701 datafields[
"currentKpos_z"] =
702 new Variant(debugOutputData.getUpToDateReadBuffer().currentKpos_z);
703 datafields[
"currentKori_x"] =
704 new Variant(debugOutputData.getUpToDateReadBuffer().currentKori_x);
705 datafields[
"currentKori_y"] =
706 new Variant(debugOutputData.getUpToDateReadBuffer().currentKori_y);
707 datafields[
"currentKori_z"] =
708 new Variant(debugOutputData.getUpToDateReadBuffer().currentKori_z);
709 datafields[
"currentKnull_x"] =
710 new Variant(debugOutputData.getUpToDateReadBuffer().currentKnull_x);
711 datafields[
"currentKnull_y"] =
712 new Variant(debugOutputData.getUpToDateReadBuffer().currentKnull_y);
713 datafields[
"currentKnull_z"] =
714 new Variant(debugOutputData.getUpToDateReadBuffer().currentKnull_z);
716 datafields[
"currentDpos_x"] =
717 new Variant(debugOutputData.getUpToDateReadBuffer().currentDpos_x);
718 datafields[
"currentDpos_y"] =
719 new Variant(debugOutputData.getUpToDateReadBuffer().currentDpos_y);
720 datafields[
"currentDpos_z"] =
721 new Variant(debugOutputData.getUpToDateReadBuffer().currentDpos_z);
722 datafields[
"currentDori_x"] =
723 new Variant(debugOutputData.getUpToDateReadBuffer().currentDori_x);
724 datafields[
"currentDori_y"] =
725 new Variant(debugOutputData.getUpToDateReadBuffer().currentDori_y);
726 datafields[
"currentDori_z"] =
727 new Variant(debugOutputData.getUpToDateReadBuffer().currentDori_z);
728 datafields[
"currentDnull_x"] =
729 new Variant(debugOutputData.getUpToDateReadBuffer().currentDnull_x);
730 datafields[
"currentDnull_y"] =
731 new Variant(debugOutputData.getUpToDateReadBuffer().currentDnull_y);
732 datafields[
"currentDnull_z"] =
733 new Variant(debugOutputData.getUpToDateReadBuffer().currentDnull_z);
735 datafields[
"forceDesired_x"] =
736 new Variant(debugOutputData.getUpToDateReadBuffer().forceDesired_x);
737 datafields[
"forceDesired_y"] =
738 new Variant(debugOutputData.getUpToDateReadBuffer().forceDesired_y);
739 datafields[
"forceDesired_z"] =
740 new Variant(debugOutputData.getUpToDateReadBuffer().forceDesired_z);
741 datafields[
"forceDesired_rx"] =
742 new Variant(debugOutputData.getUpToDateReadBuffer().forceDesired_rx);
743 datafields[
"forceDesired_ry"] =
744 new Variant(debugOutputData.getUpToDateReadBuffer().forceDesired_ry);
745 datafields[
"forceDesired_rz"] =
746 new Variant(debugOutputData.getUpToDateReadBuffer().forceDesired_rz);
748 datafields[
"deltaT"] =
new Variant(debugOutputData.getUpToDateReadBuffer().deltaT);
750 std::string channelName = cfg->nodeSetName +
"_TaskSpaceImpedanceControl";
751 debugObs->setDebugChannel(channelName, datafields);