3 #include <VirtualRobot/IK/DifferentialIK.h>
4 #include <VirtualRobot/Manipulability/SingleChainManipulability.h>
5 #include <VirtualRobot/Manipulability/SingleChainManipulabilityTracking.h>
6 #include <VirtualRobot/MathTools.h>
7 #include <VirtualRobot/Nodes/RobotNode.h>
8 #include <VirtualRobot/Nodes/Sensor.h>
9 #include <VirtualRobot/Robot.h>
10 #include <VirtualRobot/RobotNodeSet.h>
24 NJointControllerRegistration<NJointPeriodicTSDMPCompliantController>
26 "NJointPeriodicTSDMPCompliantController");
30 const armarx::NJointControllerConfigPtr& config,
34 cfg = NJointPeriodicTSDMPCompliantControllerConfigPtr::dynamicCast(config);
36 VirtualRobot::RobotNodeSetPtr rns =
rtGetRobot()->getRobotNodeSet(cfg->nodeSetName);
39 for (
size_t i = 0; i < rns->getSize(); ++i)
41 std::string jointName = rns->getNode(i)->getName();
44 targets.push_back(ct->
asA<ControlTarget1DoFActuatorTorque>());
46 const SensorValue1DoFActuatorVelocity* velocitySensor =
47 sv->
asA<SensorValue1DoFActuatorVelocity>();
48 const SensorValue1DoFActuatorPosition* positionSensor =
49 sv->
asA<SensorValue1DoFActuatorPosition>();
51 velocitySensors.push_back(velocitySensor);
52 positionSensors.push_back(positionSensor);
57 nodeSetName = cfg->nodeSetName;
58 ik.reset(
new VirtualRobot::DifferentialIK(
59 rns, rns->getRobot()->getRootNode(), VirtualRobot::JacobiProvider::eSVDDamped));
65 taskSpaceDMPConfig.
DMPMode =
"Linear";
66 taskSpaceDMPConfig.
DMPStyle =
"Periodic";
82 for (
size_t i = 0; i < 6; ++i)
97 kpos << cfg->Kpos[0], cfg->Kpos[1], cfg->Kpos[2];
98 dpos << cfg->Dpos[0], cfg->Dpos[1], cfg->Dpos[2];
99 kori << cfg->Kori[0], cfg->Kori[1], cfg->Kori[2];
100 dori << cfg->Dori[0], cfg->Dori[1], cfg->Dori[2];
107 nullSpaceJointsVec.resize(cfg->desiredNullSpaceJointValues.size());
108 for (
size_t i = 0; i < cfg->desiredNullSpaceJointValues.size(); ++i)
110 nullSpaceJointsVec(i) = cfg->desiredNullSpaceJointValues.at(i);
115 robUnit->getSensorDevice(cfg->forceSensorName)->getSensorValue();
118 forceOffset.setZero();
119 filteredForce.setZero();
120 filteredForceInRoot.setZero();
123 UserToRTData initUserData;
124 initUserData.targetForce = 0;
127 oriToolDir << 0, 0, 1;
129 qvel_filtered.setZero(targets.size());
136 if (!cfg->ignoreWSLimitChecks)
156 isManipulability = cfg->isManipulability;
160 Eigen::VectorXd maniWeightVec;
161 maniWeightVec.setOnes(rns->getNodeNames().size());
162 for (
size_t i = 0; i < cfg->maniWeight.size(); ++i)
164 maniWeightVec(i) = cfg->maniWeight[i];
167 Eigen::MatrixXd maniWeightMat = maniWeightVec.asDiagonal();
168 VirtualRobot::SingleRobotNodeSetManipulabilityPtr manipulability(
169 new VirtualRobot::SingleRobotNodeSetManipulability(
173 VirtualRobot::AbstractManipulability::Type::Velocity,
174 rns->getRobot()->getRootNode(),
176 manipulabilityTracker.reset(
177 new VirtualRobot::SingleChainManipulabilityTracking(manipulability));
180 targetManipulability.setZero(3, 3);
181 targetManipulability << cfg->positionManipulability[0], cfg->positionManipulability[1],
182 cfg->positionManipulability[2], cfg->positionManipulability[3],
183 cfg->positionManipulability[4], cfg->positionManipulability[5],
184 cfg->positionManipulability[6], cfg->positionManipulability[7],
185 cfg->positionManipulability[8];
188 Eigen::VectorXd kmaniVec;
189 kmaniVec.setZero(cfg->kmani.size());
190 for (
size_t i = 0; i < cfg->kmani.size(); ++i)
192 kmaniVec[i] = cfg->kmani[i];
195 kmani = kmaniVec.asDiagonal();
204 RTToControllerData initSensorData;
205 initSensorData.deltaT = 0;
206 initSensorData.currentTime = 0;
207 initSensorData.currentPose = tcp->getPoseInRootFrame();
208 initSensorData.currentTwist.setZero();
209 initSensorData.isPhaseStop =
false;
212 RTToUserData initInterfaceData;
213 initInterfaceData.currentTcpPose = tcp->getPoseInRootFrame();
214 initInterfaceData.waitTimeForCalibration = 0;
220 forceOffset = forceSensor->
force;
226 runTask(
"NJointPeriodicTSDMPCompliantController",
231 while (
getState() == eManagedIceObjectStarted)
237 c.waitForCycleDuration();
247 return "NJointPeriodicTSDMPCompliantController";
263 Eigen::VectorXf targetVels(6);
267 targetVels.setZero();
277 dmpCtrl->flow(deltaT, currentPose, currentTwist);
279 targetVels = dmpCtrl->getTargetVelocity();
281 debugOutputData.
getWriteBuffer().latestTargetVelocities[
"x_vel"] = targetVels(0);
282 debugOutputData.
getWriteBuffer().latestTargetVelocities[
"y_vel"] = targetVels(1);
283 debugOutputData.
getWriteBuffer().latestTargetVelocities[
"z_vel"] = targetVels(2);
284 debugOutputData.
getWriteBuffer().latestTargetVelocities[
"roll_vel"] = targetVels(3);
285 debugOutputData.
getWriteBuffer().latestTargetVelocities[
"pitch_vel"] = targetVels(4);
286 debugOutputData.
getWriteBuffer().latestTargetVelocities[
"yaw_vel"] = targetVels(5);
287 debugOutputData.
getWriteBuffer().currentPose[
"currentPose_x"] = currentPose(0, 3);
288 debugOutputData.
getWriteBuffer().currentPose[
"currentPose_y"] = currentPose(1, 3);
289 debugOutputData.
getWriteBuffer().currentPose[
"currentPose_z"] = currentPose(2, 3);
291 VirtualRobot::MathTools::eigen4f2quat(currentPose);
292 debugOutputData.
getWriteBuffer().currentPose[
"currentPose_qw"] = currentQ.w;
293 debugOutputData.
getWriteBuffer().currentPose[
"currentPose_qx"] = currentQ.x;
294 debugOutputData.
getWriteBuffer().currentPose[
"currentPose_qy"] = currentQ.y;
295 debugOutputData.
getWriteBuffer().currentPose[
"currentPose_qz"] = currentQ.z;
296 debugOutputData.
getWriteBuffer().currentCanVal = dmpCtrl->debugData.canVal;
297 debugOutputData.
getWriteBuffer().mpcFactor = dmpCtrl->debugData.mpcFactor;
298 debugOutputData.
getWriteBuffer().error = dmpCtrl->debugData.poseError;
299 debugOutputData.
getWriteBuffer().posError = dmpCtrl->debugData.posiError;
300 debugOutputData.
getWriteBuffer().oriError = dmpCtrl->debugData.oriError;
315 double deltaT = timeSinceLastIteration.toSecondsDouble();
323 Eigen::MatrixXf jacobi =
324 ik->getJacobianMatrix(tcp, VirtualRobot::IKSolver::CartesianSelection::All);
326 Eigen::VectorXf qpos(positionSensors.size());
327 Eigen::VectorXf qvel(velocitySensors.size());
328 for (
size_t i = 0; i < positionSensors.size(); ++i)
330 qpos(i) = positionSensors[i]->position;
331 qvel(i) = velocitySensors[i]->velocity;
334 qvel_filtered = (1 - cfg->velFilter) * qvel_filtered + cfg->velFilter * qvel;
335 Eigen::VectorXf currentTwist = jacobi * qvel_filtered;
337 Eigen::VectorXf targetVel(6);
339 if (firstRun || !dmpRunning)
341 lastPosition = currentPose.block<2, 1>(0, 3);
342 targetPose = currentPose;
344 filteredForce.setZero();
346 origHandOri = currentPose.block<3, 3>(0, 0);
347 toolTransform = origHandOri.transpose();
352 (1 - cfg->forceFilter) * forceOffset + cfg->forceFilter * forceSensor->
force;
365 filteredForce = (1 - cfg->forceFilter) * filteredForce +
366 cfg->forceFilter * (forceSensor->
force - forceOffset);
368 for (
size_t i = 0; i < 3; ++i)
370 if (fabs(filteredForce(i)) > cfg->forceDeadZone)
373 (filteredForce(i) / fabs(filteredForce(i))) * cfg->forceDeadZone;
377 filteredForce(i) = 0;
381 rtGetRobot()->getSensor(cfg->forceSensorName)->getRobotNode()->getPoseInRootFrame();
383 filteredForceInRoot = forceFrameInRoot.block<3, 3>(0, 0) * filteredForce;
390 float desiredZVel = kpf * (targetForce - filteredForceInRoot(2));
391 targetVel(2) -= desiredZVel;
397 for (
int i = 3; i < 6; ++i)
435 bool isPhaseStop =
false;
437 float diff = (targetPose.block<2, 1>(0, 3) - currentPose.block<2, 1>(0, 3)).
norm();
438 if (diff > cfg->phaseDist0)
443 float dTf = (
float)deltaT;
447 if (filteredForceInRoot.block<2, 1>(0, 0).norm() > cfg->dragForceDeadZone)
449 Eigen::Vector2f dragForce = filteredForceInRoot.block<2, 1>(0, 0) -
450 cfg->dragForceDeadZone *
451 filteredForceInRoot.block<2, 1>(0, 0) /
452 filteredForceInRoot.block<2, 1>(0, 0).
norm();
453 adaptK(0) = fmax(adaptK(0) - dTf * cfg->adaptForceCoeff * dragForce.norm(), 0);
454 adaptK(1) = fmax(adaptK(1) - dTf * cfg->adaptForceCoeff * dragForce.norm(), 0);
459 adaptK(0) = fmin(adaptK(0) + fabs(dTf * cfg->adaptCoeff), kpos(0));
460 adaptK(1) = fmin(adaptK(1) + fabs(dTf * cfg->adaptCoeff), kpos(1));
468 targetPose.block<3, 1>(0, 3) =
469 targetPose.block<3, 1>(0, 3) + dTf * targetVel.block<3, 1>(0, 0);
475 Eigen::Vector2f currentXY = currentPose.block<2, 1>(0, 3);
476 if ((lastPosition - currentXY).norm() < cfg->changePositionTolerance)
478 changeTimer += deltaT;
482 lastPosition = currentPose.block<2, 1>(0, 3);
486 if (changeTimer > cfg->changeTimerThreshold)
488 targetPose(0, 3) = currentPose(0, 3);
489 targetPose(1, 3) = currentPose(1, 3);
500 targetPose(0, 3) = targetPose(0, 3) > cfg->ws_x[0] ? targetPose(0, 3) : cfg->ws_x[0];
501 targetPose(0, 3) = targetPose(0, 3) < cfg->ws_x[1] ? targetPose(0, 3) : cfg->ws_x[1];
503 targetPose(1, 3) = targetPose(1, 3) > cfg->ws_y[0] ? targetPose(1, 3) : cfg->ws_y[0];
504 targetPose(1, 3) = targetPose(1, 3) < cfg->ws_y[1] ? targetPose(1, 3) : cfg->ws_y[1];
506 targetPose(2, 3) = targetPose(2, 3) > cfg->ws_z[0] ? targetPose(2, 3) : cfg->ws_z[0];
507 targetPose(2, 3) = targetPose(2, 3) < cfg->ws_z[1] ? targetPose(2, 3) : cfg->ws_z[1];
529 for (
size_t ki = 0; ki < 3; ++ki)
531 jacobi.row(ki) = 0.001 * jacobi.row(ki);
536 Eigen::Vector3f targetTCPLinearVelocity;
537 targetTCPLinearVelocity << 0.001 * targetVel(0), 0.001 * targetVel(1),
538 0.001 * targetVel(2);
539 Eigen::Vector3f currentTCPLinearVelocity;
540 currentTCPLinearVelocity << 0.001 * currentTwist(0), 0.001 * currentTwist(1),
541 0.001 * currentTwist(2);
542 Eigen::Vector3f currentTCPPosition = currentPose.block<3, 1>(0, 3);
543 Eigen::Vector3f desiredPosition = targetPose.block<3, 1>(0, 3);
545 Eigen::Vector3f linearVel = adaptK.cwiseProduct(desiredPosition - currentTCPPosition);
559 Eigen::Vector3f tcpDesiredForce =
560 0.001 * linearVel + dpos.cwiseProduct(-currentTCPLinearVelocity);
562 Eigen::Vector3f currentTCPAngularVelocity;
563 currentTCPAngularVelocity << currentTwist(3), currentTwist(4), currentTwist(5);
565 Eigen::Matrix3f diffMat = targetPose.block<3, 3>(0, 0) * currentRotMat.inverse();
566 Eigen::Vector3f rpy = VirtualRobot::MathTools::eigen3f2rpy(diffMat);
567 Eigen::Vector3f tcpDesiredTorque =
568 kori.cwiseProduct(rpy) + dori.cwiseProduct(-currentTCPAngularVelocity);
569 jointControlWrench << tcpDesiredForce, tcpDesiredTorque;
574 Eigen::VectorXf nullspaceTorque;
577 if (isManipulability)
580 manipulabilityTracker->calculateVelocity(targetManipulability, kmani,
true);
581 manidist = manipulabilityTracker->computeDistance(targetManipulability);
585 nullspaceTorque = knull * (nullSpaceJointsVec - qpos) - dnull * qvel;
588 Eigen::MatrixXf jtpinv = ik->computePseudoInverseJacobianMatrix(jacobi.transpose(), 2.0);
589 Eigen::VectorXf jointDesiredTorques = jacobi.transpose() * jointControlWrench +
590 (I - jacobi.transpose() * jtpinv) * nullspaceTorque;
593 for (
size_t i = 0; i < targets.size(); ++i)
595 targets.at(i)->torque = jointDesiredTorques(i);
597 if (!targets.at(i)->isValid())
599 targets.at(i)->torque = 0.0f;
603 if (fabs(targets.at(i)->torque) > fabs(cfg->maxJointTorque))
605 targets.at(i)->torque = fabs(cfg->maxJointTorque) *
606 (targets.at(i)->torque / fabs(targets.at(i)->torque));
623 dmpCtrl->learnDMPFromFiles(fileNames);
628 const TrajectoryBasePtr& trajectory,
633 TrajectoryPtr dmpTraj = TrajectoryPtr::dynamicCast(trajectory);
637 dmpCtrl->learnDMPFromTrajectory(dmpTraj);
644 dmpCtrl->setSpeed(times);
649 const Ice::Current& ice)
652 dmpCtrl->setGoalPoseVec(goals);
659 dmpCtrl->setAmplitude(amp);
678 cfg->waitTimeForCalibration)
687 dmpCtrl->prepareExecution(dmpCtrl->eigen4f2vec(pose), goals);
688 dmpCtrl->setSpeed(tau);
700 std::string datafieldName;
701 std::string debugName =
"Periodic";
705 datafields[
"target_x"] =
new Variant(targetPoseDebug(0, 3));
706 datafields[
"target_y"] =
new Variant(targetPoseDebug(1, 3));
707 datafields[
"target_z"] =
new Variant(targetPoseDebug(2, 3));
710 datafields[
"current_x"] =
new Variant(currentPoseDebug(0, 3));
711 datafields[
"current_y"] =
new Variant(currentPoseDebug(1, 3));
712 datafields[
"current_z"] =
new Variant(currentPoseDebug(2, 3));
715 datafields[
"filteredforce_x"] =
new Variant(filteredForce(0));
716 datafields[
"filteredforce_y"] =
new Variant(filteredForce(1));
717 datafields[
"filteredforce_z"] =
new Variant(filteredForce(2));
721 datafields[
"reactForce_x"] =
new Variant(reactForce(0));
722 datafields[
"reactForce_y"] =
new Variant(reactForce(1));
723 datafields[
"reactForce_z"] =
new Variant(reactForce(2));
726 datafields[
"targetVel_x"] =
new Variant(targetVel(0));
727 datafields[
"targetVel_y"] =
new Variant(targetVel(1));
728 datafields[
"targetVel_z"] =
new Variant(targetVel(2));
731 datafields[
"currentVel_x"] =
new Variant(currentVel(0));
732 datafields[
"currentVel_y"] =
new Variant(currentVel(1));
733 datafields[
"currentVel_z"] =
new Variant(currentVel(2));
736 datafields[
"adaptK_x"] =
new Variant(adaptK(0));
737 datafields[
"adaptK_y"] =
new Variant(adaptK(1));
777 datafieldName =
"PeriodicDMP";
778 debugObs->setDebugChannel(datafieldName, datafields);