3 #include <VirtualRobot/IK/DifferentialIK.h>
4 #include <VirtualRobot/MathTools.h>
5 #include <VirtualRobot/Nodes/RobotNode.h>
6 #include <VirtualRobot/Robot.h>
7 #include <VirtualRobot/RobotNodeSet.h>
20 #include <dmp/representation/dmp/umidmp.h>
24 NJointControllerRegistration<NJointTaskSpaceAdaptiveDMPController>
26 "NJointTaskSpaceAdaptiveDMPController");
30 const armarx::NJointControllerConfigPtr& config,
34 cfg = NJointTaskSpaceAdaptiveDMPControllerConfigPtr::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);
66 robotUnit->getSensorDevice(cfg->forceSensorName)->getSensorValue();
70 ik.reset(
new VirtualRobot::DifferentialIK(
71 rns,
rtGetRobot()->getRootNode(), VirtualRobot::JacobiProvider::eSVDDamped));
72 numOfJoints = targets.size();
76 double phaseDist0 = 10000;
77 double phaseDist1 = 10000;
78 double posToOriRatio = 10;
83 taskSpaceDMPConfig.
DMPMode = cfg->dmpMode;
84 taskSpaceDMPConfig.
DMPStyle = cfg->dmpType;
100 useNullSpaceJointDMP = cfg->useNullSpaceJointDMP;
101 nullSpaceJointDMPPtr.reset(
new DMP::UMIDMP(100));
103 isNullSpaceJointDMPLearned =
false;
105 defaultNullSpaceJointValues.resize(targets.size());
108 for (
size_t i = 0; i < targets.size(); ++i)
110 defaultNullSpaceJointValues(i) = cfg->defaultNullSpaceJointValues.at(i);
114 kpos << cfg->Kpos[0], cfg->Kpos[1], cfg->Kpos[2];
115 dpos << cfg->Dpos[0], cfg->Dpos[1], cfg->Dpos[2];
116 kori << cfg->Kori[0], cfg->Kori[1], cfg->Kori[2];
117 dori << cfg->Dori[0], cfg->Dori[1], cfg->Dori[2];
123 knull.setZero(targets.size());
124 dnull.setZero(targets.size());
126 for (
size_t i = 0; i < targets.size(); ++i)
128 knull(i) = cfg->Knull.at(i);
129 dnull(i) = cfg->Dnull.at(i);
132 torqueLimit = cfg->torqueLimit;
133 timeDuration = cfg->timeDuration;
135 NJointTaskSpaceAdaptiveDMPControllerInterfaceData initInterfaceData;
137 initInterfaceData.currentForce = Eigen::Vector3f::Zero();
138 initInterfaceData.currentVel.setZero(6);
141 NJointTaskSpaceAdaptiveDMPControllerSensorData initControllerSensorData;
143 initControllerSensorData.currentTime = 0;
144 initControllerSensorData.deltaT = 0;
145 initControllerSensorData.currentTwist.setZero();
149 Eigen::VectorXf KpImpedance;
150 KpImpedance.setZero(6);
152 for (
int i = 0; i < 3; ++i)
154 KpImpedance(i) = cfg->Kpos.at(i);
155 KpImpedance(i + 3) = cfg->Kori.at(i);
158 Eigen::VectorXf KdImpedance;
159 KdImpedance.setZero(6);
161 for (
int i = 0; i < 3; ++i)
163 KdImpedance(i) = cfg->Dpos.at(i);
164 KdImpedance(i + 3) = cfg->Dori.at(i);
167 Inferface2rtData initInt2rtData;
168 initInt2rtData.KpImpedance = KpImpedance;
169 initInt2rtData.KdImpedance = KdImpedance;
170 initInt2rtData.Knull = knull;
171 initInt2rtData.Dnull = dnull;
175 Interface2CtrlData initInt2CtrlData;
176 initInt2CtrlData.canVal = 1.0;
180 forceOffset.setZero(3);
181 filteredForce.setZero(3);
189 return "NJointTaskSpaceAdaptiveDMPController";
196 initData.
targetPose = tcp->getPoseInRootFrame();
219 double deltaT = 0.001;
221 Eigen::VectorXf currentTwist = controllerSensorData.
getReadBuffer().currentTwist;
253 if (dmpCtrl->canVal < 1e-8)
262 dmpCtrl->flow(deltaT, currentPose, currentTwist);
264 Eigen::VectorXf desiredNullSpaceJointValues(jointNames.size());
265 if (useNullSpaceJointDMP && isNullSpaceJointDMPLearned)
268 currentJointState = nullSpaceJointDMPPtr->calculateDirectlyVelocity(
270 dmpCtrl->canVal / timeDuration,
271 deltaT / timeDuration,
274 if (targetJointState.size() == jointNames.size())
276 for (
size_t i = 0; i < targetJointState.size(); ++i)
278 desiredNullSpaceJointValues(i) = targetJointState[i];
283 desiredNullSpaceJointValues = defaultNullSpaceJointValues;
288 desiredNullSpaceJointValues = defaultNullSpaceJointValues;
307 double deltaT = timeSinceLastIteration.toSecondsDouble();
310 Eigen::MatrixXf jacobi =
311 ik->getJacobianMatrix(tcp, VirtualRobot::IKSolver::CartesianSelection::All);
313 Eigen::VectorXf qpos(positionSensors.size());
314 Eigen::VectorXf qvel(velocitySensors.size());
315 for (
size_t i = 0; i < positionSensors.size(); ++i)
317 qpos(i) = positionSensors[i]->position;
318 qvel(i) = velocitySensors[i]->velocity;
321 Eigen::VectorXf currentTwist = jacobi * qvel;
324 controllerSensorData.
getWriteBuffer().currentTwist = currentTwist;
331 Eigen::VectorXf targetVel;
332 Eigen::VectorXf desiredNullSpaceJointValues;
333 if (firstRun || !started)
336 targetPose = currentPose;
337 targetVel.setZero(6);
338 desiredNullSpaceJointValues = defaultNullSpaceJointValues;
339 forceOffset = 0.1 * forceOffset + 0.9 * forceSensor->
force;
343 filteredForce = (1 - cfg->filterCoeff) * filteredForce +
344 cfg->filterCoeff * (forceSensor->
force - forceOffset);
364 jacobi.block(0, 0, 3, numOfJoints) =
365 0.001 * jacobi.block(0, 0, 3, numOfJoints);
368 Eigen::Vector3f targetTCPLinearVelocity;
369 targetTCPLinearVelocity << 0.001 * targetVel(0), 0.001 * targetVel(1),
370 0.001 * targetVel(2);
371 Eigen::Vector3f currentTCPLinearVelocity;
372 currentTCPLinearVelocity << 0.001 * currentTwist(0), 0.001 * currentTwist(1),
373 0.001 * currentTwist(2);
374 Eigen::Vector3f currentTCPPosition = currentPose.block<3, 1>(0, 3);
375 Eigen::Vector3f desiredPosition = targetPose.block<3, 1>(0, 3);
376 Eigen::Vector3f tcpDesiredForce =
377 0.001 * kpos.cwiseProduct(desiredPosition - currentTCPPosition) +
378 dpos.cwiseProduct(targetTCPLinearVelocity - currentTCPLinearVelocity);
380 Eigen::Vector3f currentTCPAngularVelocity;
381 currentTCPAngularVelocity << currentTwist(3), currentTwist(4), currentTwist(5);
383 Eigen::Matrix3f diffMat = targetPose.block<3, 3>(0, 0) * currentRotMat.inverse();
384 Eigen::Vector3f rpy = VirtualRobot::MathTools::eigen3f2rpy(diffMat);
385 Eigen::Vector3f tcpDesiredTorque =
386 kori.cwiseProduct(rpy) - dori.cwiseProduct(currentTCPAngularVelocity);
387 jointControlWrench << tcpDesiredForce, tcpDesiredTorque;
392 Eigen::VectorXf nullspaceTorque =
393 knull.cwiseProduct(desiredNullSpaceJointValues - qpos) - dnull.cwiseProduct(qvel);
394 Eigen::MatrixXf jtpinv = ik->computePseudoInverseJacobianMatrix(jacobi.transpose(), 2.0);
395 Eigen::VectorXf jointDesiredTorques = jacobi.transpose() * jointControlWrench +
396 (I - jacobi.transpose() * jtpinv) * nullspaceTorque;
401 for (
size_t i = 0; i < targets.size(); ++i)
403 float desiredTorque = jointDesiredTorques(i);
405 if (isnan(desiredTorque))
410 desiredTorque = (desiredTorque > torqueLimit) ? torqueLimit : desiredTorque;
411 desiredTorque = (desiredTorque < -torqueLimit) ? -torqueLimit : desiredTorque;
414 jointDesiredTorques(i);
415 debugOutputData.
getWriteBuffer().desired_nullspaceJoint[jointNames[i]] =
416 desiredNullSpaceJointValues(i);
418 targets.at(i)->torque = desiredTorque;
419 if (!targets.at(i)->isValid())
422 <<
"Torque controller target is invalid - setting to zero! set value: "
423 << targets.at(i)->torque;
424 targets.at(i)->torque = 0.0f;
429 debugOutputData.
getWriteBuffer().forceDesired_x = jointControlWrench(0);
430 debugOutputData.
getWriteBuffer().forceDesired_y = jointControlWrench(1);
431 debugOutputData.
getWriteBuffer().forceDesired_z = jointControlWrench(2);
432 debugOutputData.
getWriteBuffer().forceDesired_rx = jointControlWrench(3);
433 debugOutputData.
getWriteBuffer().forceDesired_ry = jointControlWrench(4);
434 debugOutputData.
getWriteBuffer().forceDesired_rz = jointControlWrench(5);
443 debugOutputData.
getWriteBuffer().forceInRoot_x = filteredForce(0);
444 debugOutputData.
getWriteBuffer().forceInRoot_y = filteredForce(1);
445 debugOutputData.
getWriteBuffer().forceInRoot_z = filteredForce(2);
461 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);
485 dmpCtrl->learnDMPFromFiles(fileNames);
491 const Ice::DoubleSeq& viapoint,
496 dmpCtrl->setViaPose(u, viapoint);
501 const Ice::Current& ice)
503 dmpCtrl->setGoalPoseVec(goals);
518 useNullSpaceJointDMP = useJointDMP;
523 const Ice::FloatSeq& desiredJointVals,
528 for (
size_t i = 0; i < targets.size(); ++i)
530 defaultNullSpaceJointValues(i) = desiredJointVals.at(i);
536 const Ice::FloatSeq& currentJVS,
539 DMP::Vec<DMP::SampledTrajectoryV2> trajs;
541 DMP::SampledTrajectoryV2 traj;
542 traj.readFromCSVFile(fileName);
544 if (traj.dim() != jointNames.size())
546 isNullSpaceJointDMPLearned =
false;
551 goal.resize(traj.dim());
552 currentJointState.resize(traj.dim());
554 for (
size_t i = 0; i < goal.size(); ++i)
556 goal.at(i) = traj.rbegin()->getPosition(i);
557 currentJointState.at(i).pos = currentJVS.at(i);
558 currentJointState.at(i).vel = 0;
561 trajs.push_back(traj);
562 nullSpaceJointDMPPtr->learnFromTrajectories(trajs);
565 nullSpaceJointDMPPtr->prepareExecution(goal, currentJointState, 1.0, 1.0);
567 isNullSpaceJointDMPLearned =
true;
584 Eigen::VectorXf setpoint;
585 setpoint.setZero(
value.size());
588 for (
size_t i = 0; i <
value.size(); ++i)
590 setpoint(i) =
value.at(i);
602 Eigen::VectorXf setpoint;
603 setpoint.setZero(
value.size());
606 for (
size_t i = 0; i <
value.size(); ++i)
608 setpoint(i) =
value.at(i);
619 Eigen::VectorXf setpoint;
620 setpoint.setZero(
value.size());
623 for (
size_t i = 0; i <
value.size(); ++i)
625 setpoint(i) =
value.at(i);
636 Eigen::VectorXf setpoint;
637 setpoint.setZero(
value.size());
640 for (
size_t i = 0; i <
value.size(); ++i)
642 setpoint(i) =
value.at(i);
654 std::vector<float> forceVec = {force(0), force(1), force(2)};
662 std::vector<float> tvelvec = {currentVel(0),
688 dmpCtrl->removeAllViaPoints();
703 dmpCtrl->prepareExecution(dmpCtrl->eigen4f2vec(pose), goals);
705 dmpCtrl->canVal = timeDuration;
706 dmpCtrl->config.motionTimeDuration = timeDuration;
710 if (isNullSpaceJointDMPLearned && useNullSpaceJointDMP)
730 dmpCtrl->prepareExecution(dmpCtrl->eigen4f2vec(pose), goals);
734 if (isNullSpaceJointDMPLearned && useNullSpaceJointDMP)
753 datafields[
"torqueDesired_" + pair.first] =
new Variant(pair.second);
757 for (
auto& pair : values_null)
759 datafields[
"nullspaceDesired_" + pair.first] =
new Variant(pair.second);
764 datafields[
"targetPose_x"] =
766 datafields[
"targetPose_y"] =
768 datafields[
"targetPose_z"] =
770 datafields[
"targetPose_qw"] =
772 datafields[
"targetPose_qx"] =
774 datafields[
"targetPose_qy"] =
776 datafields[
"targetPose_qz"] =
779 datafields[
"impedanceKp_x"] =
781 datafields[
"impedanceKp_y"] =
783 datafields[
"impedanceKp_z"] =
785 datafields[
"impedanceKp_rx"] =
787 datafields[
"impedanceKp_ry"] =
789 datafields[
"impedanceKp_rz"] =
792 datafields[
"currentPose_x"] =
794 datafields[
"currentPose_y"] =
796 datafields[
"currentPose_z"] =
798 datafields[
"currentPose_qw"] =
800 datafields[
"currentPose_qx"] =
802 datafields[
"currentPose_qy"] =
804 datafields[
"currentPose_qz"] =
807 datafields[
"forceDesired_x"] =
809 datafields[
"forceDesired_y"] =
811 datafields[
"forceDesired_z"] =
813 datafields[
"forceDesired_rx"] =
815 datafields[
"forceDesired_ry"] =
817 datafields[
"forceDesired_rz"] =
820 datafields[
"forceInRoot_x"] =
822 datafields[
"forceInRoot_y"] =
824 datafields[
"forceInRoot_z"] =
833 std::string channelName = cfg->nodeSetName +
"_TaskSpaceImpedanceControl";
834 debugObs->setDebugChannel(channelName, datafields);
842 runTask(
"NJointTaskSpaceAdaptiveDMPController",
847 while (
getState() == eManagedIceObjectStarted)
853 c.waitForCycleDuration();