2 #include <VirtualRobot/IK/DifferentialIK.h>
3 #include <VirtualRobot/Robot.h>
16 #include <armarx/control/deprecated_njoint_mp_controller/task_space/TaskSpaceImpedanceDMPControllerInterface.h>
22 NJointControllerRegistration<NJointTaskSpaceImpedanceDMPController>
24 "NJointTaskSpaceImpedanceDMPController");
27 const RobotUnitPtr& robotUnit,
28 const armarx::NJointControllerConfigPtr& config,
33 cfg = NJointTaskSpaceImpedanceDMPControllerConfigPtr::dynamicCast(config);
36 rns =
rtGetRobot()->getRobotNodeSet(cfg->nodeSetName);
39 for (
size_t i = 0; i < rns->getSize(); ++i)
41 std::string jointName = rns->getNode(i)->getName();
42 jointNames.push_back(jointName);
45 targets.push_back(ct->
asA<ControlTarget1DoFActuatorTorque>());
46 const SensorValue1DoFActuatorVelocity* velocitySensor =
47 sv->
asA<SensorValue1DoFActuatorVelocity>();
48 const SensorValue1DoFActuatorPosition* positionSensor =
49 sv->
asA<SensorValue1DoFActuatorPosition>();
60 velocitySensors.push_back(velocitySensor);
61 positionSensors.push_back(positionSensor);
64 robotUnit->getSensorDevice(cfg->forceSensorName)->getSensorValue();
68 forceOffset.setZero();
69 filteredForce.setZero();
70 filteredForceInRoot.setZero();
74 ik.reset(
new VirtualRobot::DifferentialIK(
75 rns,
rtGetRobot()->getRootNode(), VirtualRobot::JacobiProvider::eSVDDamped));
76 ik->setDampedSvdLambda(0.0001);
79 numOfJoints = targets.size();
84 taskSpaceDMPConfig.
DMPMode = cfg->dmpMode;
85 taskSpaceDMPConfig.
DMPStyle = cfg->dmpType;
101 useNullSpaceJointDMP = cfg->useNullSpaceJointDMP;
102 nullSpaceJointDMPPtr.reset(
new DMP::UMIDMP(100));
104 isNullSpaceJointDMPLearned =
false;
106 Eigen::VectorXf nullspaceValues(targets.size());
110 for (
size_t i = 0; i < targets.size(); ++i)
112 nullspaceValues(i) = cfg->defaultNullSpaceJointValues.at(i);
117 Eigen::Vector3f kpos(cfg->Kpos[0], cfg->Kpos[1], cfg->Kpos[2]);
118 Eigen::Vector3f dpos(cfg->Dpos[0], cfg->Dpos[1], cfg->Dpos[2]);
119 Eigen::Vector3f kori(cfg->Kori[0], cfg->Kori[1], cfg->Kori[2]);
120 Eigen::Vector3f dori(cfg->Dori[0], cfg->Dori[1], cfg->Dori[2]);
121 Eigen::VectorXf knull(targets.size());
122 Eigen::VectorXf dnull(targets.size());
127 for (
size_t i = 0; i < targets.size(); ++i)
129 knull(i) = cfg->Knull.at(i);
130 dnull(i) = cfg->Dnull.at(i);
133 CtrlParams initParams = {kpos, dpos, kori, dori, knull, dnull};
136 torqueLimit = cfg->torqueLimit;
137 timeDuration = cfg->timeDuration;
139 NJointTaskSpaceImpedanceDMPControllerInterfaceData initInterfaceData;
143 NJointTaskSpaceImpedanceDMPControllerSensorData initControllerSensorData;
145 initControllerSensorData.currentTime = 0;
146 initControllerSensorData.deltaT = 0;
147 initControllerSensorData.currentTwist.setZero();
151 useForceStop =
false;
159 return "NJointTaskSpaceImpedanceDMPController";
167 initData.
targetPose = tcp->getPoseInRootFrame();
188 double deltaT = 0.001;
190 Eigen::VectorXf currentTwist = controllerSensorData.
getReadBuffer().currentTwist;
219 if (dmpCtrl->canVal < 1e-8)
228 dmpCtrl->flow(deltaT, currentPose, currentTwist);
230 Eigen::VectorXf desiredNullSpaceJointValues(jointNames.size());
231 if (useNullSpaceJointDMP && isNullSpaceJointDMPLearned)
234 currentJointState = nullSpaceJointDMPPtr->calculateDirectlyVelocity(
236 dmpCtrl->canVal / timeDuration,
237 deltaT / timeDuration,
240 if (targetJointState.size() == jointNames.size())
242 for (
size_t i = 0; i < targetJointState.size(); ++i)
244 desiredNullSpaceJointValues(i) = targetJointState[i];
249 desiredNullSpaceJointValues =
255 desiredNullSpaceJointValues =
278 double deltaT = timeSinceLastIteration.toSecondsDouble();
280 Eigen::VectorXf targetVel;
281 Eigen::VectorXf desiredNullSpaceJointValues;
285 targetPose = currentPose;
286 stopPose = currentPose;
287 targetVel.setZero(6);
294 targetPose = stopPose;
295 targetVel.setZero(6);
298 (1 - cfg->forceFilter) * forceOffset + cfg->forceFilter * forceSensor->
force;
299 timeForCalibration = timeForCalibration + timeSinceLastIteration.toSecondsDouble();
310 filteredForce = (1 - cfg->forceFilter) * filteredForce +
311 cfg->forceFilter * (forceSensor->
force - forceOffset);
313 for (
size_t i = 0; i < 3; ++i)
315 if (fabs(filteredForce(i)) > cfg->forceDeadZone)
318 (filteredForce(i) / fabs(filteredForce(i))) * cfg->forceDeadZone;
322 filteredForce(i) = 0;
326 rtGetRobot()->getRobotNode(cfg->forceFrameName)->getPoseInRootFrame();
327 filteredForceInRoot = forceFrameInRoot.block<3, 3>(0, 0) * filteredForce;
329 for (
size_t i = 0; i < 3; ++i)
331 if (fabs(filteredForceInRoot[i]) >
334 stopPose = currentPose;
335 targetVel.setZero(6);
336 desiredNullSpaceJointValues =
347 Eigen::MatrixXf jacobi =
348 ik->getJacobianMatrix(tcp, VirtualRobot::IKSolver::CartesianSelection::All);
350 Eigen::VectorXf qpos(positionSensors.size());
351 Eigen::VectorXf qvel(velocitySensors.size());
352 for (
size_t i = 0; i < positionSensors.size(); ++i)
354 qpos(i) = positionSensors[i]->position;
355 qvel(i) = velocitySensors[i]->velocity;
358 Eigen::VectorXf currentTwist = jacobi * qvel;
361 controllerSensorData.
getWriteBuffer().currentTwist = currentTwist;
369 jacobi.block(0, 0, 3, numOfJoints) =
370 0.001 * jacobi.block(0, 0, 3, numOfJoints);
381 Eigen::Vector3f targetTCPLinearVelocity;
382 targetTCPLinearVelocity << 0.001 * targetVel(0), 0.001 * targetVel(1),
383 0.001 * targetVel(2);
384 Eigen::Vector3f currentTCPLinearVelocity;
385 currentTCPLinearVelocity << 0.001 * currentTwist(0), 0.001 * currentTwist(1),
386 0.001 * currentTwist(2);
387 Eigen::Vector3f currentTCPPosition = currentPose.block<3, 1>(0, 3);
388 Eigen::Vector3f desiredPosition = targetPose.block<3, 1>(0, 3);
389 Eigen::Vector3f tcpDesiredForce =
390 0.001 * kpos.cwiseProduct(desiredPosition - currentTCPPosition) +
391 dpos.cwiseProduct(targetTCPLinearVelocity - currentTCPLinearVelocity);
393 Eigen::Vector3f currentTCPAngularVelocity;
394 currentTCPAngularVelocity << currentTwist(3), currentTwist(4), currentTwist(5);
396 Eigen::Matrix3f diffMat = targetPose.block<3, 3>(0, 0) * currentRotMat.inverse();
397 Eigen::Vector3f rpy = VirtualRobot::MathTools::eigen3f2rpy(diffMat);
398 Eigen::Vector3f tcpDesiredTorque =
399 kori.cwiseProduct(rpy) - dori.cwiseProduct(currentTCPAngularVelocity);
400 jointControlWrench << tcpDesiredForce, tcpDesiredTorque;
405 Eigen::VectorXf nullspaceTorque =
406 knull.cwiseProduct(desiredNullSpaceJointValues - qpos) - dnull.cwiseProduct(qvel);
407 Eigen::MatrixXf jtpinv = ik->computePseudoInverseJacobianMatrix(jacobi.transpose(), 2.0);
408 Eigen::VectorXf jointDesiredTorques = jacobi.transpose() * jointControlWrench +
409 (I - jacobi.transpose() * jtpinv) * nullspaceTorque;
415 for (
size_t i = 0; i < targets.size(); ++i)
417 float desiredTorque = jointDesiredTorques(i);
419 if (isnan(desiredTorque))
424 desiredTorque = (desiredTorque > torqueLimit) ? torqueLimit : desiredTorque;
425 desiredTorque = (desiredTorque < -torqueLimit) ? -torqueLimit : desiredTorque;
428 jointDesiredTorques(i);
429 debugOutputData.
getWriteBuffer().desired_nullspaceJoint[jointNames[i]] =
430 desiredNullSpaceJointValues(i);
432 targets.at(i)->torque = desiredTorque;
433 if (!targets.at(i)->isValid())
436 <<
"Torque controller target is invalid - setting to zero! set value: "
437 << targets.at(i)->torque;
438 targets.at(i)->torque = 0.0f;
443 debugOutputData.
getWriteBuffer().forceDesired_x = jointControlWrench(0);
444 debugOutputData.
getWriteBuffer().forceDesired_y = jointControlWrench(1);
445 debugOutputData.
getWriteBuffer().forceDesired_z = jointControlWrench(2);
446 debugOutputData.
getWriteBuffer().forceDesired_rx = jointControlWrench(3);
447 debugOutputData.
getWriteBuffer().forceDesired_ry = jointControlWrench(4);
448 debugOutputData.
getWriteBuffer().forceDesired_rz = jointControlWrench(5);
457 VirtualRobot::MathTools::eigen4f2quat(targetPose);
464 debugOutputData.
getWriteBuffer().currentPose_x = currentPose(0, 3);
465 debugOutputData.
getWriteBuffer().currentPose_y = currentPose(1, 3);
466 debugOutputData.
getWriteBuffer().currentPose_z = currentPose(2, 3);
468 VirtualRobot::MathTools::eigen4f2quat(currentPose);
502 dmpCtrl->learnDMPFromFiles(fileNames);
508 const Ice::DoubleSeq& viapoint,
513 dmpCtrl->setViaPose(u, viapoint);
518 const Ice::Current& ice)
520 dmpCtrl->setGoalPoseVec(goals);
525 const Ice::FloatSeq& currentJVS,
528 DMP::Vec<DMP::SampledTrajectoryV2> trajs;
530 DMP::SampledTrajectoryV2 traj;
531 traj.readFromCSVFile(fileName);
533 if (traj.dim() != jointNames.size())
535 isNullSpaceJointDMPLearned =
false;
540 goal.resize(traj.dim());
541 currentJointState.resize(traj.dim());
543 for (
size_t i = 0; i < goal.size(); ++i)
545 goal.at(i) = traj.rbegin()->getPosition(i);
546 currentJointState.at(i).pos = currentJVS.at(i);
547 currentJointState.at(i).vel = 0;
550 trajs.push_back(traj);
551 nullSpaceJointDMPPtr->learnFromTrajectories(trajs);
554 nullSpaceJointDMPPtr->prepareExecution(goal, currentJointState, 1.0, 1.0);
556 isNullSpaceJointDMPLearned =
true;
574 prematurely_stopped =
true;
586 useNullSpaceJointDMP = enable;
594 dmpCtrl->canVal = timeDuration;
595 dmpCtrl->config.motionTimeDuration = timeDuration;
604 prematurely_stopped =
false;
605 timeForCalibration = 0;
608 while (firstRun || timeForCalibration < cfg->waitTimeForCalibration)
610 if (prematurely_stopped.load())
612 ARMARX_WARNING <<
"StopDMP has been prematurely called; aborting runDMP";
624 dmpCtrl->prepareExecution(dmpCtrl->eigen4f2vec(pose), goals);
628 if (isNullSpaceJointDMPLearned && useNullSpaceJointDMP)
633 if (prematurely_stopped.load())
635 ARMARX_WARNING <<
"StopDMP has been prematurely called; aborting runDMP";
653 datafields[
"torqueDesired_" + pair.first] =
new Variant(pair.second);
657 for (
auto& pair : values_null)
659 datafields[
"nullspaceDesired_" + pair.first] =
new Variant(pair.second);
664 datafields[
"targetPose_x"] =
666 datafields[
"targetPose_y"] =
668 datafields[
"targetPose_z"] =
670 datafields[
"targetPose_qw"] =
672 datafields[
"targetPose_qx"] =
674 datafields[
"targetPose_qy"] =
676 datafields[
"targetPose_qz"] =
679 datafields[
"currentPose_x"] =
681 datafields[
"currentPose_y"] =
683 datafields[
"currentPose_z"] =
685 datafields[
"currentPose_qw"] =
687 datafields[
"currentPose_qx"] =
689 datafields[
"currentPose_qy"] =
691 datafields[
"currentPose_qz"] =
694 datafields[
"currentKpos_x"] =
696 datafields[
"currentKpos_y"] =
698 datafields[
"currentKpos_z"] =
700 datafields[
"currentKori_x"] =
702 datafields[
"currentKori_y"] =
704 datafields[
"currentKori_z"] =
706 datafields[
"currentKnull_x"] =
708 datafields[
"currentKnull_y"] =
710 datafields[
"currentKnull_z"] =
713 datafields[
"currentDpos_x"] =
715 datafields[
"currentDpos_y"] =
717 datafields[
"currentDpos_z"] =
719 datafields[
"currentDori_x"] =
721 datafields[
"currentDori_y"] =
723 datafields[
"currentDori_z"] =
725 datafields[
"currentDnull_x"] =
727 datafields[
"currentDnull_y"] =
729 datafields[
"currentDnull_z"] =
732 datafields[
"forceDesired_x"] =
734 datafields[
"forceDesired_y"] =
736 datafields[
"forceDesired_z"] =
738 datafields[
"forceDesired_rx"] =
740 datafields[
"forceDesired_ry"] =
742 datafields[
"forceDesired_rz"] =
747 std::string channelName = cfg->nodeSetName +
"_TaskSpaceImpedanceControl";
748 debugObs->setDebugChannel(channelName, datafields);
756 runTask(
"NJointTaskSpaceImpedanceDMPController",
761 while (
getState() == eManagedIceObjectStarted)
767 c.waitForCycleDuration();
782 dmpCtrl->setWeights(weights);
788 DMP::DVec2d res = dmpCtrl->getWeights();
790 for (
size_t i = 0; i < res.size(); ++i)
792 std::vector<double> cvec;
793 for (
size_t j = 0; j < res[i].size(); ++j)
795 cvec.push_back(res[i][j]);
797 resvec.push_back(cvec);
808 dmpCtrl->removeAllViaPoints();
879 const Eigen::VectorXf& jointValues,
890 return dmpCtrl->canVal;