NJointCartesianWaypointController.cpp
Go to the documentation of this file.
2
3#include <iomanip>
4
5#include <VirtualRobot/Nodes/RobotNode.h>
6#include <VirtualRobot/Robot.h>
7
9
16#include <RobotAPI/interface/visualization/DebugDrawerInterface.h>
17
18namespace armarx
19{
20 std::ostream&
21 operator<<(std::ostream& out, const NJointCartesianWaypointControllerRuntimeConfig& cfg)
22 {
23 out << "maxPositionAcceleration " << cfg.wpCfg.maxPositionAcceleration << '\n'
24 << "maxOrientationAcceleration " << cfg.wpCfg.maxOrientationAcceleration << '\n'
25 << "maxNullspaceAcceleration " << cfg.wpCfg.maxNullspaceAcceleration << '\n'
26
27 << "kpJointLimitAvoidance " << cfg.wpCfg.kpJointLimitAvoidance << '\n'
28 << "jointLimitAvoidanceScale " << cfg.wpCfg.jointLimitAvoidanceScale << '\n'
29
30 << "thresholdPositionNear " << cfg.wpCfg.thresholdPositionNear << '\n'
31 << "thresholdPositionReached " << cfg.wpCfg.thresholdPositionReached << '\n'
32 << "maxPosVel " << cfg.wpCfg.maxPosVel << '\n'
33 << "kpPos " << cfg.wpCfg.kpPos << '\n'
34
35 << "thresholdOrientationNear " << cfg.wpCfg.thresholdOrientationNear << '\n'
36 << "thresholdOrientationReached " << cfg.wpCfg.thresholdOrientationReached << '\n'
37 << "maxOriVel " << cfg.wpCfg.maxOriVel << '\n'
38 << "kpOri " << cfg.wpCfg.kpOri << '\n'
39
40 << "forceThreshold " << cfg.forceThreshold << '\n';
41 return out;
42 }
43
44 NJointControllerRegistration<NJointCartesianWaypointController>
46 "NJointCartesianWaypointController");
47
48 std::string
50 {
51 return "NJointCartesianWaypointController";
52 }
53
55 RobotUnit*,
56 const NJointCartesianWaypointControllerConfigPtr& config,
58 {
60
61 //robot
62 {
63 _rtRobot = useSynchronizedRtRobot();
64 ARMARX_CHECK_NOT_NULL(_rtRobot);
65
66 _rtRns = _rtRobot->getRobotNodeSet(config->rns);
67 ARMARX_CHECK_NOT_NULL(_rtRns) << "No rns " << config->rns;
68 _rtTcp = _rtRns->getTCP();
69 ARMARX_CHECK_NOT_NULL(_rtTcp) << "No tcp in rns " << config->rns;
70
71 _rtRobotRoot = _rtRobot->getRootNode();
72 }
73
74 //sensor
75 {
76 if (!config->ftName.empty())
77 {
78 const auto svalFT = useSensorValue<SensorValueForceTorque>(config->ftName);
79 ARMARX_CHECK_NOT_NULL(svalFT) << "No sensor value of name " << config->ftName;
80 _rtForceSensor = &(svalFT->force);
81 _rtTorqueSensor = &(svalFT->force);
82
83 const auto sdev = peekSensorDevice(config->ftName);
85
86 const auto reportFrameName = sdev->getReportingFrame();
87 ARMARX_CHECK_EXPRESSION(!reportFrameName.empty())
88 << VAROUT(sdev->getReportingFrame());
89
90 _rtFT = _rtRobot->getRobotNode(reportFrameName);
92 << "No sensor report frame '" << reportFrameName << "' in robot";
93 }
94 }
95 //ctrl
96 {
97 _rtJointVelocityFeedbackBuffer =
98 Eigen::VectorXf::Zero(static_cast<int>(_rtRns->getSize()));
99
100 VirtualRobot::RobotNodePtr referenceFrame = nullptr;
101 if (!config->referenceFrameName.empty())
102 {
103 referenceFrame = _rtRobot->getRobotNode(config->referenceFrameName);
104 ARMARX_CHECK_NOT_NULL(referenceFrame)
105 << "No node with name '" << config->referenceFrameName
106 << "' for referenceFrame in robot";
107 }
108
109 _rtWpController = std::make_unique<CartesianWaypointController>(
110 _rtRns,
111 _rtJointVelocityFeedbackBuffer,
112 config->runCfg.wpCfg.maxPositionAcceleration,
113 config->runCfg.wpCfg.maxOrientationAcceleration,
114 config->runCfg.wpCfg.maxNullspaceAcceleration,
115 nullptr,
116 referenceFrame);
117
118 _rtWpController->setConfig({});
119
120 for (size_t i = 0; i < _rtRns->getSize(); ++i)
121 {
122 std::string jointName = _rtRns->getNode(i)->getName();
124 jointName, ControlModes::Velocity1DoF);
128
129 _rtVelTargets.emplace_back(&(ct->velocity));
130 _rtVelSensors.emplace_back(&(sv->velocity));
131 }
132 }
133 //visu
134 {
135 _tripRt2NonRtRobotGP.getWriteBuffer().setIdentity();
136 _tripRt2NonRtRobotGP.commitWrite();
137 }
138 }
139
140 void
142 {
143 _publishIsAtTarget = false;
144 _rtForceOffset = Eigen::Vector3f::Zero();
145
146 _publishErrorPos = 0;
147 _publishErrorOri = 0;
148 _publishErrorPosMax = 0;
149 _publishErrorOriMax = 0;
150 _publishForceThreshold = _rtForceThreshold;
151
152 //feedback
153 {
154#pragma GCC diagnostic push
155#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
156 for (std::size_t idx = 0; idx < _rtVelSensors.size(); ++idx)
157 {
158 const float* ptr = _rtVelSensors[idx];
159 _rtJointVelocityFeedbackBuffer(idx) = *ptr;
160 }
161 _rtWpController->setCurrentJointVelocity(_rtJointVelocityFeedbackBuffer);
162#pragma GCC diagnostic pop
163 }
164 }
165
166 void
167 NJointCartesianWaypointController::rtRun(const IceUtil::Time& sensorValuesTimestamp,
168 const IceUtil::Time& timeSinceLastIteration)
169 {
170 auto& rt2nonrtBuf = _tripRt2NonRt.getWriteBuffer();
171
172 if (_tripBufWpCtrl.updateReadBuffer())
173 {
174 ARMARX_RT_LOGF_IMPORTANT("updates in tripple buffer");
175 auto& r = _tripBufWpCtrl._getNonConstReadBuffer();
176 if (r.cfgUpdated)
177 {
178 r.cfgUpdated = false;
179 _rtWpController->setConfig(r.cfg.wpCfg);
180 _rtForceThreshold = r.cfg.forceThreshold;
181 _publishForceThreshold = _rtForceThreshold;
182 _rtOptimizeNullspaceIfTargetWasReached = r.cfg.optimizeNullspaceIfTargetWasReached;
183 _rtForceThresholdInRobotRootZ = r.cfg.forceThresholdInRobotRootZ;
184 _publishForceThresholdInRobotRootZ = r.cfg.forceThresholdInRobotRootZ;
185 ARMARX_RT_LOGF_IMPORTANT("updated the controller config");
186 }
187 if (r.wpsUpdated)
188 {
189 _rtStopConditionReached = false;
190 _publishIsAtTarget = false;
191 r.wpsUpdated = false;
192 ARMARX_RT_LOGF_IMPORTANT("updated waypoints (# = %u)", r.wps.size());
193 _publishWpsNum = r.wps.size();
194 _rtHasWps = !r.wps.empty();
195 _rtWpController->swapWaypoints(r.wps);
196 if (r.cfg.skipToClosestWaypoint)
197 {
198 _rtWpController->skipToClosestWaypoint(r.skipRad2mmFactor);
199 }
200 }
201 _publishIsAtForceLimit = false;
202 }
203 //run
204 bool reachedTarget = false;
205 bool reachedFtLimit = false;
206
207 if (_rtForceSensor)
208 {
209 const Eigen::Vector3f ftInRoot =
210 _rtFT->getTransformationTo(_rtRobotRoot).topLeftCorner<3, 3>().transpose() *
211 (*_rtForceSensor);
212 rt2nonrtBuf.ft.force = ftInRoot;
213 rt2nonrtBuf.ft.torque = *_rtTorqueSensor;
214 rt2nonrtBuf.ft.timestampInUs = sensorValuesTimestamp.toMicroSeconds();
215 rt2nonrtBuf.ftInRoot = _rtFT->getPoseInRootFrame();
216
217 Eigen::Vector3f ftVal = ftInRoot;
218 if (_rtForceThresholdInRobotRootZ)
219 {
220 ftVal(0) = 0;
221 ftVal(1) = 0;
222 }
223 if (_setFTOffset)
224 {
225 _rtForceOffset = ftVal;
226 _setFTOffset = false;
227 _publishIsAtForceLimit = false;
228 }
229 rt2nonrtBuf.ftUsed = ftVal;
230
231 const float currentForce = std::abs(ftVal.norm() - _rtForceOffset.norm());
232
233 reachedFtLimit = (_rtForceThreshold >= 0) && currentForce > _rtForceThreshold;
234 _publishForceCurrent = currentForce;
235 _publishIsAtForceLimit = _publishIsAtForceLimit || reachedFtLimit;
236 }
237
238 _publishWpsCur = _rtHasWps ? _rtWpController->currentWaypointIndex : 0;
239
240 rt2nonrtBuf.rootPose = _rtRobot->getGlobalPose();
241 rt2nonrtBuf.tcp = _rtTcp->getPoseInRootFrame();
242 if (_rtHasWps)
243 {
244 const float errorPos = _rtWpController->getPositionError();
245 const float errorOri = _rtWpController->getOrientationError();
246
247 _publishErrorPos = errorPos;
248 _publishErrorOri = errorOri;
249 if (!_rtWpController->isLastWaypoint())
250 {
251 _publishErrorPosMax = _rtWpController->thresholdPositionNear;
252 _publishErrorOriMax = _rtWpController->thresholdOrientationNear;
253 }
254 else
255 {
256 _publishErrorPosMax = _rtWpController->thresholdPositionReached;
257 _publishErrorOriMax = _rtWpController->thresholdOrientationReached;
258 reachedTarget = (errorPos < _rtWpController->thresholdPositionReached) &&
259 (errorOri < _rtWpController->thresholdOrientationReached);
260 }
261 rt2nonrtBuf.tcpTarg = _rtWpController->getCurrentTarget();
262 }
263 else
264 {
265 rt2nonrtBuf.tcpTarg = rt2nonrtBuf.tcp;
266 }
267 _rtStopConditionReached = _rtStopConditionReached || reachedFtLimit ||
268 (reachedTarget && !_rtOptimizeNullspaceIfTargetWasReached);
269 _publishIsAtTarget = _publishIsAtTarget || reachedTarget;
270 if (!_rtHasWps || _rtStopConditionReached)
271 {
272 setNullVelocity();
273 }
274 else
275 {
276 const Eigen::VectorXf& goal =
277 _rtWpController->calculate(timeSinceLastIteration.toSecondsDouble());
278 //write targets
279 ARMARX_CHECK_EQUAL(static_cast<std::size_t>(goal.size()), _rtVelTargets.size());
280 for (std::size_t idx = 0; idx < _rtVelTargets.size(); ++idx)
281 {
282 float* ptr = _rtVelTargets[idx];
283 *ptr = goal(idx);
284 }
285 }
286 _tripRt2NonRt.commitWrite();
287
288 _tripRt2NonRtRobotGP.getWriteBuffer() = _rtRobot->getGlobalPose();
289 _tripRt2NonRtRobotGP.commitWrite();
290 }
291
292 void
296
297 bool
299 {
300 return _publishIsAtTarget;
301 }
302
303 void
305 const NJointCartesianWaypointControllerRuntimeConfig& cfg,
306 const Ice::Current&)
307 {
308 std::lock_guard g{_tripBufWpCtrlMut};
309 auto& w = _tripBufWpCtrl.getWriteBuffer();
310 w.cfgUpdated = true;
311 w.cfg = cfg;
312 _tripBufWpCtrl.commitWrite();
313 ARMARX_IMPORTANT << "set new config\n" << cfg;
314 }
315
316 void
317 NJointCartesianWaypointController::setWaypoints(const std::vector<Eigen::Matrix4f>& wps,
318 const Ice::Current&)
319 {
320 std::lock_guard g{_tripBufWpCtrlMut};
321 auto& w = _tripBufWpCtrl.getWriteBuffer();
322 w.wpsUpdated = true;
323 w.wps = wps;
324 _tripBufWpCtrl.commitWrite();
325 ARMARX_IMPORTANT << "set new waypoints\n" << wps;
326 }
327
328 void
329 NJointCartesianWaypointController::setWaypoint(const Eigen::Matrix4f& wp, const Ice::Current&)
330 {
331 std::lock_guard g{_tripBufWpCtrlMut};
332 auto& w = _tripBufWpCtrl.getWriteBuffer();
333 w.wpsUpdated = true;
334 w.wps.clear();
335 w.wps.emplace_back(wp);
336 _tripBufWpCtrl.commitWrite();
337 ARMARX_IMPORTANT << "set new waypoint\n" << wp;
338 }
339
340 void
341 NJointCartesianWaypointController::setWaypointAx(const Ice::FloatSeq& data, const Ice::Current&)
342 {
343 Eigen::Matrix4f wp(data.data());
344 std::lock_guard g{_tripBufWpCtrlMut};
345 auto& w = _tripBufWpCtrl.getWriteBuffer();
346 w.wpsUpdated = true;
347 w.wps.clear();
348 w.wps.emplace_back(wp);
349 _tripBufWpCtrl.commitWrite();
350 ARMARX_IMPORTANT << "set new waypoint\n" << wp;
351 }
352
353 void
355 const NJointCartesianWaypointControllerRuntimeConfig& cfg,
356 const std::vector<Eigen::Matrix4f>& wps,
357 const Ice::Current&)
358 {
359 std::lock_guard g{_tripBufWpCtrlMut};
360 auto& w = _tripBufWpCtrl.getWriteBuffer();
361 w.wpsUpdated = true;
362 w.cfgUpdated = true;
363 w.cfg = cfg;
364 w.wps = wps;
365 _tripBufWpCtrl.commitWrite();
366 ARMARX_IMPORTANT << "set new config\n" << cfg << " and new waypoints\n" << wps;
367 }
368
369 void
371 const NJointCartesianWaypointControllerRuntimeConfig& cfg,
372 const Eigen::Matrix4f& wp,
373 const Ice::Current&)
374 {
375 std::lock_guard g{_tripBufWpCtrlMut};
376 auto& w = _tripBufWpCtrl.getWriteBuffer();
377 w.wpsUpdated = true;
378 w.cfgUpdated = true;
379 w.cfg = cfg;
380 w.wps.clear();
381 w.wps.emplace_back(wp);
382 _tripBufWpCtrl.commitWrite();
383 ARMARX_IMPORTANT << "set new config\n" << cfg << "and a new waypoint\n" << wp;
384 }
385
386 void
387 NJointCartesianWaypointController::setNullVelocity()
388 {
389 for (auto ptr : _rtVelTargets)
390 {
391 *ptr = 0;
392 }
393 }
394
395 bool
397 {
398 ARMARX_CHECK_NOT_NULL(_rtForceSensor);
399 return _publishIsAtForceLimit;
400 }
401
402 FTSensorValue
404 {
405 ARMARX_CHECK_NOT_NULL(_rtForceSensor);
406 std::lock_guard g{_tripRt2NonRtMutex};
407 return _tripRt2NonRt.getUpToDateReadBuffer().ft;
408 }
409
410 void
412 {
413 ARMARX_CHECK_NOT_NULL(_rtForceSensor);
414 _setFTOffset = true;
415 }
416
417 void
419 const Ice::Current&)
420 {
421 ; // No longer used ...
422 }
423
424 void
426 {
427 ; // No longer used ...
428 }
429
430 void
432 {
433 std::lock_guard g{_tripBufWpCtrlMut};
434 auto& w = _tripBufWpCtrl.getWriteBuffer();
435 w.wpsUpdated = true;
436 w.cfgUpdated = false;
437 w.wps.clear();
438 _tripBufWpCtrl.commitWrite();
439 ARMARX_IMPORTANT << "stop movement by setting 0 waypoints";
440 }
441
442 void
444 const DebugDrawerInterfacePrx& drawer,
445 const DebugObserverInterfacePrx& obs)
446 {
447 const std::size_t wpsNum = _publishWpsNum;
448 const std::size_t wpsCur = wpsNum ? _publishWpsCur + 1 : 0;
449
450 const float errorPos = _publishErrorPos;
451 const float errorOri = _publishErrorOri;
452 const float errorPosMax = _publishErrorPosMax;
453 const float errorOriMax = _publishErrorOriMax;
454 const float forceThreshold = _publishForceThreshold;
455 const float forceCurrent = _publishForceCurrent;
456
457 {
458 StringVariantBaseMap datafields;
459 datafields["WpNum"] = new Variant(static_cast<int>(wpsNum));
460 datafields["WpCur"] = new Variant(static_cast<int>(wpsCur));
461
462 datafields["errorPos"] = new Variant(errorPos);
463 datafields["errorOri"] = new Variant(errorOri);
464 datafields["errorPosMax"] = new Variant(errorPosMax);
465 datafields["errorOriMax"] = new Variant(errorOriMax);
466
467 datafields["forceThreshold"] = new Variant(forceThreshold);
468 datafields["forceCurrent"] = new Variant(forceCurrent);
469
470 obs->setDebugChannel(getInstanceName(), datafields);
471 }
472
473 ARMARX_INFO << deactivateSpam(1) << std::setprecision(4) << "At waypoint " << wpsCur
474 << " / " << wpsNum << " (last " << _publishIsAtTarget << ", ft limit "
475 << _publishIsAtForceLimit << ", perror " << errorPos << " / " << errorPosMax
476 << ", oerror " << errorOri << " / " << errorOriMax << ')';
477
478 {
479 std::lock_guard g{_tripRt2NonRtMutex};
480 const auto& buf = _tripRt2NonRt.getUpToDateReadBuffer();
481
482 const Eigen::Matrix4f fakeGP = _tripRt2NonRtRobotGP.getUpToDateReadBuffer();
483 const Eigen::Matrix4f gp = std::isfinite(fakeGP(0, 0)) ? fakeGP : buf.rootPose;
484
485 if (buf.tcp != buf.tcpTarg)
486 {
487 const Eigen::Matrix4f gtcp = gp * buf.tcp;
488 const Eigen::Matrix4f gtcptarg = gp * buf.tcpTarg;
489 drawer->setPoseVisu(getName(), "tcp", new Pose(gtcp));
490 drawer->setPoseVisu(getName(), "tcptarg", new Pose(gtcptarg));
491 drawer->setLineVisu(getName(),
492 "tcp2targ",
493 new Vector3(Eigen::Vector3f{gtcp.topRightCorner<3, 1>()}),
494 new Vector3(Eigen::Vector3f{gtcptarg.topRightCorner<3, 1>()}),
495 3,
496 {0, 0, 1, 1});
497 }
498 else
499 {
500 drawer->removePoseVisu(getName(), "tcp");
501 drawer->removePoseVisu(getName(), "tcptarg");
502 drawer->removeLineVisu(getName(), "tcp2targ");
503 }
504 if (_rtForceSensor)
505 {
506 const Eigen::Matrix4f gft = gp * buf.ftInRoot;
507 const Vector3Ptr pos = new Vector3{Eigen::Vector3f{gft.topRightCorner<3, 1>()}};
508 drawer->setArrowVisu(getName(),
509 "force",
510 pos,
511 new Vector3{buf.ft.force.normalized()},
512 {1, 1, 0, 1},
513 buf.ft.force.norm(),
514 2.5);
515 drawer->setArrowVisu(getName(),
516 "forceUsed",
517 pos,
518 new Vector3{buf.ftUsed.normalized()},
519 {1, 0.5, 0, 1},
520 buf.ftUsed.norm(),
521 2.5);
522 }
523 }
524 }
525
526 int
528 {
529 return _publishWpsCur;
530 }
531} // namespace armarx
#define ARMARX_RT_LOGF_IMPORTANT(...)
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition Logging.cpp:75
#define VAROUT(x)
std::string getName() const
Retrieve name of object.
std::string getClassName(const Ice::Current &=Ice::emptyCurrent) const override
void resetVisualizationRobotGlobalPose(const Ice::Current &=Ice::emptyCurrent) override
void onPublish(const SensorAndControl &, const DebugDrawerInterfacePrx &, const DebugObserverInterfacePrx &) override
int getCurrentWaypointIndex(const Ice::Current &=Ice::emptyCurrent) override
bool hasReachedForceLimit(const Ice::Current &=Ice::emptyCurrent) override
void setWaypointAx(const Ice::FloatSeq &data, const Ice::Current &=Ice::emptyCurrent) override
void setWaypoint(const Eigen::Matrix4f &wp, const Ice::Current &=Ice::emptyCurrent) override
FTSensorValue getFTSensorValue(const Ice::Current &=Ice::emptyCurrent) override
bool hasReachedTarget(const Ice::Current &=Ice::emptyCurrent) override
void stopMovement(const Ice::Current &=Ice::emptyCurrent) override
void setConfigAndWaypoints(const NJointCartesianWaypointControllerRuntimeConfig &cfg, const std::vector< Eigen::Matrix4f > &wps, const Ice::Current &=Ice::emptyCurrent) override
void rtPostDeactivateController() override
This function is called after the controller is deactivated.
void rtRun(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration) override
TODO make protected and use attorneys.
void setConfigAndWaypoint(const NJointCartesianWaypointControllerRuntimeConfig &cfg, const Eigen::Matrix4f &wp, const Ice::Current &=Ice::emptyCurrent) override
void setConfig(const NJointCartesianWaypointControllerRuntimeConfig &cfg, const Ice::Current &=Ice::emptyCurrent) override
void setVisualizationRobotGlobalPose(const Eigen::Matrix4f &p, const Ice::Current &=Ice::emptyCurrent) override
NJointCartesianWaypointController(RobotUnit *robotUnit, const NJointCartesianWaypointControllerConfigPtr &config, const VirtualRobot::RobotPtr &)
void setWaypoints(const std::vector< Eigen::Matrix4f > &wps, const Ice::Current &=Ice::emptyCurrent) override
void setCurrentFTAsOffset(const Ice::Current &=Ice::emptyCurrent) override
void rtPreActivateController() override
This function is called before the controller is activated.
const SensorValueBase * useSensorValue(const std::string &sensorDeviceName) const
Get a const ptr to the given SensorDevice's SensorValue.
const VirtualRobot::RobotPtr & useSynchronizedRtRobot(bool updateCollisionModel=false)
Requests a VirtualRobot for use in rtRun *.
std::string getInstanceName(const Ice::Current &=Ice::emptyCurrent) const final override
ConstSensorDevicePtr peekSensorDevice(const std::string &deviceName) const
Get a const ptr to the given SensorDevice.
ControlTargetBase * useControlTarget(const std::string &deviceName, const std::string &controlMode)
Declares to calculate the ControlTarget for the given ControlDevice in the given ControlMode when rtR...
The Pose class.
Definition Pose.h:243
The RobotUnit class manages a robot and its controllers.
Definition RobotUnit.h:192
The Variant class is described here: Variants.
Definition Variant.h:224
The Vector3 class.
Definition Pose.h:113
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
Definition Logging.h:190
std::shared_ptr< class Robot > RobotPtr
Definition Bus.h:19
This file offers overloads of toIce() and fromIce() functions for STL container types.
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugObserverInterface > DebugObserverInterfacePrx
std::ostream & operator<<(std::ostream &os, const PythonApplicationManager::Paths &paths)
IceInternal::Handle< Vector3 > Vector3Ptr
Definition Pose.h:165
std::map< std::string, VariantBasePtr > StringVariantBaseMap
NJointControllerRegistration< NJointCartesianWaypointController > registrationControllerNJointCartesianWaypointController("NJointCartesianWaypointController")
std::vector< std::vector< T > > transpose(const std::vector< std::vector< T > > &src, Thrower thrower)
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugDrawerInterface > DebugDrawerInterfacePrx
detail::ControlThreadOutputBufferEntry SensorAndControl
bool isfinite(const std::vector< T, Ts... > &v)
Definition algorithm.h:366