7 NJointControllerRegistration<NJointTaskSpaceAdaptiveDMPController>
9 "NJointTaskSpaceAdaptiveDMPController");
12 const RobotUnitPtr& robotUnit,
13 const armarx::NJointControllerConfigPtr& config,
17 cfg = NJointTaskSpaceAdaptiveDMPControllerConfigPtr::dynamicCast(config);
19 rns =
rtGetRobot()->getRobotNodeSet(cfg->nodeSetName);
22 for (
size_t i = 0; i < rns->getSize(); ++i)
24 std::string jointName = rns->getNode(i)->getName();
25 jointNames.push_back(jointName);
28 targets.push_back(ct->
asA<ControlTarget1DoFActuatorTorque>());
29 const SensorValue1DoFActuatorVelocity* velocitySensor =
30 sv->
asA<SensorValue1DoFActuatorVelocity>();
31 const SensorValue1DoFActuatorPosition* positionSensor =
32 sv->
asA<SensorValue1DoFActuatorPosition>();
43 velocitySensors.push_back(velocitySensor);
44 positionSensors.push_back(positionSensor);
49 robotUnit->getSensorDevice(cfg->forceSensorName)->getSensorValue();
53 ik.reset(
new VirtualRobot::DifferentialIK(
54 rns,
rtGetRobot()->getRootNode(), VirtualRobot::JacobiProvider::eSVDDamped));
55 numOfJoints = targets.size();
59 double phaseDist0 = 10000;
60 double phaseDist1 = 10000;
61 double posToOriRatio = 10;
66 taskSpaceDMPConfig.
DMPMode = cfg->dmpMode;
67 taskSpaceDMPConfig.
DMPStyle = cfg->dmpType;
82 useNullSpaceJointDMP = cfg->useNullSpaceJointDMP;
83 nullSpaceJointDMPPtr.reset(
new DMP::UMIDMP(100));
85 isNullSpaceJointDMPLearned =
false;
87 defaultNullSpaceJointValues.resize(targets.size());
90 for (
size_t i = 0; i < targets.size(); ++i)
92 defaultNullSpaceJointValues(i) = cfg->defaultNullSpaceJointValues.at(i);
96 kpos << cfg->Kpos[0], cfg->Kpos[1], cfg->Kpos[2];
97 dpos << cfg->Dpos[0], cfg->Dpos[1], cfg->Dpos[2];
98 kori << cfg->Kori[0], cfg->Kori[1], cfg->Kori[2];
99 dori << cfg->Dori[0], cfg->Dori[1], cfg->Dori[2];
105 knull.setZero(targets.size());
106 dnull.setZero(targets.size());
108 for (
size_t i = 0; i < targets.size(); ++i)
110 knull(i) = cfg->Knull.at(i);
111 dnull(i) = cfg->Dnull.at(i);
114 torqueLimit = cfg->torqueLimit;
115 timeDuration = cfg->timeDuration;
117 NJointTaskSpaceAdaptiveDMPControllerInterfaceData initInterfaceData;
119 initInterfaceData.currentForce = Eigen::Vector3f::Zero();
120 initInterfaceData.currentVel.setZero(6);
123 NJointTaskSpaceAdaptiveDMPControllerSensorData initControllerSensorData;
125 initControllerSensorData.currentTime = 0;
126 initControllerSensorData.deltaT = 0;
127 initControllerSensorData.currentTwist.setZero();
131 Eigen::VectorXf KpImpedance;
132 KpImpedance.setZero(6);
134 for (
int i = 0; i < 3; ++i)
136 KpImpedance(i) = cfg->Kpos.at(i);
137 KpImpedance(i + 3) = cfg->Kori.at(i);
140 Eigen::VectorXf KdImpedance;
141 KdImpedance.setZero(6);
143 for (
int i = 0; i < 3; ++i)
145 KdImpedance(i) = cfg->Dpos.at(i);
146 KdImpedance(i + 3) = cfg->Dori.at(i);
149 Inferface2rtData initInt2rtData;
150 initInt2rtData.KpImpedance = KpImpedance;
151 initInt2rtData.KdImpedance = KdImpedance;
152 initInt2rtData.Knull = knull;
153 initInt2rtData.Dnull = dnull;
157 Interface2CtrlData initInt2CtrlData;
158 initInt2CtrlData.canVal = 1.0;
162 forceOffset.setZero(3);
163 filteredForce.setZero(3);
171 return "NJointTaskSpaceAdaptiveDMPController";
179 initData.
targetPose = tcp->getPoseInRootFrame();
203 double deltaT = 0.001;
205 Eigen::VectorXf currentTwist = controllerSensorData.
getReadBuffer().currentTwist;
237 if (dmpCtrl->canVal < 1e-8)
246 dmpCtrl->flow(deltaT, currentPose, currentTwist);
248 Eigen::VectorXf desiredNullSpaceJointValues(jointNames.size());
249 if (useNullSpaceJointDMP && isNullSpaceJointDMPLearned)
252 currentJointState = nullSpaceJointDMPPtr->calculateDirectlyVelocity(
254 dmpCtrl->canVal / timeDuration,
255 deltaT / timeDuration,
258 if (targetJointState.size() == jointNames.size())
260 for (
size_t i = 0; i < targetJointState.size(); ++i)
262 desiredNullSpaceJointValues(i) = targetJointState[i];
267 desiredNullSpaceJointValues = defaultNullSpaceJointValues;
272 desiredNullSpaceJointValues = defaultNullSpaceJointValues;
291 double deltaT = timeSinceLastIteration.toSecondsDouble();
294 Eigen::MatrixXf jacobi =
295 ik->getJacobianMatrix(tcp, VirtualRobot::IKSolver::CartesianSelection::All);
297 Eigen::VectorXf qpos(positionSensors.size());
298 Eigen::VectorXf qvel(velocitySensors.size());
299 for (
size_t i = 0; i < positionSensors.size(); ++i)
301 qpos(i) = positionSensors[i]->position;
302 qvel(i) = velocitySensors[i]->velocity;
305 Eigen::VectorXf currentTwist = jacobi * qvel;
308 controllerSensorData.
getWriteBuffer().currentTwist = currentTwist;
315 Eigen::VectorXf targetVel;
316 Eigen::VectorXf desiredNullSpaceJointValues;
317 if (firstRun || !started)
320 targetPose = currentPose;
321 targetVel.setZero(6);
322 desiredNullSpaceJointValues = defaultNullSpaceJointValues;
323 forceOffset = 0.1 * forceOffset + 0.9 * forceSensor->
force;
327 filteredForce = (1 - cfg->filterCoeff) * filteredForce +
328 cfg->filterCoeff * (forceSensor->
force - forceOffset);
348 jacobi.block(0, 0, 3, numOfJoints) =
349 0.001 * jacobi.block(0, 0, 3, numOfJoints);
352 Eigen::Vector3f targetTCPLinearVelocity;
353 targetTCPLinearVelocity << 0.001 * targetVel(0), 0.001 * targetVel(1),
354 0.001 * targetVel(2);
355 Eigen::Vector3f currentTCPLinearVelocity;
356 currentTCPLinearVelocity << 0.001 * currentTwist(0), 0.001 * currentTwist(1),
357 0.001 * currentTwist(2);
358 Eigen::Vector3f currentTCPPosition = currentPose.block<3, 1>(0, 3);
359 Eigen::Vector3f desiredPosition = targetPose.block<3, 1>(0, 3);
360 Eigen::Vector3f tcpDesiredForce =
361 0.001 * kpos.cwiseProduct(desiredPosition - currentTCPPosition) +
362 dpos.cwiseProduct(targetTCPLinearVelocity - currentTCPLinearVelocity);
364 Eigen::Vector3f currentTCPAngularVelocity;
365 currentTCPAngularVelocity << currentTwist(3), currentTwist(4), currentTwist(5);
367 Eigen::Matrix3f diffMat = targetPose.block<3, 3>(0, 0) * currentRotMat.inverse();
368 Eigen::Vector3f rpy = VirtualRobot::MathTools::eigen3f2rpy(diffMat);
369 Eigen::Vector3f tcpDesiredTorque =
370 kori.cwiseProduct(rpy) - dori.cwiseProduct(currentTCPAngularVelocity);
371 jointControlWrench << tcpDesiredForce, tcpDesiredTorque;
376 Eigen::VectorXf nullspaceTorque =
377 knull.cwiseProduct(desiredNullSpaceJointValues - qpos) - dnull.cwiseProduct(qvel);
378 Eigen::MatrixXf jtpinv = ik->computePseudoInverseJacobianMatrix(jacobi.transpose(), 2.0);
379 Eigen::VectorXf jointDesiredTorques = jacobi.transpose() * jointControlWrench +
380 (I - jacobi.transpose() * jtpinv) * nullspaceTorque;
385 for (
size_t i = 0; i < targets.size(); ++i)
387 float desiredTorque = jointDesiredTorques(i);
389 if (isnan(desiredTorque))
394 desiredTorque = (desiredTorque > torqueLimit) ? torqueLimit : desiredTorque;
395 desiredTorque = (desiredTorque < -torqueLimit) ? -torqueLimit : desiredTorque;
398 jointDesiredTorques(i);
399 debugOutputData.
getWriteBuffer().desired_nullspaceJoint[jointNames[i]] =
400 desiredNullSpaceJointValues(i);
402 targets.at(i)->torque = desiredTorque;
403 if (!targets.at(i)->isValid())
406 <<
"Torque controller target is invalid - setting to zero! set value: "
407 << targets.at(i)->torque;
408 targets.at(i)->torque = 0.0f;
413 debugOutputData.
getWriteBuffer().forceDesired_x = jointControlWrench(0);
414 debugOutputData.
getWriteBuffer().forceDesired_y = jointControlWrench(1);
415 debugOutputData.
getWriteBuffer().forceDesired_z = jointControlWrench(2);
416 debugOutputData.
getWriteBuffer().forceDesired_rx = jointControlWrench(3);
417 debugOutputData.
getWriteBuffer().forceDesired_ry = jointControlWrench(4);
418 debugOutputData.
getWriteBuffer().forceDesired_rz = jointControlWrench(5);
427 debugOutputData.
getWriteBuffer().forceInRoot_x = filteredForce(0);
428 debugOutputData.
getWriteBuffer().forceInRoot_y = filteredForce(1);
429 debugOutputData.
getWriteBuffer().forceInRoot_z = filteredForce(2);
445 VirtualRobot::MathTools::eigen4f2quat(targetPose);
451 debugOutputData.
getWriteBuffer().currentPose_x = currentPose(0, 3);
452 debugOutputData.
getWriteBuffer().currentPose_y = currentPose(1, 3);
453 debugOutputData.
getWriteBuffer().currentPose_z = currentPose(2, 3);
455 VirtualRobot::MathTools::eigen4f2quat(currentPose);
470 dmpCtrl->learnDMPFromFiles(fileNames);
476 const Ice::DoubleSeq& viapoint,
481 dmpCtrl->setViaPose(u, viapoint);
486 const Ice::Current& ice)
488 dmpCtrl->setGoalPoseVec(goals);
503 useNullSpaceJointDMP = useJointDMP;
509 const Ice::FloatSeq& desiredJointVals,
514 for (
size_t i = 0; i < targets.size(); ++i)
516 defaultNullSpaceJointValues(i) = desiredJointVals.at(i);
522 const Ice::FloatSeq& currentJVS,
525 DMP::Vec<DMP::SampledTrajectoryV2> trajs;
527 DMP::SampledTrajectoryV2 traj;
528 traj.readFromCSVFile(fileName);
530 if (traj.dim() != jointNames.size())
532 isNullSpaceJointDMPLearned =
false;
537 goal.resize(traj.dim());
538 currentJointState.resize(traj.dim());
540 for (
size_t i = 0; i < goal.size(); ++i)
542 goal.at(i) = traj.rbegin()->getPosition(i);
543 currentJointState.at(i).pos = currentJVS.at(i);
544 currentJointState.at(i).vel = 0;
547 trajs.push_back(traj);
548 nullSpaceJointDMPPtr->learnFromTrajectories(trajs);
551 nullSpaceJointDMPPtr->prepareExecution(goal, currentJointState, 1.0, 1.0);
553 isNullSpaceJointDMPLearned =
true;
571 Eigen::VectorXf setpoint;
572 setpoint.setZero(
value.size());
575 for (
size_t i = 0; i <
value.size(); ++i)
577 setpoint(i) =
value.at(i);
589 Eigen::VectorXf setpoint;
590 setpoint.setZero(
value.size());
593 for (
size_t i = 0; i <
value.size(); ++i)
595 setpoint(i) =
value.at(i);
606 Eigen::VectorXf setpoint;
607 setpoint.setZero(
value.size());
610 for (
size_t i = 0; i <
value.size(); ++i)
612 setpoint(i) =
value.at(i);
623 Eigen::VectorXf setpoint;
624 setpoint.setZero(
value.size());
627 for (
size_t i = 0; i <
value.size(); ++i)
629 setpoint(i) =
value.at(i);
641 std::vector<float> forceVec = {force(0), force(1), force(2)};
649 std::vector<float> tvelvec = {currentVel(0),
676 dmpCtrl->removeAllViaPoints();
692 dmpCtrl->prepareExecution(dmpCtrl->eigen4f2vec(pose), goals);
694 dmpCtrl->canVal = timeDuration;
695 dmpCtrl->config.motionTimeDuration = timeDuration;
699 if (isNullSpaceJointDMPLearned && useNullSpaceJointDMP)
719 dmpCtrl->prepareExecution(dmpCtrl->eigen4f2vec(pose), goals);
723 if (isNullSpaceJointDMPLearned && useNullSpaceJointDMP)
743 datafields[
"torqueDesired_" + pair.first] =
new Variant(pair.second);
747 for (
auto& pair : values_null)
749 datafields[
"nullspaceDesired_" + pair.first] =
new Variant(pair.second);
754 datafields[
"targetPose_x"] =
756 datafields[
"targetPose_y"] =
758 datafields[
"targetPose_z"] =
760 datafields[
"targetPose_qw"] =
762 datafields[
"targetPose_qx"] =
764 datafields[
"targetPose_qy"] =
766 datafields[
"targetPose_qz"] =
769 datafields[
"impedanceKp_x"] =
771 datafields[
"impedanceKp_y"] =
773 datafields[
"impedanceKp_z"] =
775 datafields[
"impedanceKp_rx"] =
777 datafields[
"impedanceKp_ry"] =
779 datafields[
"impedanceKp_rz"] =
782 datafields[
"currentPose_x"] =
784 datafields[
"currentPose_y"] =
786 datafields[
"currentPose_z"] =
788 datafields[
"currentPose_qw"] =
790 datafields[
"currentPose_qx"] =
792 datafields[
"currentPose_qy"] =
794 datafields[
"currentPose_qz"] =
797 datafields[
"forceDesired_x"] =
799 datafields[
"forceDesired_y"] =
801 datafields[
"forceDesired_z"] =
803 datafields[
"forceDesired_rx"] =
805 datafields[
"forceDesired_ry"] =
807 datafields[
"forceDesired_rz"] =
810 datafields[
"forceInRoot_x"] =
812 datafields[
"forceInRoot_y"] =
814 datafields[
"forceInRoot_z"] =
823 std::string channelName = cfg->nodeSetName +
"_TaskSpaceImpedanceControl";
824 debugObs->setDebugChannel(channelName, datafields);
832 runTask(
"NJointTaskSpaceAdaptiveDMPController",
837 while (
getState() == eManagedIceObjectStarted)
843 c.waitForCycleDuration();