8 "DeprecatedNJointTaskSpaceAdmittanceDMPController");
11 const RobotUnitPtr& robotUnit,
12 const armarx::NJointControllerConfigPtr& config,
15 ARMARX_INFO <<
"creating task-space admittance dmp controller";
18 cfg = DeprecatedNJointTaskSpaceAdmittanceDMPControllerConfigPtr::dynamicCast(config);
22 VirtualRobot::RobotNodeSetPtr rns =
rtGetRobot()->getRobotNodeSet(cfg->nodeSetName);
24 for (
size_t i = 0; i < rns->getSize(); ++i)
26 std::string jointName = rns->getNode(i)->getName();
27 jointNames.push_back(jointName);
31 targets.push_back(ct->
asA<ControlTarget1DoFActuatorTorque>());
33 const SensorValue1DoFActuatorVelocity* velocitySensor = sv->
asA<SensorValue1DoFActuatorVelocity>();
34 const SensorValue1DoFActuatorPosition* positionSensor = sv->
asA<SensorValue1DoFActuatorPosition>();
45 velocitySensors.push_back(velocitySensor);
46 positionSensors.push_back(positionSensor);
50 ik.reset(
new VirtualRobot::DifferentialIK(rns,
rtGetRobot()->getRootNode(), VirtualRobot::JacobiProvider::eSVDDamped));
51 ik->setDampedSvdLambda(0.0001);
52 numOfJoints = targets.size();
53 qvel_filtered.setZero(targets.size());
54 torqueLimit = cfg->jointTorqueLimit;
57 const SensorValueBase* svlf = robotUnit->getSensorDevice(cfg->forceSensorName)->getSensorValue();
61 Eigen::Vector3f tcpCoMInForceSensorFrame;
62 tcpCoMInForceSensorFrame.setZero();
64 enableTCPGravityCompensation.store(cfg->enableTCPGravityCompensation);
66 if (enableTCPGravityCompensation.load())
68 tcpMass = cfg->tcpMass;
69 tcpCoMInForceSensorFrame = cfg->tcpCoMInForceSensorFrame;
72 forceOffset.setZero();
73 torqueOffset.setZero();
74 filteredForce.setZero();
75 filteredTorque.setZero();
76 filteredForceInRoot.setZero();
77 filteredTorqueInRoot.setZero();
85 taskSpaceDMPConfig.
DMPMode = cfg->dmpMode;
86 taskSpaceDMPConfig.
DMPStyle = cfg->dmpType;
98 kinematic_chain = cfg->nodeSetName;
101 useNullSpaceJointDMP = cfg->useNullSpaceJointDMP;
102 nullSpaceJointDMPPtr.reset(
new DMP::UMIDMP(100));
103 isNullSpaceJointDMPLearned =
false;
107 virtualAcc.setZero();
108 virtualVel.setZero();
115 CtrlParams initParams =
117 cfg->kpImpedance, cfg->kdImpedance,
118 cfg->kpAdmittance, cfg->kdAdmittance, cfg->kmAdmittance,
119 cfg->Knull, cfg->Dnull,
120 Eigen::Vector3f::Zero(), Eigen::Vector3f::Zero(),
121 tcpMass, tcpCoMInForceSensorFrame
140 RT2InterfaceData rt2InterfaceData;
141 rt2InterfaceData.currentTcpPose = tcp->getPoseInRootFrame();
146 rt2MPData.currentPose = tcp->getPoseInRootFrame();
147 rt2MPData.currentTime = 0;
148 rt2MPData.deltaT = 0;
149 rt2MPData.currentTwist.setZero();
153 runTask(
"DeprecatedNJointTaskSpaceAdmittanceDMPController", [&]
157 while (
getState() == eManagedIceObjectStarted)
163 c.waitForCycleDuration();
172 return "DeprecatedNJointTaskSpaceAdmittanceDMPController";
190 double deltaT = 0.001;
192 Eigen::VectorXf currentTwist = rt2MPBuffer.
getReadBuffer().currentTwist;
194 if (mpRunning.load() && dmpCtrl->canVal > 1e-8)
196 dmpCtrl->flow(deltaT, currentPose, currentTwist);
198 Eigen::VectorXf targetNullSpaceJointValues = cfg->targetNullSpaceJointValues;
199 if (useNullSpaceJointDMP && isNullSpaceJointDMPLearned)
202 currentJointState = nullSpaceJointDMPPtr->calculateDirectlyVelocity(currentJointState,
203 dmpCtrl->canVal / cfg->timeDuration,
204 deltaT / cfg->timeDuration,
207 if (targetJointState.size() == targets.size())
209 for (
size_t i = 0; i < targetJointState.size(); ++i)
211 targetNullSpaceJointValues(i) = targetJointState[i];
226 mpRunning.store(
false);
238 Eigen::MatrixXf jacobi = ik->getJacobianMatrix(tcp, VirtualRobot::IKSolver::CartesianSelection::All);
240 Eigen::VectorXf qpos(positionSensors.size());
241 Eigen::VectorXf qvel(velocitySensors.size());
242 for (
size_t i = 0; i < positionSensors.size(); ++i)
244 qpos(i) = positionSensors[i]->position;
245 qvel(i) = velocitySensors[i]->velocity;
247 qvel_filtered = (1 - cfg->qvelFilter) * qvel_filtered + cfg->qvelFilter * qvel;
248 Eigen::VectorXf currentTwist = jacobi * qvel_filtered;
249 jacobi.block(0, 0, 3, numOfJoints) = 0.001 * jacobi.block(0, 0, 3, numOfJoints);
251 double deltaT = timeSinceLastIteration.toSecondsDouble();
284 forceTorque.setZero();
285 tcpGravityCompensation.setZero();
290 Eigen::VectorXf targetNullSpaceJointValues =
rtGetControlStruct().targetNullSpaceJointValues;
292 if (rtFirstRun.load())
294 rtReady.store(
false);
295 rtFirstRun.store(
false);
296 timeForCalibration = 0;
297 forceOffset.setZero();
298 torqueOffset.setZero();
300 targetPose = currentPose;
301 previousTargetPose = currentPose;
302 virtualPose = currentPose;
305 forceFrameInTCP.block<3, 3>(0, 0) = currentPose.block<3, 3>(0, 0).transpose() * forceFrameInRoot.block<3, 3>(0, 0);
306 tcpCoMInTCPFrame = forceFrameInTCP.block<3, 3>(0, 0) * tcpCoMInFTFrame;
307 ARMARX_IMPORTANT <<
"impedance control first run with\n" <<
VAROUT(targetPose) <<
"\nTCP CoM Vec (in TCP frame): \n" <<
VAROUT(tcpCoMInTCPFrame);
311 if (enableTCPGravityCompensation.load())
317 targetPose = previousTargetPose;
318 forceOffset = (1 - cfg->forceFilter) * forceOffset + cfg->forceFilter * (forceSensor->
force - tcpGravityCompensation.head(3));
319 torqueOffset = (1 - cfg->forceFilter) * torqueOffset + cfg->forceFilter * (forceSensor->
torque - tcpGravityCompensation.tail(3));
320 timeForCalibration = timeForCalibration + deltaT;
321 if (timeForCalibration > cfg->waitTimeForCalibration)
335 if ((previousTargetPose.block<3, 1>(0, 3) - targetPose.block<3, 1>(0, 3)).norm() > 100.0f)
338 targetPose = previousTargetPose;
340 previousTargetPose = targetPose;
347 Eigen::VectorXf poseError(6);
348 poseError.head(3) = virtualPose.block<3, 1>(0, 3) - targetPose.block<3, 1>(0, 3);
349 Eigen::Matrix3f objDiffMat = virtualPose.block<3, 3>(0, 0) * targetPose.block<3, 3>(0, 0).transpose();
350 poseError.tail(3) = VirtualRobot::MathTools::eigen3f2rpy(objDiffMat);
355 acc = kmAdmittance.cwiseProduct(forceTorque) - kpAdmittance.cwiseProduct(poseError) - kdAdmittance.cwiseProduct(virtualVel);
356 vel = virtualVel + 0.5 * deltaT * (acc + virtualAcc);
357 Eigen::VectorXf deltaPose = 0.5 * deltaT * (vel + virtualVel);
360 virtualPose.block<3, 1>(0, 3) += deltaPose.head(3);
361 Eigen::Matrix3f deltaPoseMat = VirtualRobot::MathTools::rpy2eigen3f(deltaPose(3), deltaPose(4), deltaPose(5));
362 virtualPose.block<3, 3>(0, 0) = deltaPoseMat * virtualPose.block<3, 3>(0, 0);
369 Eigen::Matrix3f diffMat = virtualPose.block<3, 3>(0, 0) * currentPose.block<3, 3>(0, 0).transpose();
370 poseErrorImp.head(3) = 0.001 * (virtualPose.block<3, 1>(0, 3) - currentPose.block<3, 1>(0, 3));
371 currentTwist.head(3) *= 0.001;
372 poseErrorImp.tail(3) = VirtualRobot::MathTools::eigen3f2rpy(diffMat);
373 Eigen::Vector6f forceImpedance = kpImpedance.cwiseProduct(poseErrorImp) - kdImpedance.cwiseProduct(currentTwist);
376 Eigen::VectorXf nullspaceTorque = knull.cwiseProduct(targetNullSpaceJointValues - qpos) - dnull.cwiseProduct(qvel);
380 Eigen::MatrixXf jtpinv = ik->computePseudoInverseJacobianMatrix(jacobi.transpose(), 2.0);
381 Eigen::VectorXf jointDesiredTorques = jacobi.transpose() * forceImpedance + (I - jacobi.transpose() * jtpinv) * nullspaceTorque;
385 for (
size_t i = 0; i < targets.size(); ++i)
387 targets.at(i)->torque = jointDesiredTorques(i);
388 if (!targets.at(i)->isValid() || isnan(targets.at(i)->torque))
390 targets.at(i)->torque = 0.0f;
394 if (fabs(targets.at(i)->torque) > fabs(torqueLimit))
396 targets.at(i)->torque = fabs(torqueLimit) * (targets.at(i)->torque / fabs(targets.at(i)->torque));
400 debugRTBuffer.
getWriteBuffer().desired_torques[jointNames[i]] = targets.at(i)->torque;
401 debugRTBuffer.
getWriteBuffer().desired_nullspaceJoint[jointNames[i]] = targetNullSpaceJointValues(i);
407 debugRTBuffer.
getWriteBuffer().forceDesired_x = forceImpedance(0);
408 debugRTBuffer.
getWriteBuffer().forceDesired_y = forceImpedance(1);
409 debugRTBuffer.
getWriteBuffer().forceDesired_z = forceImpedance(2);
410 debugRTBuffer.
getWriteBuffer().forceDesired_rx = forceImpedance(3);
411 debugRTBuffer.
getWriteBuffer().forceDesired_ry = forceImpedance(4);
412 debugRTBuffer.
getWriteBuffer().forceDesired_rz = forceImpedance(5);
421 debugRTBuffer.
getWriteBuffer().ft_FilteredInRoot_x = forceTorque(0);
422 debugRTBuffer.
getWriteBuffer().ft_FilteredInRoot_y = forceTorque(1);
423 debugRTBuffer.
getWriteBuffer().ft_FilteredInRoot_z = forceTorque(2);
424 debugRTBuffer.
getWriteBuffer().ft_FilteredInRoot_rx = forceTorque(3);
425 debugRTBuffer.
getWriteBuffer().ft_FilteredInRoot_ry = forceTorque(4);
426 debugRTBuffer.
getWriteBuffer().ft_FilteredInRoot_rz = forceTorque(5);
479 debugRTBuffer.
getWriteBuffer().gravityCompensation = tcpGravityCompensation;
492 Eigen::Vector3f gravity;
493 gravity << 0.0, 0.0, -9.8;
494 Eigen::Vector3f localGravity = currentPose.block<3, 3>(0, 0).
transpose() * gravity;
495 Eigen::Vector3f localForceVec = tcpMass * localGravity;
496 Eigen::Vector3f localTorqueVec = tcpCoMInTCPFrame.cross(localForceVec);
500 tcpGravityCompensation << localForceVec, localTorqueVec;
501 return tcpGravityCompensation;
507 filteredForce = (1 - cfg->forceFilter) * filteredForce + cfg->forceFilter * forceSensor->
force;
508 filteredTorque = (1 - cfg->forceFilter) * filteredTorque + cfg->forceFilter * forceSensor->
torque;
511 filteredForceInRoot = forceFrameInRoot.block<3, 3>(0, 0) * (filteredForce - forceOffset - handCompensatedFT.head(3)) - forceBaseline;
512 filteredTorqueInRoot = forceFrameInRoot.block<3, 3>(0, 0) * (filteredTorque - torqueOffset - handCompensatedFT.tail(3)) - torqueBaseline;
514 for (
size_t i = 0; i < 3; ++i)
516 if (fabs(filteredForceInRoot(i)) > cfg->forceDeadZone)
518 filteredForceInRoot(i) -= (filteredForceInRoot(i) / fabs(filteredForceInRoot(i))) * cfg->forceDeadZone;
522 filteredForceInRoot(i) = 0;
525 if (fabs(filteredTorqueInRoot(i)) > cfg->torqueDeadZone)
527 filteredTorqueInRoot(i) -= (filteredTorqueInRoot(i) / fabs(filteredTorqueInRoot(i))) * cfg->torqueDeadZone;
531 filteredTorqueInRoot(i) = 0;
536 forceTorque << filteredForceInRoot, filteredTorqueInRoot;
542 return kinematic_chain;
552 dmpCtrl->learnDMPFromFiles(fileNames);
558 return !mpRunning.load();
566 dmpCtrl->setViaPose(u, viapoint);
572 dmpCtrl->setGoalPoseVec(goals);
579 dmpCtrl->removeAllViaPoints();
580 dmpCtrl->setViaPose(1.0, starts);
581 dmpCtrl->setViaPose(1e-8, goals);
586 const Ice::FloatSeq& currentJVS,
589 DMP::Vec<DMP::SampledTrajectoryV2> trajs;
591 DMP::SampledTrajectoryV2 traj;
592 traj.readFromCSVFile(fileName);
594 if (traj.dim() != targets.size())
596 isNullSpaceJointDMPLearned =
false;
601 goal.resize(traj.dim());
602 currentJointState.resize(traj.dim());
604 for (
size_t i = 0; i < goal.size(); ++i)
606 goal.at(i) = traj.rbegin()->getPosition(i);
607 currentJointState.at(i).pos = currentJVS.at(i);
608 currentJointState.at(i).vel = 0;
611 trajs.push_back(traj);
612 nullSpaceJointDMPPtr->learnFromTrajectories(trajs);
615 nullSpaceJointDMPPtr->prepareExecution(goal, currentJointState, 1.0, 1.0);
617 isNullSpaceJointDMPLearned =
true;
624 if (mpRunning.load())
633 mpRunning.store(
false);
641 dmpCtrl->pauseController();
647 return dmpCtrl->saveDMPToString();
652 dmpCtrl->loadDMPFromString(dmpString);
653 return dmpCtrl->dmpPtr->defaultGoal;
658 return dmpCtrl->canVal;
663 dmpCtrl->resumeController();
669 useNullSpaceJointDMP = enable;
676 dmpCtrl->canVal = timeDuration;
677 dmpCtrl->config.motionTimeDuration = timeDuration;
684 return dmpCtrl->canVal;
689 rtFirstRun.store(
true);
690 while (rtFirstRun.load() || !rtReady.load() || !rt2InterfaceBuffer.
updateReadBuffer())
698 dmpCtrl->prepareExecution(dmpCtrl->eigen4f2vec(pose), goals);
700 if (isNullSpaceJointDMPLearned && useNullSpaceJointDMP)
707 mpRunning.store(
true);
708 dmpCtrl->resumeController();
720 datafields[
"torqueDesired_" + pair.first] =
new Variant(pair.second);
724 for (
auto& pair : values_null)
726 datafields[
"nullspaceDesired_" + pair.first] =
new Variant(pair.second);
827 std::string channelName = cfg->nodeSetName +
"_TaskSpaceAdmittanceControl";
828 debugObs->setDebugChannel(channelName, datafields);
838 dmpCtrl->setWeights(weights);
843 DMP::DVec2d res = dmpCtrl->getWeights();
845 for (
size_t i = 0; i < res.size(); ++i)
847 std::vector<double> cvec;
848 for (
size_t j = 0; j < res[i].size(); ++j)
850 cvec.push_back(res[i][j]);
852 resvec.push_back(cvec);
862 dmpCtrl->removeAllViaPoints();