16 const armarx::NJointControllerConfigPtr& config,
20 cfg = NJointTaskSpaceDMPControllerConfigPtr::dynamicCast(config);
22 VirtualRobot::RobotNodeSetPtr rns =
rtGetRobot()->getRobotNodeSet(cfg->nodeSetName);
23 jointNames = rns->getNodeNames();
25 for (
size_t i = 0; i < rns->getSize(); ++i)
27 std::string jointName = rns->getNode(i)->getName();
30 targets.push_back(ct->
asA<ControlTarget1DoFActuatorVelocity>());
32 const SensorValue1DoFActuatorTorque* torqueSensor =
33 sv->
asA<SensorValue1DoFActuatorTorque>();
34 const SensorValue1DoFActuatorVelocity* velocitySensor =
35 sv->
asA<SensorValue1DoFActuatorVelocity>();
36 const SensorValue1DoFGravityTorque* gravityTorqueSensor =
37 sv->
asA<SensorValue1DoFGravityTorque>();
38 const SensorValue1DoFActuatorPosition* positionSensor =
39 sv->
asA<SensorValue1DoFActuatorPosition>();
44 if (!gravityTorqueSensor)
46 ARMARX_WARNING <<
"No Gravity Torque sensor available for " << jointName;
49 torqueSensors.push_back(torqueSensor);
50 gravityTorqueSensors.push_back(gravityTorqueSensor);
51 velocitySensors.push_back(velocitySensor);
52 positionSensors.push_back(positionSensor);
55 tcp = (cfg->tcpName.empty()) ? rns->getTCP() :
rtGetRobot()->getRobotNode(cfg->tcpName);
56 refFrame = (cfg->frameName.empty()) ? rns->getRobot()->getRootNode()
62 nodeSetName = cfg->nodeSetName;
63 torquePIDs.resize(tcpController->rns->getSize(), pidController());
65 ik.reset(
new VirtualRobot::DifferentialIK(
66 rns, refFrame, VirtualRobot::JacobiProvider::eSVDDamped));
73 taskSpaceDMPConfig.
DMPMode = cfg->dmpMode;
74 taskSpaceDMPConfig.
DMPStyle = cfg->dmpStyle;
91 RTToControllerData initSensorData;
92 initSensorData.deltaT = 0;
93 initSensorData.currentTime = 0;
94 initSensorData.currentPose.setZero();
95 initSensorData.currentTwist.setZero();
96 rt2CtrlData.reinitAllBuffers(initSensorData);
98 targetVels.setZero(6);
101 initData.
targetPose = refFrame->toLocalCoordinateSystem(tcp->getGlobalPose());
103 initData.
torqueKp.resize(tcpController->rns->getSize(), 0);
104 initData.
torqueKd.resize(tcpController->rns->getSize(), 0);
108 debugName = cfg->debugName;
110 KpF = cfg->Kp_LinearVel;
111 KoF = cfg->Kp_AngularVel;
112 DpF = cfg->Kd_LinearVel;
113 DoF = cfg->Kd_AngularVel;
115 filtered_qvel.setZero(targets.size());
116 vel_filter_factor = cfg->vel_filter;
118 filtered_position.setZero(3);
119 pos_filter_factor = cfg->pos_filter;
125 jointLowLimits.setZero(targets.size());
126 jointHighLimits.setZero(targets.size());
127 for (
size_t i = 0; i < rns->getSize(); i++)
129 VirtualRobot::RobotNodePtr rn = rns->getAllRobotNodes().at(i);
131 jointLowLimits(i) = rn->getJointLimitLo();
132 jointHighLimits(i) = rn->getJointLimitHi();
137 RTToUserData initInterfaceData;
138 initInterfaceData.currentTcpPose = Eigen::Matrix4f::Identity();
139 rt2UserData.reinitAllBuffers(initInterfaceData);
156 if (!rt2CtrlData.updateReadBuffer() || !dmpCtrl)
161 double deltaT = rt2CtrlData.getReadBuffer().deltaT;
162 Eigen::Matrix4f currentPose = rt2CtrlData.getReadBuffer().currentPose;
163 Eigen::VectorXf currentTwist = rt2CtrlData.getReadBuffer().currentTwist;
166 dmpCtrl->flow(deltaT, currentPose, currentTwist);
168 if (dmpCtrl->canVal < 1e-8)
172 targetVels = dmpCtrl->getTargetVelocity();
173 targetPose = dmpCtrl->getTargetPoseMat();
174 std::vector<double> targetState = dmpCtrl->getTargetPose();
176 debugOutputData.getWriteBuffer().latestTargetVelocities[
"x_vel"] = targetVels(0);
177 debugOutputData.getWriteBuffer().latestTargetVelocities[
"y_vel"] = targetVels(1);
178 debugOutputData.getWriteBuffer().latestTargetVelocities[
"z_vel"] = targetVels(2);
179 debugOutputData.getWriteBuffer().latestTargetVelocities[
"roll_vel"] = targetVels(3);
180 debugOutputData.getWriteBuffer().latestTargetVelocities[
"pitch_vel"] = targetVels(4);
181 debugOutputData.getWriteBuffer().latestTargetVelocities[
"yaw_vel"] = targetVels(5);
182 debugOutputData.getWriteBuffer().dmpTargets[
"dmp_x"] = targetState[0];
183 debugOutputData.getWriteBuffer().dmpTargets[
"dmp_y"] = targetState[1];
184 debugOutputData.getWriteBuffer().dmpTargets[
"dmp_z"] = targetState[2];
185 debugOutputData.getWriteBuffer().dmpTargets[
"dmp_qw"] = targetState[3];
186 debugOutputData.getWriteBuffer().dmpTargets[
"dmp_qx"] = targetState[4];
187 debugOutputData.getWriteBuffer().dmpTargets[
"dmp_qy"] = targetState[5];
188 debugOutputData.getWriteBuffer().dmpTargets[
"dmp_qz"] = targetState[6];
189 debugOutputData.getWriteBuffer().currentPose[
"currentPose_x"] = currentPose(0, 3);
190 debugOutputData.getWriteBuffer().currentPose[
"currentPose_y"] = currentPose(1, 3);
191 debugOutputData.getWriteBuffer().currentPose[
"currentPose_z"] = currentPose(2, 3);
193 VirtualRobot::MathTools::Quaternion currentQ =
194 VirtualRobot::MathTools::eigen4f2quat(currentPose);
195 debugOutputData.getWriteBuffer().currentPose[
"currentPose_qw"] = currentQ.w;
196 debugOutputData.getWriteBuffer().currentPose[
"currentPose_qx"] = currentQ.x;
197 debugOutputData.getWriteBuffer().currentPose[
"currentPose_qy"] = currentQ.y;
198 debugOutputData.getWriteBuffer().currentPose[
"currentPose_qz"] = currentQ.z;
199 debugOutputData.getWriteBuffer().currentCanVal = dmpCtrl->debugData.canVal;
200 debugOutputData.getWriteBuffer().mpcFactor = dmpCtrl->debugData.mpcFactor;
201 debugOutputData.getWriteBuffer().error = dmpCtrl->debugData.poseError;
202 debugOutputData.getWriteBuffer().posError = dmpCtrl->debugData.posiError;
203 debugOutputData.getWriteBuffer().oriError = dmpCtrl->debugData.oriError;
204 debugOutputData.getWriteBuffer().deltaT = deltaT;
206 debugOutputData.commitWrite();
215 const Eigen::VectorXf& nullspaceVel,
216 VirtualRobot::IKSolver::CartesianSelection mode)
218 Eigen::MatrixXf jacobi = ik->getJacobianMatrix(tcp, mode);
220 Eigen::FullPivLU<Eigen::MatrixXf> lu_decomp(jacobi);
222 Eigen::MatrixXf nullspace = lu_decomp.kernel();
223 Eigen::VectorXf nsv = Eigen::VectorXf::Zero(nullspace.rows());
224 for (
int i = 0; i < nullspace.cols(); i++)
226 float squaredNorm = nullspace.col(i).squaredNorm();
228 if (squaredNorm > 1.0e-32f)
230 nsv += nullspace.col(i) * nullspace.col(i).dot(nullspaceVel) /
231 nullspace.col(i).squaredNorm();
235 Eigen::MatrixXf inv =
236 ik->computePseudoInverseJacobianMatrix(jacobi, ik->getJacobiRegularization(mode));
238 Eigen::VectorXf jointVel = inv * cartesianVel;
245 const IceUtil::Time& timeSinceLastIteration)
247 Eigen::Matrix4f currentPose = refFrame->toLocalCoordinateSystem(tcp->getGlobalPose());
248 rt2UserData.getWriteBuffer().currentTcpPose = currentPose;
249 rt2UserData.commitWrite();
253 filtered_position = currentPose.block<3, 1>(0, 3);
256 for (
size_t i = 0; i < targets.size(); ++i)
258 targets.at(i)->velocity = 0;
264 filtered_position = (1 - pos_filter_factor) * filtered_position +
265 pos_filter_factor * currentPose.block<3, 1>(0, 3);
268 double deltaT = timeSinceLastIteration.toSecondsDouble();
270 Eigen::MatrixXf jacobi =
271 ik->getJacobianMatrix(tcp, VirtualRobot::IKSolver::CartesianSelection::All);
273 Eigen::VectorXf qvel(velocitySensors.size());
274 for (
size_t i = 0; i < velocitySensors.size(); ++i)
276 qvel(i) = velocitySensors[i]->velocity;
279 filtered_qvel = (1 - vel_filter_factor) * filtered_qvel + vel_filter_factor * qvel;
280 Eigen::VectorXf tcptwist = jacobi * filtered_qvel;
282 rt2CtrlData.getWriteBuffer().currentPose = currentPose;
283 rt2CtrlData.getWriteBuffer().currentTwist = tcptwist;
284 rt2CtrlData.getWriteBuffer().deltaT = deltaT;
285 rt2CtrlData.getWriteBuffer().currentTime += deltaT;
286 rt2CtrlData.commitWrite();
288 rt2UserData.getWriteBuffer().currentTcpPose = currentPose;
289 rt2UserData.commitWrite();
294 Eigen::VectorXf jointTargetVelocities = Eigen::VectorXf::Zero(targets.size());
300 Eigen::Matrix3f diffMat =
301 targetPose.block<3, 3>(0, 0) * currentPose.block<3, 3>(0, 0).inverse();
302 Eigen::Vector3f errorRPY = VirtualRobot::MathTools::eigen3f2rpy(diffMat);
305 rtTargetVel.block<3, 1>(0, 0) =
306 KpF * (targetPose.block<3, 1>(0, 3) - currentPose.block<3, 1>(0, 3)) +
307 DpF * (-tcptwist.block<3, 1>(0, 0));
309 rtTargetVel.block<3, 1>(3, 0) =
310 KoF * errorRPY + DoF * (targetVel.block<3, 1>(3, 0) - tcptwist.block<3, 1>(3, 0));
314 float normLinearVelocity = rtTargetVel.block<3, 1>(0, 0).
norm();
315 if (normLinearVelocity > cfg->maxLinearVel)
317 rtTargetVel.block<3, 1>(0, 0) =
318 cfg->maxLinearVel * rtTargetVel.block<3, 1>(0, 0) / normLinearVelocity;
321 float normAngularVelocity = rtTargetVel.block<3, 1>(3, 0).
norm();
322 if (normAngularVelocity > cfg->maxAngularVel)
324 rtTargetVel.block<3, 1>(3, 0) =
325 cfg->maxAngularVel * rtTargetVel.block<3, 1>(3, 0) / normAngularVelocity;
336 Eigen::VectorXf jnv = Eigen::VectorXf::Zero(tcpController->rns->getSize());
338 if (jointLimitAvoidanceKp > 0)
340 jnv += jointLimitAvoidanceKp * tcpController->calculateJointLimitAvoidance();
342 for (
size_t i = 0; i < tcpController->rns->getSize(); i++)
348 jointTargetVelocities =
349 calcIK(rtTargetVel, jnv, VirtualRobot::IKSolver::CartesianSelection::All);
355 for (
size_t i = 0; i < targets.size(); ++i)
357 targets.at(i)->velocity = jointTargetVelocities(i);
359 if (!targets.at(i)->isValid() || fabs(targets.at(i)->velocity) > cfg->maxJointVelocity)
361 targets.at(i)->velocity = 0.0f;
364 rtDebugData.getWriteBuffer().targetJointVels = jointTargetVelocities;
365 rtDebugData.commitWrite();
573 std::string datafieldName = debugName;
575 auto values = debugOutputData.getUpToDateReadBuffer().latestTargetVelocities;
576 for (
auto& pair : values)
578 datafieldName = pair.first +
"_" + debugName;
579 datafields[datafieldName] =
new Variant(pair.second);
582 auto dmpTargets = debugOutputData.getUpToDateReadBuffer().dmpTargets;
583 for (
auto& pair : dmpTargets)
585 datafieldName = pair.first +
"_" + debugName;
586 datafields[datafieldName] =
new Variant(pair.second);
589 auto currentPose = debugOutputData.getUpToDateReadBuffer().currentPose;
590 for (
auto& pair : currentPose)
592 datafieldName = pair.first +
"_" + debugName;
593 datafields[datafieldName] =
new Variant(pair.second);
596 datafieldName =
"canVal_" + debugName;
597 datafields[datafieldName] =
598 new Variant(debugOutputData.getUpToDateReadBuffer().currentCanVal);
599 datafieldName =
"mpcFactor_" + debugName;
600 datafields[datafieldName] =
new Variant(debugOutputData.getUpToDateReadBuffer().mpcFactor);
601 datafieldName =
"error_" + debugName;
602 datafields[datafieldName] =
new Variant(debugOutputData.getUpToDateReadBuffer().error);
603 datafieldName =
"posError_" + debugName;
604 datafields[datafieldName] =
new Variant(debugOutputData.getUpToDateReadBuffer().posError);
605 datafieldName =
"oriError_" + debugName;
606 datafields[datafieldName] =
new Variant(debugOutputData.getUpToDateReadBuffer().oriError);
607 datafieldName =
"deltaT_" + debugName;
608 datafields[datafieldName] =
new Variant(debugOutputData.getUpToDateReadBuffer().deltaT);
611 Eigen::VectorXf targetJoints = rtDebugData.getUpToDateReadBuffer().targetJointVels;
612 for (
int i = 0; i < targetJoints.size(); ++i)
614 datafieldName = jointNames[i] +
"_velocity";
615 datafields[datafieldName] =
new Variant(targetJoints[i]);
618 datafieldName =
"DMPController_" + debugName;
619 debugObs->setDebugChannel(datafieldName, datafields);