3 #include <VirtualRobot/IK/DifferentialIK.h>
4 #include <VirtualRobot/MathTools.h>
5 #include <VirtualRobot/Nodes/RobotNode.h>
6 #include <VirtualRobot/Nodes/Sensor.h>
7 #include <VirtualRobot/RobotNodeSet.h>
17 #include <dmp/representation/dmp/umitsmp.h>
21 NJointControllerRegistration<DeprecatedNJointTaskSpaceAdmittanceDMPController>
23 "DeprecatedNJointTaskSpaceAdmittanceDMPController");
28 const armarx::NJointControllerConfigPtr& config,
31 ARMARX_INFO <<
"creating task-space admittance dmp controller";
34 cfg = DeprecatedNJointTaskSpaceAdmittanceDMPControllerConfigPtr::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();
43 jointNames.push_back(jointName);
47 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);
68 ik.reset(
new VirtualRobot::DifferentialIK(
69 rns,
rtGetRobot()->getRootNode(), VirtualRobot::JacobiProvider::eSVDDamped));
70 ik->setDampedSvdLambda(0.0001);
71 numOfJoints = targets.size();
72 qvel_filtered.setZero(targets.size());
73 torqueLimit = cfg->jointTorqueLimit;
77 robotUnit->getSensorDevice(cfg->forceSensorName)->getSensorValue();
81 Eigen::Vector3f tcpCoMInForceSensorFrame;
82 tcpCoMInForceSensorFrame.setZero();
84 enableTCPGravityCompensation.store(cfg->enableTCPGravityCompensation);
86 if (enableTCPGravityCompensation.load())
88 tcpMass = cfg->tcpMass;
89 tcpCoMInForceSensorFrame = cfg->tcpCoMInForceSensorFrame;
92 forceOffset.setZero();
93 torqueOffset.setZero();
94 filteredForce.setZero();
95 filteredTorque.setZero();
96 filteredForceInRoot.setZero();
97 filteredTorqueInRoot.setZero();
105 taskSpaceDMPConfig.
DMPMode = cfg->dmpMode;
106 taskSpaceDMPConfig.
DMPStyle = cfg->dmpType;
119 kinematic_chain = cfg->nodeSetName;
122 useNullSpaceJointDMP = cfg->useNullSpaceJointDMP;
123 nullSpaceJointDMPPtr.reset(
new DMP::UMIDMP(100));
124 isNullSpaceJointDMPLearned =
false;
128 virtualAcc.setZero();
129 virtualVel.setZero();
136 CtrlParams initParams = {cfg->kpImpedance,
143 Eigen::Vector3f::Zero(),
144 Eigen::Vector3f::Zero(),
146 tcpCoMInForceSensorFrame};
165 RT2InterfaceData rt2InterfaceData;
166 rt2InterfaceData.currentTcpPose = tcp->getPoseInRootFrame();
171 rt2MPData.currentPose = tcp->getPoseInRootFrame();
172 rt2MPData.currentTime = 0;
173 rt2MPData.deltaT = 0;
174 rt2MPData.currentTwist.setZero();
178 runTask(
"DeprecatedNJointTaskSpaceAdmittanceDMPController",
183 while (
getState() == eManagedIceObjectStarted)
189 c.waitForCycleDuration();
199 return "DeprecatedNJointTaskSpaceAdmittanceDMPController";
216 double deltaT = 0.001;
218 Eigen::VectorXf currentTwist = rt2MPBuffer.
getReadBuffer().currentTwist;
220 if (mpRunning.load() && dmpCtrl->canVal > 1e-8)
222 dmpCtrl->flow(deltaT, currentPose, currentTwist);
224 Eigen::VectorXf targetNullSpaceJointValues = cfg->targetNullSpaceJointValues;
225 if (useNullSpaceJointDMP && isNullSpaceJointDMPLearned)
228 currentJointState = nullSpaceJointDMPPtr->calculateDirectlyVelocity(
230 dmpCtrl->canVal / cfg->timeDuration,
231 deltaT / cfg->timeDuration,
234 if (targetJointState.size() == targets.size())
236 for (
size_t i = 0; i < targetJointState.size(); ++i)
238 targetNullSpaceJointValues(i) = targetJointState[i];
253 mpRunning.store(
false);
267 Eigen::MatrixXf jacobi =
268 ik->getJacobianMatrix(tcp, VirtualRobot::IKSolver::CartesianSelection::All);
270 Eigen::VectorXf qpos(positionSensors.size());
271 Eigen::VectorXf qvel(velocitySensors.size());
272 for (
size_t i = 0; i < positionSensors.size(); ++i)
274 qpos(i) = positionSensors[i]->position;
275 qvel(i) = velocitySensors[i]->velocity;
277 qvel_filtered = (1 - cfg->qvelFilter) * qvel_filtered + cfg->qvelFilter * qvel;
278 Eigen::VectorXf currentTwist = jacobi * qvel_filtered;
279 jacobi.block(0, 0, 3, numOfJoints) =
280 0.001 * jacobi.block(0, 0, 3, numOfJoints);
282 double deltaT = timeSinceLastIteration.toSecondsDouble();
308 Eigen::Vector3f tcpCoMInFTFrame =
316 forceTorque.setZero();
317 tcpGravityCompensation.setZero();
322 Eigen::VectorXf targetNullSpaceJointValues =
325 if (rtFirstRun.load())
327 rtReady.store(
false);
328 rtFirstRun.store(
false);
329 timeForCalibration = 0;
330 forceOffset.setZero();
331 torqueOffset.setZero();
333 targetPose = currentPose;
334 previousTargetPose = currentPose;
335 virtualPose = currentPose;
338 rtGetRobot()->getSensor(cfg->forceSensorName)->getRobotNode()->getPoseInRootFrame();
339 forceFrameInTCP.block<3, 3>(0, 0) =
340 currentPose.block<3, 3>(0, 0).transpose() * forceFrameInRoot.block<3, 3>(0, 0);
341 tcpCoMInTCPFrame = forceFrameInTCP.block<3, 3>(0, 0) * tcpCoMInFTFrame;
343 <<
VAROUT(targetPose) <<
"\nTCP CoM Vec (in TCP frame): \n"
344 <<
VAROUT(tcpCoMInTCPFrame);
348 if (enableTCPGravityCompensation.load())
354 targetPose = previousTargetPose;
356 (1 - cfg->forceFilter) * forceOffset +
357 cfg->forceFilter * (forceSensor->
force - tcpGravityCompensation.head<3>());
359 (1 - cfg->forceFilter) * torqueOffset +
360 cfg->forceFilter * (forceSensor->
torque - tcpGravityCompensation.tail<3>());
361 timeForCalibration = timeForCalibration + deltaT;
362 if (timeForCalibration > cfg->waitTimeForCalibration)
366 <<
VAROUT(forceOffset) <<
"\n"
367 <<
VAROUT(torqueOffset) <<
"\n"
368 <<
VAROUT(tcpGravityCompensation);
379 if ((previousTargetPose.block<3, 1>(0, 3) - targetPose.block<3, 1>(0, 3)).norm() >
383 <<
VAROUT(targetPose) <<
"\nis too far away from\n"
384 <<
VAROUT(previousTargetPose);
385 targetPose = previousTargetPose;
387 previousTargetPose = targetPose;
395 Eigen::VectorXf poseError(6);
396 poseError.head<3>() = virtualPose.block<3, 1>(0, 3) - targetPose.block<3, 1>(0, 3);
398 virtualPose.block<3, 3>(0, 0) * targetPose.block<3, 3>(0, 0).transpose();
399 poseError.tail<3>() = VirtualRobot::MathTools::eigen3f2rpy(objDiffMat);
404 acc = kmAdmittance.cwiseProduct(forceTorque) - kpAdmittance.cwiseProduct(poseError) -
405 kdAdmittance.cwiseProduct(virtualVel);
406 vel = virtualVel + 0.5 * deltaT * (acc + virtualAcc);
407 Eigen::VectorXf deltaPose = 0.5 * deltaT * (vel + virtualVel);
410 virtualPose.block<3, 1>(0, 3) += deltaPose.head<3>();
412 VirtualRobot::MathTools::rpy2eigen3f(deltaPose(3), deltaPose(4), deltaPose(5));
413 virtualPose.block<3, 3>(0, 0) = deltaPoseMat * virtualPose.block<3, 3>(0, 0);
421 virtualPose.block<3, 3>(0, 0) * currentPose.block<3, 3>(0, 0).transpose();
422 poseErrorImp.head<3>() =
423 0.001 * (virtualPose.block<3, 1>(0, 3) - currentPose.block<3, 1>(0, 3));
424 currentTwist.head<3>() *= 0.001;
425 poseErrorImp.tail<3>() = VirtualRobot::MathTools::eigen3f2rpy(diffMat);
427 kpImpedance.cwiseProduct(poseErrorImp) - kdImpedance.cwiseProduct(currentTwist);
430 Eigen::VectorXf nullspaceTorque =
431 knull.cwiseProduct(targetNullSpaceJointValues - qpos) - dnull.cwiseProduct(qvel);
435 Eigen::MatrixXf jtpinv = ik->computePseudoInverseJacobianMatrix(jacobi.transpose(), 2.0);
436 Eigen::VectorXf jointDesiredTorques = jacobi.transpose() * forceImpedance +
437 (I - jacobi.transpose() * jtpinv) * nullspaceTorque;
441 for (
size_t i = 0; i < targets.size(); ++i)
443 targets.at(i)->torque = jointDesiredTorques(i);
444 if (!targets.at(i)->isValid() || isnan(targets.at(i)->torque))
446 targets.at(i)->torque = 0.0f;
450 if (fabs(targets.at(i)->torque) > fabs(torqueLimit))
452 targets.at(i)->torque =
453 fabs(torqueLimit) * (targets.at(i)->torque / fabs(targets.at(i)->torque));
457 debugRTBuffer.
getWriteBuffer().desired_torques[jointNames[i]] = targets.at(i)->torque;
458 debugRTBuffer.
getWriteBuffer().desired_nullspaceJoint[jointNames[i]] =
459 targetNullSpaceJointValues(i);
465 debugRTBuffer.
getWriteBuffer().forceDesired_x = forceImpedance(0);
466 debugRTBuffer.
getWriteBuffer().forceDesired_y = forceImpedance(1);
467 debugRTBuffer.
getWriteBuffer().forceDesired_z = forceImpedance(2);
468 debugRTBuffer.
getWriteBuffer().forceDesired_rx = forceImpedance(3);
469 debugRTBuffer.
getWriteBuffer().forceDesired_ry = forceImpedance(4);
470 debugRTBuffer.
getWriteBuffer().forceDesired_rz = forceImpedance(5);
479 debugRTBuffer.
getWriteBuffer().ft_FilteredInRoot_x = forceTorque(0);
480 debugRTBuffer.
getWriteBuffer().ft_FilteredInRoot_y = forceTorque(1);
481 debugRTBuffer.
getWriteBuffer().ft_FilteredInRoot_z = forceTorque(2);
482 debugRTBuffer.
getWriteBuffer().ft_FilteredInRoot_rx = forceTorque(3);
483 debugRTBuffer.
getWriteBuffer().ft_FilteredInRoot_ry = forceTorque(4);
484 debugRTBuffer.
getWriteBuffer().ft_FilteredInRoot_rz = forceTorque(5);
490 VirtualRobot::MathTools::eigen4f2quat(targetPose);
500 VirtualRobot::MathTools::eigen4f2quat(virtualPose);
512 VirtualRobot::MathTools::eigen4f2quat(currentPose);
540 debugRTBuffer.
getWriteBuffer().gravityCompensation = tcpGravityCompensation;
556 Eigen::Vector3f gravity;
557 gravity << 0.0, 0.0, -9.8;
558 Eigen::Vector3f localGravity = currentPose.block<3, 3>(0, 0).
transpose() * gravity;
559 Eigen::Vector3f localForceVec = tcpMass * localGravity;
560 Eigen::Vector3f localTorqueVec = tcpCoMInTCPFrame.cross(localForceVec);
564 tcpGravityCompensation << localForceVec, localTorqueVec;
565 return tcpGravityCompensation;
570 Eigen::Vector3f& forceBaseline,
571 Eigen::Vector3f& torqueBaseline,
575 (1 - cfg->forceFilter) * filteredForce + cfg->forceFilter * forceSensor->
force;
577 (1 - cfg->forceFilter) * filteredTorque + cfg->forceFilter * forceSensor->
torque;
580 rtGetRobot()->getSensor(cfg->forceSensorName)->getRobotNode()->getPoseInRootFrame();
581 filteredForceInRoot = forceFrameInRoot.block<3, 3>(0, 0) *
582 (filteredForce - forceOffset - handCompensatedFT.head<3>()) -
584 filteredTorqueInRoot = forceFrameInRoot.block<3, 3>(0, 0) *
585 (filteredTorque - torqueOffset - handCompensatedFT.tail<3>()) -
588 for (
size_t i = 0; i < 3; ++i)
590 if (fabs(filteredForceInRoot(i)) > cfg->forceDeadZone)
592 filteredForceInRoot(i) -=
593 (filteredForceInRoot(i) / fabs(filteredForceInRoot(i))) * cfg->forceDeadZone;
597 filteredForceInRoot(i) = 0;
600 if (fabs(filteredTorqueInRoot(i)) > cfg->torqueDeadZone)
602 filteredTorqueInRoot(i) -=
603 (filteredTorqueInRoot(i) / fabs(filteredTorqueInRoot(i))) * cfg->torqueDeadZone;
607 filteredTorqueInRoot(i) = 0;
612 forceTorque << filteredForceInRoot, filteredTorqueInRoot;
619 return kinematic_chain;
629 const Ice::StringSeq& fileNames,
632 dmpCtrl->learnDMPFromFiles(fileNames);
639 return !mpRunning.load();
644 const Ice::DoubleSeq& viapoint,
649 dmpCtrl->setViaPose(u, viapoint);
654 const Ice::Current& ice)
656 dmpCtrl->setGoalPoseVec(goals);
661 const Ice::DoubleSeq& goals,
662 const Ice::Current& ice)
665 dmpCtrl->removeAllViaPoints();
666 dmpCtrl->setViaPose(1.0, starts);
667 dmpCtrl->setViaPose(1e-8, goals);
672 const std::string& fileName,
673 const Ice::FloatSeq& currentJVS,
676 DMP::Vec<DMP::SampledTrajectoryV2> trajs;
678 DMP::SampledTrajectoryV2 traj;
679 traj.readFromCSVFile(fileName);
681 if (traj.dim() != targets.size())
683 isNullSpaceJointDMPLearned =
false;
688 goal.resize(traj.dim());
689 currentJointState.resize(traj.dim());
691 for (
size_t i = 0; i < goal.size(); ++i)
693 goal.at(i) = traj.rbegin()->getPosition(i);
694 currentJointState.at(i).pos = currentJVS.at(i);
695 currentJointState.at(i).vel = 0;
698 trajs.push_back(traj);
699 nullSpaceJointDMPPtr->learnFromTrajectories(trajs);
702 nullSpaceJointDMPPtr->prepareExecution(goal, currentJointState, 1.0, 1.0);
704 isNullSpaceJointDMPLearned =
true;
711 if (mpRunning.load())
721 mpRunning.store(
false);
730 dmpCtrl->pauseController();
737 return dmpCtrl->saveDMPToString();
742 const std::string& dmpString,
745 dmpCtrl->loadDMPFromString(dmpString);
746 return dmpCtrl->dmpPtr->defaultGoal;
752 return dmpCtrl->canVal;
758 dmpCtrl->resumeController();
766 useNullSpaceJointDMP = enable;
774 dmpCtrl->canVal = timeDuration;
775 dmpCtrl->config.motionTimeDuration = timeDuration;
783 return dmpCtrl->canVal;
790 rtFirstRun.store(
true);
791 while (rtFirstRun.load() || !rtReady.load() || !rt2InterfaceBuffer.
updateReadBuffer())
799 dmpCtrl->prepareExecution(dmpCtrl->eigen4f2vec(pose), goals);
801 if (isNullSpaceJointDMPLearned && useNullSpaceJointDMP)
808 mpRunning.store(
true);
809 dmpCtrl->resumeController();
823 datafields[
"torqueDesired_" + pair.first] =
new Variant(pair.second);
827 for (
auto& pair : values_null)
829 datafields[
"nullspaceDesired_" + pair.first] =
new Variant(pair.second);
834 datafields[
"targetPose_x"] =
836 datafields[
"targetPose_y"] =
838 datafields[
"targetPose_z"] =
840 datafields[
"targetPose_qw"] =
842 datafields[
"targetPose_qx"] =
844 datafields[
"targetPose_qy"] =
846 datafields[
"targetPose_qz"] =
849 datafields[
"virtualPose_x"] =
851 datafields[
"virtualPose_y"] =
853 datafields[
"virtualPose_z"] =
855 datafields[
"virtualPose_qw"] =
857 datafields[
"virtualPose_qx"] =
859 datafields[
"virtualPose_qy"] =
861 datafields[
"virtualPose_qz"] =
864 datafields[
"currentPose_x"] =
866 datafields[
"currentPose_y"] =
868 datafields[
"currentPose_z"] =
870 datafields[
"currentPose_qw"] =
872 datafields[
"currentPose_qx"] =
874 datafields[
"currentPose_qy"] =
876 datafields[
"currentPose_qz"] =
879 datafields[
"currentKpos_x"] =
881 datafields[
"currentKpos_y"] =
883 datafields[
"currentKpos_z"] =
885 datafields[
"currentKori_x"] =
887 datafields[
"currentKori_y"] =
889 datafields[
"currentKori_z"] =
891 datafields[
"currentKnull_x"] =
893 datafields[
"currentKnull_y"] =
895 datafields[
"currentKnull_z"] =
898 datafields[
"currentDpos_x"] =
900 datafields[
"currentDpos_y"] =
902 datafields[
"currentDpos_z"] =
904 datafields[
"currentDori_x"] =
906 datafields[
"currentDori_y"] =
908 datafields[
"currentDori_z"] =
910 datafields[
"currentDnull_x"] =
912 datafields[
"currentDnull_y"] =
914 datafields[
"currentDnull_z"] =
917 datafields[
"forceDesired_x"] =
919 datafields[
"forceDesired_y"] =
921 datafields[
"forceDesired_z"] =
923 datafields[
"forceDesired_rx"] =
925 datafields[
"forceDesired_ry"] =
927 datafields[
"forceDesired_rz"] =
933 datafields[
"ft_InRoot_rx"] =
935 datafields[
"ft_InRoot_ry"] =
937 datafields[
"ft_InRoot_rz"] =
940 datafields[
"ft_FilteredInRoot_x"] =
942 datafields[
"ft_FilteredInRoot_y"] =
944 datafields[
"ft_FilteredInRoot_z"] =
946 datafields[
"ft_FilteredInRoot_rx"] =
948 datafields[
"ft_FilteredInRoot_ry"] =
950 datafields[
"ft_FilteredInRoot_rz"] =
955 datafields[
"kmAdmittance_x"] =
957 datafields[
"kmAdmittance_y"] =
959 datafields[
"kmAdmittance_z"] =
961 datafields[
"kmAdmittance_rx"] =
963 datafields[
"kmAdmittance_ry"] =
965 datafields[
"kmAdmittance_rz"] =
968 datafields[
"gravityCompensation_x"] =
970 datafields[
"gravityCompensation_y"] =
972 datafields[
"gravityCompensation_z"] =
974 datafields[
"gravityCompensation_rx"] =
976 datafields[
"gravityCompensation_ry"] =
978 datafields[
"gravityCompensation_rz"] =
982 datafields[
"ft_offset_x"] =
984 datafields[
"ft_offset_y"] =
986 datafields[
"ft_offset_z"] =
988 datafields[
"ft_offset_rx"] =
990 datafields[
"ft_offset_ry"] =
992 datafields[
"ft_offset_rz"] =
995 datafields[
"ft_Baseline_x"] =
997 datafields[
"ft_Baseline_y"] =
999 datafields[
"ft_Baseline_z"] =
1001 datafields[
"ft_Baseline_rx"] =
1003 datafields[
"ft_Baseline_ry"] =
1005 datafields[
"ft_Baseline_rz"] =
1008 std::string channelName = cfg->nodeSetName +
"_TaskSpaceAdmittanceControl";
1009 debugObs->setDebugChannel(channelName, datafields);
1020 const Ice::Current&)
1022 dmpCtrl->setWeights(weights);
1028 DMP::DVec2d res = dmpCtrl->getWeights();
1029 DoubleSeqSeq resvec;
1030 for (
size_t i = 0; i < res.size(); ++i)
1032 std::vector<double> cvec;
1033 for (
size_t j = 0; j < res[i].size(); ++j)
1035 cvec.push_back(res[i][j]);
1037 resvec.push_back(cvec);
1048 dmpCtrl->removeAllViaPoints();
1054 const Ice::Current&)
1063 const Ice::Current&)
1072 const Ice::Current&)
1081 const Ice::Current&)
1090 const Ice::Current&)
1098 const Ice::Current&)
1106 const Ice::Current&)
1114 const Eigen::VectorXf& kd,
1115 const Ice::Current&)
1125 const Eigen::VectorXf& kp,
1126 const Ice::Current&)
1136 const Eigen::VectorXf& jointValues,
1137 const Ice::Current&)
1146 const Eigen::Vector3f& force,
1147 const Eigen::Vector3f& torque,
1148 const Ice::Current&)