12 cfg = NJointPeriodicTSDMPCompliantControllerConfigPtr::dynamicCast(config);
14 VirtualRobot::RobotNodeSetPtr rns =
rtGetRobot()->getRobotNodeSet(cfg->nodeSetName);
17 for (
size_t i = 0; i < rns->getSize(); ++i)
19 std::string jointName = rns->getNode(i)->getName();
22 targets.push_back(ct->
asA<ControlTarget1DoFActuatorTorque>());
24 const SensorValue1DoFActuatorVelocity* velocitySensor = sv->
asA<SensorValue1DoFActuatorVelocity>();
25 const SensorValue1DoFActuatorPosition* positionSensor = sv->
asA<SensorValue1DoFActuatorPosition>();
27 velocitySensors.push_back(velocitySensor);
28 positionSensors.push_back(positionSensor);
33 nodeSetName = cfg->nodeSetName;
34 ik.reset(
new VirtualRobot::DifferentialIK(rns, rns->getRobot()->getRootNode(), VirtualRobot::JacobiProvider::eSVDDamped));
40 taskSpaceDMPConfig.
DMPMode =
"Linear";
41 taskSpaceDMPConfig.
DMPStyle =
"Periodic";
58 for (
size_t i = 0; i < 6; ++i)
73 kpos << cfg->Kpos[0], cfg->Kpos[1], cfg->Kpos[2];
74 dpos << cfg->Dpos[0], cfg->Dpos[1], cfg->Dpos[2];
75 kori << cfg->Kori[0], cfg->Kori[1], cfg->Kori[2];
76 dori << cfg->Dori[0], cfg->Dori[1], cfg->Dori[2];
84 nullSpaceJointsVec.resize(cfg->desiredNullSpaceJointValues.size());
85 for (
size_t i = 0; i < cfg->desiredNullSpaceJointValues.size(); ++i)
87 nullSpaceJointsVec(i) = cfg->desiredNullSpaceJointValues.at(i);
91 const SensorValueBase* svlf = robUnit->getSensorDevice(cfg->forceSensorName)->getSensorValue();
94 forceOffset.setZero();
95 filteredForce.setZero();
96 filteredForceInRoot.setZero();
99 UserToRTData initUserData;
100 initUserData.targetForce = 0;
103 oriToolDir << 0, 0, 1;
105 qvel_filtered.setZero(targets.size());
112 if (!cfg->ignoreWSLimitChecks)
132 isManipulability = cfg->isManipulability;
136 Eigen::VectorXd maniWeightVec;
137 maniWeightVec.setOnes(rns->getNodeNames().size());
138 for (
size_t i = 0; i < cfg->maniWeight.size(); ++i)
140 maniWeightVec(i) = cfg->maniWeight[i];
143 Eigen::MatrixXd maniWeightMat = maniWeightVec.asDiagonal();
144 VirtualRobot::SingleRobotNodeSetManipulabilityPtr manipulability(
145 new VirtualRobot::SingleRobotNodeSetManipulability(rns, rns->getTCP(),
147 VirtualRobot::AbstractManipulability::Type::Velocity,
148 rns->getRobot()->getRootNode(), maniWeightMat));
149 manipulabilityTracker.reset(
new VirtualRobot::SingleChainManipulabilityTracking(manipulability));
152 targetManipulability.setZero(3, 3);
153 targetManipulability << cfg->positionManipulability[0], cfg->positionManipulability[1], cfg->positionManipulability[2],
154 cfg->positionManipulability[3], cfg->positionManipulability[4], cfg->positionManipulability[5],
155 cfg->positionManipulability[6], cfg->positionManipulability[7], cfg->positionManipulability[8];
158 Eigen::VectorXd kmaniVec;
159 kmaniVec.setZero(cfg->kmani.size());
160 for (
size_t i = 0; i < cfg->kmani.size(); ++i)
162 kmaniVec[i] = cfg->kmani[i];
165 kmani = kmaniVec.asDiagonal();
174 RTToControllerData initSensorData;
175 initSensorData.deltaT = 0;
176 initSensorData.currentTime = 0;
177 initSensorData.currentPose = tcp->getPoseInRootFrame();
178 initSensorData.currentTwist.setZero();
179 initSensorData.isPhaseStop =
false;
182 RTToUserData initInterfaceData;
183 initInterfaceData.currentTcpPose = tcp->getPoseInRootFrame();
184 initInterfaceData.waitTimeForCalibration = 0;
190 forceOffset = forceSensor->
force;
196 runTask(
"NJointPeriodicTSDMPCompliantController", [&]
200 while (
getState() == eManagedIceObjectStarted)
206 c.waitForCycleDuration();
216 return "NJointPeriodicTSDMPCompliantController";
231 Eigen::VectorXf targetVels(6);
235 targetVels.setZero();
245 dmpCtrl->flow(deltaT, currentPose, currentTwist);
247 targetVels = dmpCtrl->getTargetVelocity();
249 debugOutputData.
getWriteBuffer().latestTargetVelocities[
"x_vel"] = targetVels(0);
250 debugOutputData.
getWriteBuffer().latestTargetVelocities[
"y_vel"] = targetVels(1);
251 debugOutputData.
getWriteBuffer().latestTargetVelocities[
"z_vel"] = targetVels(2);
252 debugOutputData.
getWriteBuffer().latestTargetVelocities[
"roll_vel"] = targetVels(3);
253 debugOutputData.
getWriteBuffer().latestTargetVelocities[
"pitch_vel"] = targetVels(4);
254 debugOutputData.
getWriteBuffer().latestTargetVelocities[
"yaw_vel"] = targetVels(5);
255 debugOutputData.
getWriteBuffer().currentPose[
"currentPose_x"] = currentPose(0, 3);
256 debugOutputData.
getWriteBuffer().currentPose[
"currentPose_y"] = currentPose(1, 3);
257 debugOutputData.
getWriteBuffer().currentPose[
"currentPose_z"] = currentPose(2, 3);
259 debugOutputData.
getWriteBuffer().currentPose[
"currentPose_qw"] = currentQ.w;
260 debugOutputData.
getWriteBuffer().currentPose[
"currentPose_qx"] = currentQ.x;
261 debugOutputData.
getWriteBuffer().currentPose[
"currentPose_qy"] = currentQ.y;
262 debugOutputData.
getWriteBuffer().currentPose[
"currentPose_qz"] = currentQ.z;
263 debugOutputData.
getWriteBuffer().currentCanVal = dmpCtrl->debugData.canVal;
264 debugOutputData.
getWriteBuffer().mpcFactor = dmpCtrl->debugData.mpcFactor;
265 debugOutputData.
getWriteBuffer().error = dmpCtrl->debugData.poseError;
266 debugOutputData.
getWriteBuffer().posError = dmpCtrl->debugData.posiError;
267 debugOutputData.
getWriteBuffer().oriError = dmpCtrl->debugData.oriError;
281 double deltaT = timeSinceLastIteration.toSecondsDouble();
289 Eigen::MatrixXf jacobi = ik->getJacobianMatrix(tcp, VirtualRobot::IKSolver::CartesianSelection::All);
291 Eigen::VectorXf qpos(positionSensors.size());
292 Eigen::VectorXf qvel(velocitySensors.size());
293 for (
size_t i = 0; i < positionSensors.size(); ++i)
295 qpos(i) = positionSensors[i]->position;
296 qvel(i) = velocitySensors[i]->velocity;
299 qvel_filtered = (1 - cfg->velFilter) * qvel_filtered + cfg->velFilter * qvel;
300 Eigen::VectorXf currentTwist = jacobi * qvel_filtered;
302 Eigen::VectorXf targetVel(6);
304 if (firstRun || !dmpRunning)
306 lastPosition = currentPose.block<2, 1>(0, 3);
307 targetPose = currentPose;
309 filteredForce.setZero();
311 origHandOri = currentPose.block<3, 3>(0, 0);
312 toolTransform = origHandOri.transpose();
316 forceOffset = (1 - cfg->forceFilter) * forceOffset + cfg->forceFilter * forceSensor->
force;
329 filteredForce = (1 - cfg->forceFilter) * filteredForce + cfg->forceFilter * (forceSensor->
force - forceOffset);
331 for (
size_t i = 0; i < 3; ++i)
333 if (fabs(filteredForce(i)) > cfg->forceDeadZone)
335 filteredForce(i) -= (filteredForce(i) / fabs(filteredForce(i))) * cfg->forceDeadZone;
339 filteredForce(i) = 0;
344 filteredForceInRoot = forceFrameInRoot.block<3, 3>(0, 0) * filteredForce;
349 float desiredZVel = kpf * (targetForce - filteredForceInRoot(2));
350 targetVel(2) -= desiredZVel;
356 for (
int i = 3; i < 6; ++i)
399 bool isPhaseStop =
false;
401 float diff = (targetPose.block<2, 1>(0, 3) - currentPose.block<2, 1>(0, 3)).
norm();
402 if (diff > cfg->phaseDist0)
407 float dTf = (
float)deltaT;
410 if (filteredForceInRoot.block<2, 1>(0, 0).norm() > cfg->dragForceDeadZone)
412 Eigen::Vector2f dragForce = filteredForceInRoot.block<2, 1>(0, 0) - cfg->dragForceDeadZone * filteredForceInRoot.block<2, 1>(0, 0) / filteredForceInRoot.block<2, 1>(0, 0).
norm();
413 adaptK(0) = fmax(adaptK(0) - dTf * cfg->adaptForceCoeff * dragForce.norm(), 0);
414 adaptK(1) = fmax(adaptK(1) - dTf * cfg->adaptForceCoeff * dragForce.norm(), 0);
419 adaptK(0) = fmin(adaptK(0) + fabs(dTf * cfg->adaptCoeff), kpos(0));
420 adaptK(1) = fmin(adaptK(1) + fabs(dTf * cfg->adaptCoeff), kpos(1));
429 targetPose.block<3, 1>(0, 3) = targetPose.block<3, 1>(0, 3) + dTf * targetVel.block<3, 1>(0, 0);
433 Eigen::Vector2f currentXY = currentPose.block<2, 1>(0, 3);
434 if ((lastPosition - currentXY).norm() < cfg->changePositionTolerance)
436 changeTimer += deltaT;
440 lastPosition = currentPose.block<2, 1>(0, 3);
444 if (changeTimer > cfg->changeTimerThreshold)
446 targetPose(0, 3) = currentPose(0, 3);
447 targetPose(1, 3) = currentPose(1, 3);
458 targetPose(0, 3) = targetPose(0, 3) > cfg->ws_x[0] ? targetPose(0, 3) : cfg->ws_x[0];
459 targetPose(0, 3) = targetPose(0, 3) < cfg->ws_x[1] ? targetPose(0, 3) : cfg->ws_x[1];
461 targetPose(1, 3) = targetPose(1, 3) > cfg->ws_y[0] ? targetPose(1, 3) : cfg->ws_y[0];
462 targetPose(1, 3) = targetPose(1, 3) < cfg->ws_y[1] ? targetPose(1, 3) : cfg->ws_y[1];
464 targetPose(2, 3) = targetPose(2, 3) > cfg->ws_z[0] ? targetPose(2, 3) : cfg->ws_z[0];
465 targetPose(2, 3) = targetPose(2, 3) < cfg->ws_z[1] ? targetPose(2, 3) : cfg->ws_z[1];
490 for (
size_t ki = 0; ki < 3; ++ki)
492 jacobi.row(ki) = 0.001 * jacobi.row(ki);
501 Eigen::Vector3f targetTCPLinearVelocity;
502 targetTCPLinearVelocity << 0.001 * targetVel(0), 0.001 * targetVel(1), 0.001 * targetVel(2);
503 Eigen::Vector3f currentTCPLinearVelocity;
504 currentTCPLinearVelocity << 0.001 * currentTwist(0), 0.001 * currentTwist(1), 0.001 * currentTwist(2);
505 Eigen::Vector3f currentTCPPosition = currentPose.block<3, 1>(0, 3);
506 Eigen::Vector3f desiredPosition = targetPose.block<3, 1>(0, 3);
508 Eigen::Vector3f linearVel = adaptK.cwiseProduct(desiredPosition - currentTCPPosition);
522 Eigen::Vector3f tcpDesiredForce = 0.001 * linearVel + dpos.cwiseProduct(- currentTCPLinearVelocity);
524 Eigen::Vector3f currentTCPAngularVelocity;
525 currentTCPAngularVelocity << currentTwist(3), currentTwist(4), currentTwist(5);
527 Eigen::Matrix3f diffMat = targetPose.block<3, 3>(0, 0) * currentRotMat.inverse();
528 Eigen::Vector3f rpy = VirtualRobot::MathTools::eigen3f2rpy(diffMat);
529 Eigen::Vector3f tcpDesiredTorque = kori.cwiseProduct(rpy) + dori.cwiseProduct(- currentTCPAngularVelocity);
530 jointControlWrench << tcpDesiredForce, tcpDesiredTorque;
536 Eigen::VectorXf nullspaceTorque;
539 if (isManipulability)
541 nullspaceTorque = manipulabilityTracker->calculateVelocity(targetManipulability, kmani,
true);
542 manidist = manipulabilityTracker->computeDistance(targetManipulability);
546 nullspaceTorque = knull * (nullSpaceJointsVec - qpos) - dnull * qvel;
549 Eigen::MatrixXf jtpinv = ik->computePseudoInverseJacobianMatrix(jacobi.transpose(), 2.0);
550 Eigen::VectorXf jointDesiredTorques = jacobi.transpose() * jointControlWrench + (I - jacobi.transpose() * jtpinv) * nullspaceTorque;
553 for (
size_t i = 0; i < targets.size(); ++i)
555 targets.at(i)->torque = jointDesiredTorques(i);
557 if (!targets.at(i)->isValid())
559 targets.at(i)->torque = 0.0f;
563 if (fabs(targets.at(i)->torque) > fabs(cfg->maxJointTorque))
565 targets.at(i)->torque = fabs(cfg->maxJointTorque) * (targets.at(i)->torque / fabs(targets.at(i)->torque));
583 dmpCtrl->learnDMPFromFiles(fileNames);
591 TrajectoryPtr dmpTraj = TrajectoryPtr::dynamicCast(trajectory);
595 dmpCtrl->learnDMPFromTrajectory(dmpTraj);
602 dmpCtrl->setSpeed(times);
609 dmpCtrl->setGoalPoseVec(goals);
615 dmpCtrl->setAmplitude(amp);
628 while (firstRun || rt2UserData.
getUpToDateReadBuffer().waitTimeForCalibration < cfg->waitTimeForCalibration)
637 dmpCtrl->prepareExecution(dmpCtrl->eigen4f2vec(pose), goals);
638 dmpCtrl->setSpeed(tau);
648 std::string datafieldName;
649 std::string debugName =
"Periodic";
653 datafields[
"target_x"] =
new Variant(targetPoseDebug(0, 3));
654 datafields[
"target_y"] =
new Variant(targetPoseDebug(1, 3));
655 datafields[
"target_z"] =
new Variant(targetPoseDebug(2, 3));
658 datafields[
"current_x"] =
new Variant(currentPoseDebug(0, 3));
659 datafields[
"current_y"] =
new Variant(currentPoseDebug(1, 3));
660 datafields[
"current_z"] =
new Variant(currentPoseDebug(2, 3));
663 datafields[
"filteredforce_x"] =
new Variant(filteredForce(0));
664 datafields[
"filteredforce_y"] =
new Variant(filteredForce(1));
665 datafields[
"filteredforce_z"] =
new Variant(filteredForce(2));
669 datafields[
"reactForce_x"] =
new Variant(reactForce(0));
670 datafields[
"reactForce_y"] =
new Variant(reactForce(1));
671 datafields[
"reactForce_z"] =
new Variant(reactForce(2));
674 datafields[
"targetVel_x"] =
new Variant(targetVel(0));
675 datafields[
"targetVel_y"] =
new Variant(targetVel(1));
676 datafields[
"targetVel_z"] =
new Variant(targetVel(2));
679 datafields[
"currentVel_x"] =
new Variant(currentVel(0));
680 datafields[
"currentVel_y"] =
new Variant(currentVel(1));
681 datafields[
"currentVel_z"] =
new Variant(currentVel(2));
684 datafields[
"adaptK_x"] =
new Variant(adaptK(0));
685 datafields[
"adaptK_y"] =
new Variant(adaptK(1));
725 datafieldName =
"PeriodicDMP";
726 debugObs->setDebugChannel(datafieldName, datafields);