2 #include <VirtualRobot/IK/DifferentialIK.h>
3 #include <VirtualRobot/MathTools.h>
4 #include <VirtualRobot/Nodes/RobotNode.h>
5 #include <VirtualRobot/Robot.h>
6 #include <VirtualRobot/RobotNodeSet.h>
19 #include <armarx/control/deprecated_njoint_mp_controller/task_space/TaskSpaceImpedanceDMPControllerInterface.h>
25 NJointControllerRegistration<NJointTaskSpaceImpedanceDMPController>
27 "NJointTaskSpaceImpedanceDMPController");
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();
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);
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};
139 torqueLimit = cfg->torqueLimit;
140 timeDuration = cfg->timeDuration;
142 NJointTaskSpaceImpedanceDMPControllerInterfaceData initInterfaceData;
146 NJointTaskSpaceImpedanceDMPControllerSensorData initControllerSensorData;
148 initControllerSensorData.currentTime = 0;
149 initControllerSensorData.deltaT = 0;
150 initControllerSensorData.currentTwist.setZero();
154 useForceStop =
false;
162 return "NJointTaskSpaceImpedanceDMPController";
170 initData.
targetPose = tcp->getPoseInRootFrame();
191 double deltaT = 0.001;
193 Eigen::VectorXf currentTwist = controllerSensorData.
getReadBuffer().currentTwist;
222 if (dmpCtrl->canVal < 1e-8)
231 dmpCtrl->flow(deltaT, currentPose, currentTwist);
233 Eigen::VectorXf desiredNullSpaceJointValues(jointNames.size());
234 if (useNullSpaceJointDMP && isNullSpaceJointDMPLearned)
237 currentJointState = nullSpaceJointDMPPtr->calculateDirectlyVelocity(
239 dmpCtrl->canVal / timeDuration,
240 deltaT / timeDuration,
243 if (targetJointState.size() == jointNames.size())
245 for (
size_t i = 0; i < targetJointState.size(); ++i)
247 desiredNullSpaceJointValues(i) = targetJointState[i];
252 desiredNullSpaceJointValues =
258 desiredNullSpaceJointValues =
281 double deltaT = timeSinceLastIteration.toSecondsDouble();
283 Eigen::VectorXf targetVel;
284 Eigen::VectorXf desiredNullSpaceJointValues;
288 targetPose = currentPose;
289 stopPose = currentPose;
290 targetVel.setZero(6);
297 targetPose = stopPose;
298 targetVel.setZero(6);
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;
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]) >
337 stopPose = currentPose;
338 targetVel.setZero(6);
339 desiredNullSpaceJointValues =
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;
364 controllerSensorData.
getWriteBuffer().currentTwist = currentTwist;
372 jacobi.block(0, 0, 3, numOfJoints) =
373 0.001 * jacobi.block(0, 0, 3, numOfJoints);
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);
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;
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;
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);
460 VirtualRobot::MathTools::eigen4f2quat(targetPose);
467 debugOutputData.
getWriteBuffer().currentPose_x = currentPose(0, 3);
468 debugOutputData.
getWriteBuffer().currentPose_y = currentPose(1, 3);
469 debugOutputData.
getWriteBuffer().currentPose_z = currentPose(2, 3);
471 VirtualRobot::MathTools::eigen4f2quat(currentPose);
505 dmpCtrl->learnDMPFromFiles(fileNames);
511 const Ice::DoubleSeq& viapoint,
516 dmpCtrl->setViaPose(u, viapoint);
521 const Ice::Current& ice)
523 dmpCtrl->setGoalPoseVec(goals);
528 const Ice::FloatSeq& currentJVS,
531 DMP::Vec<DMP::SampledTrajectoryV2> trajs;
533 DMP::SampledTrajectoryV2 traj;
534 traj.readFromCSVFile(fileName);
536 if (traj.dim() != jointNames.size())
538 isNullSpaceJointDMPLearned =
false;
543 goal.resize(traj.dim());
544 currentJointState.resize(traj.dim());
546 for (
size_t i = 0; i < goal.size(); ++i)
548 goal.at(i) = traj.rbegin()->getPosition(i);
549 currentJointState.at(i).pos = currentJVS.at(i);
550 currentJointState.at(i).vel = 0;
553 trajs.push_back(traj);
554 nullSpaceJointDMPPtr->learnFromTrajectories(trajs);
557 nullSpaceJointDMPPtr->prepareExecution(goal, currentJointState, 1.0, 1.0);
559 isNullSpaceJointDMPLearned =
true;
577 prematurely_stopped =
true;
589 useNullSpaceJointDMP = enable;
597 dmpCtrl->canVal = timeDuration;
598 dmpCtrl->config.motionTimeDuration = timeDuration;
607 prematurely_stopped =
false;
608 timeForCalibration = 0;
611 while (firstRun || timeForCalibration < cfg->waitTimeForCalibration)
613 if (prematurely_stopped.load())
615 ARMARX_WARNING <<
"StopDMP has been prematurely called; aborting runDMP";
627 dmpCtrl->prepareExecution(dmpCtrl->eigen4f2vec(pose), goals);
631 if (isNullSpaceJointDMPLearned && useNullSpaceJointDMP)
636 if (prematurely_stopped.load())
638 ARMARX_WARNING <<
"StopDMP has been prematurely called; aborting runDMP";
656 datafields[
"torqueDesired_" + pair.first] =
new Variant(pair.second);
660 for (
auto& pair : values_null)
662 datafields[
"nullspaceDesired_" + pair.first] =
new Variant(pair.second);
667 datafields[
"targetPose_x"] =
669 datafields[
"targetPose_y"] =
671 datafields[
"targetPose_z"] =
673 datafields[
"targetPose_qw"] =
675 datafields[
"targetPose_qx"] =
677 datafields[
"targetPose_qy"] =
679 datafields[
"targetPose_qz"] =
682 datafields[
"currentPose_x"] =
684 datafields[
"currentPose_y"] =
686 datafields[
"currentPose_z"] =
688 datafields[
"currentPose_qw"] =
690 datafields[
"currentPose_qx"] =
692 datafields[
"currentPose_qy"] =
694 datafields[
"currentPose_qz"] =
697 datafields[
"currentKpos_x"] =
699 datafields[
"currentKpos_y"] =
701 datafields[
"currentKpos_z"] =
703 datafields[
"currentKori_x"] =
705 datafields[
"currentKori_y"] =
707 datafields[
"currentKori_z"] =
709 datafields[
"currentKnull_x"] =
711 datafields[
"currentKnull_y"] =
713 datafields[
"currentKnull_z"] =
716 datafields[
"currentDpos_x"] =
718 datafields[
"currentDpos_y"] =
720 datafields[
"currentDpos_z"] =
722 datafields[
"currentDori_x"] =
724 datafields[
"currentDori_y"] =
726 datafields[
"currentDori_z"] =
728 datafields[
"currentDnull_x"] =
730 datafields[
"currentDnull_y"] =
732 datafields[
"currentDnull_z"] =
735 datafields[
"forceDesired_x"] =
737 datafields[
"forceDesired_y"] =
739 datafields[
"forceDesired_z"] =
741 datafields[
"forceDesired_rx"] =
743 datafields[
"forceDesired_ry"] =
745 datafields[
"forceDesired_rz"] =
750 std::string channelName = cfg->nodeSetName +
"_TaskSpaceImpedanceControl";
751 debugObs->setDebugChannel(channelName, datafields);
759 runTask(
"NJointTaskSpaceImpedanceDMPController",
764 while (
getState() == eManagedIceObjectStarted)
770 c.waitForCycleDuration();
785 dmpCtrl->setWeights(weights);
791 DMP::DVec2d res = dmpCtrl->getWeights();
793 for (
size_t i = 0; i < res.size(); ++i)
795 std::vector<double> cvec;
796 for (
size_t j = 0; j < res[i].size(); ++j)
798 cvec.push_back(res[i][j]);
800 resvec.push_back(cvec);
811 dmpCtrl->removeAllViaPoints();
882 const Eigen::VectorXf& jointValues,
893 return dmpCtrl->canVal;