71 const NJointCartesianNaturalPositionControllerConfigPtr& config,
84 _rtRns = _rtRobot->getRobotNodeSet(config->rns);
86 _rtTcp = _rtRns->getTCP();
88 _rtElbow = _rtRobot->getRobotNode(config->elbowNode);
91 _rtRobotRoot = _rtRobot->getRootNode();
97 if (!config->ftName.empty())
101 _rtForceSensor = &(svalFT->force);
102 _rtTorqueSensor = &(svalFT->force);
107 const auto reportFrameName = sdev->getReportingFrame();
109 <<
VAROUT(sdev->getReportingFrame());
111 _rtFT = _rtRobot->getRobotNode(reportFrameName);
113 <<
"No sensor report frame '" << reportFrameName <<
"' in robot";
119 _rtJointVelocityFeedbackBuffer =
120 Eigen::VectorXf::Zero(
static_cast<int>(_rtRns->getSize()));
122 _rtPosController = std::make_unique<CartesianNaturalPositionController>(
125 config->runCfg.maxPositionAcceleration,
126 config->runCfg.maxOrientationAcceleration,
127 config->runCfg.maxNullspaceAcceleration);
129 _rtPosController->setConfig(config->runCfg);
132 for (
size_t i = 0; i < _rtRns->getSize(); ++i)
134 std::string jointName = _rtRns->getNode(i)->getName();
136 jointName, ControlModes::Velocity1DoF);
141 _rtVelTargets.emplace_back(&(ct->velocity));
142 _rtVelSensors.emplace_back(&(sv->velocity));
146 _rtFFvelMaxAgeMS = config->feedforwardVelocityTTLms;
148 _rtFTHistory.resize(config->ftHistorySize, FTval());
153 _tripFakeRobotGP.getWriteBuffer()(0, 0) = std::nanf(
"");
154 _tripFakeRobotGP.commitWrite();
180 const IceUtil::Time& timeSinceLastIteration)
182 auto& rt2nonrtBuf = _tripRt2NonRt.getWriteBuffer();
184 if (_tripBufCfg.updateReadBuffer())
187 auto& r = _tripBufCfg._getNonConstReadBuffer();
191 _rtPosController->setConfig(r.cfg);
195 if (_tripBufTarget.updateReadBuffer())
198 auto& r = _tripBufTarget._getNonConstReadBuffer();
202 _rtSetOrientation = r.setOrientation;
203 _rtPosController->setTarget(r.tcpTarget, r.elbowTarget);
204 _rtStopConditionReached =
false;
205 _publishIsAtForceLimit =
false;
208 if (_tripBufNullspaceTarget.updateReadBuffer())
211 auto& r = _tripBufNullspaceTarget._getNonConstReadBuffer();
215 if (r.clearRequested)
217 _rtPosController->clearNullspaceTarget();
222 _rtPosController->setNullspaceTarget(r.nullspaceTarget);
224 r.clearRequested =
false;
227 if (_tripBufFFvel.updateReadBuffer())
229 _rtFFvel = _tripBufFFvel.getReadBuffer();
230 _rtFFvelLastUpdateMS = sensorValuesTimestamp.toMilliSeconds();
232 if (_tripBufFToffset.updateReadBuffer())
234 _rtFTOffset = _tripBufFToffset.getReadBuffer();
236 if (_tripBufFTlimit.updateReadBuffer())
238 _rtFTlimit = _tripBufFTlimit.getReadBuffer();
239 if (_rtFTlimit.force < 0 && _rtFTlimit.torque < 0)
241 _publishIsAtForceLimit =
false;
244 if (_tripBufFTfake.updateReadBuffer())
246 _rtFTfake = _tripBufFTfake.getReadBuffer();
266 ft.force = *_rtForceSensor;
267 ft.torque = *_rtTorqueSensor;
271 ft.force = _rtFTfake.force;
272 ft.torque = _rtFTfake.torque;
276 _rtFTHistory.at(_rtFTHistoryIndex) = ft;
277 _rtFTHistoryIndex = (_rtFTHistoryIndex + 1) % _rtFTHistory.size();
280 for (
size_t i = 0; i < _rtFTHistory.size(); i++)
282 ftAvg.force += _rtFTHistory.at(i).force;
283 ftAvg.torque += _rtFTHistory.at(i).torque;
285 ftAvg.force = ftAvg.force / _rtFTHistory.size();
286 ftAvg.torque = ftAvg.torque / _rtFTHistory.size();
289 rt2nonrtBuf.currentFT = ft;
290 rt2nonrtBuf.averageFT = ftAvg;
292 if ((_rtFTlimit.force > 0 && ft.force.norm() > _rtFTlimit.force) ||
293 (_rtFTlimit.torque > 0 && ft.torque.norm() > _rtFTlimit.torque))
295 _rtStopConditionReached =
true;
296 _publishIsAtForceLimit =
true;
322 rt2nonrtBuf.rootPose = _rtRobot->getGlobalPose();
323 rt2nonrtBuf.tcp = _rtTcp->getPoseInRootFrame();
324 rt2nonrtBuf.elb = _rtElbow->getPoseInRootFrame();
325 rt2nonrtBuf.tcpTarg = _rtPosController->getCurrentTarget();
326 rt2nonrtBuf.elbTarg = ::math::Helpers::CreatePose(_rtPosController->getCurrentElbowTarget(),
327 Eigen::Matrix3f::Identity());
330 if (_rtStopConditionReached)
336 VirtualRobot::IKSolver::CartesianSelection mode =
337 _rtSetOrientation ? VirtualRobot::IKSolver::All : VirtualRobot::IKSolver::Position;
338 _rtPosController->setNullSpaceControl(_nullspaceControlEnabled);
342 if (_rtFFvelLastUpdateMS + _rtFFvelMaxAgeMS >
343 sensorValuesTimestamp.toMilliSeconds())
345 _rtPosController->setFeedForwardVelocity(_rtFFvel.feedForwardVelocity);
350 _rtFFvel.use =
false;
354 const Eigen::VectorXf& goal =
355 _rtPosController->calculate(timeSinceLastIteration.toSecondsDouble(), mode);
357 const Eigen::VectorXf actualTcpVel = _rtPosController->actualTcpVel(goal);
358 const Eigen::VectorXf actualElbVel = _rtPosController->actualElbVel(goal);
360 _publish.tcpPosVel = actualTcpVel.block<3, 1>(0, 0).
norm();
361 _publish.tcpOriVel = actualTcpVel.block<3, 1>(3, 0).
norm();
362 _publish.elbPosVel = actualElbVel.block<3, 1>(0, 0).
norm();
366 for (std::size_t idx = 0; idx < _rtVelTargets.size(); ++idx)
368 float* ptr = _rtVelTargets[idx];
372 _tripRt2NonRt.commitWrite();
648 const float errorPos = _publish.errorPos;
649 const float errorOri = _publish.errorOri;
650 const float errorPosMax = _publish.errorPosMax;
651 const float errorOriMax = _publish.errorOriMax;
654 const float tcpPosVel = _publish.tcpPosVel;
655 const float tcpOriVel = _publish.tcpOriVel;
656 const float elbPosVel = _publish.elbPosVel;
661 datafields[
"errorPos"] =
new Variant(errorPos);
662 datafields[
"errorOri"] =
new Variant(errorOri);
663 datafields[
"errorPosMax"] =
new Variant(errorPosMax);
664 datafields[
"errorOriMax"] =
new Variant(errorOriMax);
666 datafields[
"tcpPosVel"] =
new Variant(tcpPosVel);
667 datafields[
"tcpOriVel"] =
new Variant(tcpOriVel);
668 datafields[
"elbPosVel"] =
new Variant(elbPosVel);
677 << errorPosMax <<
", oerror " << errorOri <<
" / " << errorOriMax <<
')';
680 std::lock_guard g{_tripRt2NonRtMutex};
681 const auto& buf = _tripRt2NonRt.getUpToDateReadBuffer();
683 const Eigen::Matrix4f fakeGP = _tripFakeRobotGP.getUpToDateReadBuffer();
684 const Eigen::Matrix4f gp =
std::isfinite(fakeGP(0, 0)) ? fakeGP : buf.rootPose;
686 if (buf.tcp != buf.tcpTarg)
688 const Eigen::Matrix4f gtcp = gp * buf.tcp;
689 const Eigen::Matrix4f gtcptarg = gp * buf.tcpTarg;
690 const Eigen::Matrix4f gelb = gp * buf.elb;
691 const Eigen::Matrix4f gelbtarg = gp * buf.elbTarg;
692 drawer->setPoseVisu(
getName(),
"tcp",
new Pose(gtcp));
693 drawer->setPoseVisu(
getName(),
"tcptarg",
new Pose(gtcptarg));
696 new Vector3(Eigen::Vector3f{gtcp.topRightCorner<3, 1>()}),
697 new Vector3(Eigen::Vector3f{gtcptarg.topRightCorner<3, 1>()}),
702 new Vector3(Eigen::Vector3f{gelb.topRightCorner<3, 1>()}),
703 new Vector3(Eigen::Vector3f{gelbtarg.topRightCorner<3, 1>()}),
709 drawer->removePoseVisu(
getName(),
"tcp");
710 drawer->removePoseVisu(
getName(),
"tcptarg");
711 drawer->removeLineVisu(
getName(),
"tcp2targ");