Template.h
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @package ...
17 * @author Jianfeng Gao ( jianfeng dot gao at kit dot edu )
18 * @date 2025
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
23#pragma once
24
26
32#include <armarx/control/njoint_mp_controller/task_space/ControllerInterface.h>
33
35{
36 // using namespace armarx::control::njoint_controller::task_space;
37 // using namespace armarx::control::common;
38 namespace common = armarx::control::common;
39
40 template <typename TSControllerType, typename MPInterfaceType>
42 public TSControllerType,
43 public common::mp::MPPool,
44 virtual public MPInterfaceType
45 {
46 public:
47 using MPListConfig = common::mp::arondto::MPListConfig;
48
50 const NJointControllerConfigPtr& config,
51 const VirtualRobot::RobotPtr& /*robot*/);
52
53 void updateMPConfig(const ::armarx::aron::data::dto::DictPtr& dto,
54 const Ice::Current& iceCurrent = Ice::emptyCurrent) override;
55 void additionalTask() override;
56 void onPublish(const SensorAndControl& /*sac*/,
57 const DebugDrawerInterfacePrx& /*interface*/,
58 const DebugObserverInterfacePrx& /*debugObs*/) override;
59
60 void rtPreActivateController() override;
61
63 {
65 std::map<std::string, Eigen::Matrix4f> desiredPose;
66 };
67
69
70 private:
71 std::map<common::mp::arondto::MPGroup, bool> groupDeviationFlag_;
72 void updateNonRTTiming();
73 std::map<std::string, bool> manageMPStopsAndGuards();
74 void updateMPInputs(common::mp::MPInputOutput& mpData);
75 void processGroupSafety(common::mp::MPInputOutput& mpData, MPDebugData& buffer);
76 void
77 processMPOutput(common::mp::MPInputOutput& mpData, MPDebugData& buffer, bool rtTargetSafe);
78 };
79
80 ///// -------------------------------- Implementation --------------------------------
81 template <typename TSControllerType, typename MPInterfaceType>
83 const RobotUnitPtr& robotUnit,
84 const NJointControllerConfigPtr& config,
85 const VirtualRobot::RobotPtr& robot) :
86 TSControllerType{robotUnit, config, robot}, common::mp::MPPool{}
87 {
88 auto data = MPDebugData();
89 data.canonicalValue = 1.0;
90 bufferMPToOnPublish.reinitAllBuffers(data);
91 }
92
93 template <typename TSControllerType, typename MPInterfaceType>
94 void
96 {
97 TSControllerType::rtPreActivateController();
98
99 if (not isFinished("all") and (not this->rtGetDesiredPoseSafeStatusOnActivation() or
100 not this->rtGetDesiredPoseSafeStatus()))
101 {
102 ARMARX_WARNING << "Your MPs are not terminated before controller de-/re-activation, "
103 "and the controller is not in a safe status regarding desried pose. "
104 "either your MP has an improper desired pose, or "
105 "you interruped the controller with a different controller. "
106 "No worry, this is just a warning. I will terminate all running MPs.";
107 requestStop("all");
108 }
109 }
110
111 template <typename TSControllerType, typename MPInterfaceType>
112 void
114 const SensorAndControl& sac,
115 const DebugDrawerInterfacePrx& interface,
116 const DebugObserverInterfacePrx& debugObs)
117 {
118 TSControllerType::onPublish(sac, interface, debugObs);
119
120 StringVariantBaseMap datafields;
121 auto& data = bufferMPToOnPublish.getUpToDateReadBuffer();
122 datafields["canonicalValue"] = new Variant(data.canonicalValue);
123
124 auto& desiredPoses = data.desiredPose;
125 for (const auto& [name, pose] : desiredPoses)
126 {
127 common::debugEigenPose(datafields, "mp.desired_pose_" + name, pose);
128 }
129 debugObs->setDebugChannel("MP", datafields);
130 }
131
132 template <typename TSControllerType, typename MPInterfaceType>
133 void
135 const ::armarx::aron::data::dto::DictPtr& dto,
136 const Ice::Current& /*iceCurrent*/)
137 {
138 if (not isFinished("all"))
139 {
141 << "All running MPs will be terminated. This is only a temporal solution, most "
142 "likely your previous mp get into a un-safe status and in your high-level "
143 "application, you are not checking and using these status. A proper way to "
144 "terminate the mps is to get the ctrl proxy and call requestStop('all'). In "
145 "theory, controller should not handle this, but to save your time now, I will "
146 "force to remove the existing mp regardless and create new MPs on your request";
147 requestStop("all");
148 while (not isFinished("all"))
149 {
151 }
152 ARMARX_INFO << "-- all mps stopped";
153 }
154 if (resetMPsV1(dto, this->controllableNodeSets, this->coordinator))
155 {
156 for (auto& [_, arm] : this->limb)
157 {
158 arm->rtFirstRun.store(true);
159 }
160 }
161 {
162 const std::scoped_lock lock(mtx_mps);
163 auto& buffer = bufferMPToOnPublish.getWriteBuffer();
164 buffer.desiredPose.clear();
165 ARMARX_VERBOSE << " -- Debug message: reset MP debug buffer " << mps.size();
166 for (const auto& mp : mps)
167 {
168 if (mp.second.mp->getRole() == "taskspace")
169 {
170 buffer.desiredPose.emplace(mp.second.mp->getNodeSetName(),
171 Eigen::Matrix4f::Identity());
172 ARMARX_VERBOSE << "reset mp debug message: " << mp.second.mp->getNodeSetName()
173 << " to identity";
174 }
175 }
176 bufferMPToOnPublish.reinitAllBuffers(buffer);
177 }
178 }
179
180 template <typename TSControllerType, typename MPInterfaceType>
181 void
183 {
184 const std::lock_guard<std::recursive_mutex> lock(mtx_mps);
185
186 /// 1. Update Status from RT and user configuration update
187 auto [rtTargetSafe, ftSafe] = this->additionalTaskUpdateStatus();
188 if (this->coordinator)
189 {
190 this->coordinator->updateNonRt();
191 }
192
194 /// 2. Update Timing calculations
195 this->updateNonRTTiming();
196
197 /// 3. Check Stop Conditions
198 std::map<std::string, bool> mpRunningStatus = this->manageMPStopsAndGuards();
199
200 /// 4. Prepare Inputs
201 for (auto& mp : mps)
202 {
203 if (mpRunningStatus[mp.second.mp->getMPName()] && !mp.second.mp->isFinished())
204 {
205 this->updateMPInputs(mp.second);
206 }
207 }
208
209 /// 5. Handle RT unsafe logging due to descripancy in desired and current pose
210 if (!rtTargetSafe)
211 {
212 this->handleRTNotSafeInNonRT();
213 }
214
215 /// 6. The MPs will envolve one step forward if it is the first run or rtTargetSafe is true
216 runMPs(rtTargetSafe);
217
218 /// 7. Set mp target to nonRT config data structure
219 auto& buffer = bufferMPToOnPublish.getWriteBuffer();
220
221 groupDeviationFlag_.clear();
222 for (auto& mpWrapper : mps)
223 {
224 auto& mpData = mpWrapper.second;
225
226 // Only process if the MP is marked as running
227 if (mpRunningStatus[mpData.mp->getMPName()])
228 {
229 this->processGroupSafety(mpData, buffer);
230 }
231 }
232
233 for (auto& mpWrapper : mps)
234 {
235 auto& mpData = mpWrapper.second;
236
237 // Only process if the MP is marked as running
238 if (mpRunningStatus[mpData.mp->getMPName()])
239 {
240 this->processMPOutput(mpData, buffer, rtTargetSafe);
241 }
242 }
243
244 /// 8. Handle coordinator and set/commit non RT targets/buffer
245 if (this->coordinator)
246 {
247 this->coordinator->commitNonRt();
248 }
249
250 this->additionalTaskSetTarget();
251 bufferMPToOnPublish.commitWrite();
252 }
253
254 template <typename TSControllerType, typename MPInterfaceType>
255 void
256 TSMPController<TSControllerType, MPInterfaceType>::updateNonRTTiming()
257 {
258 for (auto& [name, arm] : this->limb)
259 {
260 arm->nonRTDeltaT = arm->rtStatusInNonRT.accumulateTime - arm->nonRTAccumulateTime;
261 arm->nonRTAccumulateTime = arm->rtStatusInNonRT.accumulateTime;
262 }
263 if (this->hands)
264 {
265 for (auto& [_, hand] : this->hands->hands)
266 {
267 hand->nonRTDeltaT = hand->rtsInNonRT.accumulateTime - hand->nonRTAccumulateTime;
268 hand->nonRTAccumulateTime = hand->rtsInNonRT.accumulateTime;
269 }
270 }
271 }
272
273 template <typename TSControllerType, typename MPInterfaceType>
274 std::map<std::string, bool>
275 TSMPController<TSControllerType, MPInterfaceType>::manageMPStopsAndGuards()
276 {
277 std::map<std::string, bool> mpRunning;
278
279 // Check global FT safety per limb
280 std::map<std::string, bool> limbStopFlags;
281 for (auto& [name, arm] : this->limb)
282 {
283 // limbStopFlags[name] = not arm->controller.isForceTorqueSafe();
284 limbStopFlags[name] = not arm->controller.ftsensor.ftSafe.load();
285 }
286
287 for (auto& mpWrapper : mps)
288 {
289 auto& mp = mpWrapper.second.mp;
290 const auto mpName = mp->getMPName();
291 const auto nodeSet = mp->getNodeSetName();
292
293 mpRunning[mpName] = mp->isRunning();
294
295 /// 1. Check User Stop Request
296 if (mp->isStopRequested())
297 {
298 mp->stop();
299 ARMARX_INFO << "user requested to stop mp execution at canonical value: "
300 << mp->getCanonicalValue();
301 continue;
302 }
303
304 /// 2. Check Force/Torque Guards configuration
305 bool forceGuardEnabled = false;
306 bool torqueGuardEnabled = false;
307 for (auto& ftGuard : mpConfig.ftGuard)
308 {
309 if (ftGuard.mpName == mpName)
310 {
311 if (ftGuard.force.has_value() &&
312 ftGuard.force.value() >= mp->getCanonicalValue())
313 {
314 forceGuardEnabled = true;
315 }
316 if (ftGuard.torque.has_value() &&
317 ftGuard.torque.value() >= mp->getCanonicalValue())
318 {
319 torqueGuardEnabled = true;
320 }
321 }
322 }
323
324 /// 3. Stop if Global FT Unsafe OR Specific Guard Triggered
325 bool globalFtUnsafe = (limbStopFlags.count(nodeSet) && limbStopFlags.at(nodeSet));
326
327 if (globalFtUnsafe && mp->isRunning() && !mp->isFirstRun() &&
328 ((forceGuardEnabled &&
329 this->limb.at(nodeSet)->controller.ftsensor.isForceGuardEnabled()) ||
330 (torqueGuardEnabled &&
331 this->limb.at(nodeSet)->controller.ftsensor.isTorqueGuardEnabled())))
332 {
333 mp->stop();
334 ARMARX_INFO << "Due to force/torque safe guard, MP " << mpName << " is stopped at "
335 << mp->getCanonicalValue();
336
337 if (this->coordinatorEnabled)
338 {
339 for (auto& mpWrapper2 : mps)
340 {
341 auto& mp2 = mpWrapper2.second.mp;
342 ARMARX_INFO << "Stopped MP " << mp2->getMPName()
343 << " as coordination is enabled";
344 }
345 }
346 else
347 {
348 for (auto& mpWrapper2 : mps)
349 {
350 auto& mp2 = mpWrapper2.second.mp;
351 if (mp->getGroup() == mp2->getGroup())
352 {
353 mp2->stop();
354 ARMARX_INFO << "Stopped MP " << mp2->getMPName() << " part of MP group "
355 << mp->getGroupName();
356 }
357 }
358 }
359 }
360 }
361 return mpRunning;
362 }
363
364 template <typename TSControllerType, typename MPInterfaceType>
365 void
366 TSMPController<TSControllerType, MPInterfaceType>::updateMPInputs(
368 {
369 auto& mp = mpData.mp;
370 const std::string& role = mp->getRole();
371 const std::string& nodeSet = mp->getNodeSetName();
372
374 if (role == "taskspace")
375 {
376 auto& arm = this->limb.at(nodeSet);
377
378 // Handle First Run Logic (Deviation Checks)
379 if (mp->isFirstRun())
380 {
381 ARMARX_VERBOSE << "checking TSMP initial status ...";
382 const std::vector<double> mpStart = mp->getStartVec();
383 const auto mpStartPose = common::dVecToMat4(mpStart);
384
385 const bool deviation = common::detectAndReportPoseDeviationWarning(
386 arm->rtStatusInNonRT.currentPose,
387 mpStartPose,
388 "current pose",
389 "initial start pose",
390 arm->nonRtConfig.safeDistanceMMToGoal,
391 arm->nonRtConfig.safeRotAngleDegreeToGoal,
392 "Additional task for task space MPs: " + mp->getMPName() +
393 " detects that the ");
394
395 if (mp->getStartFromPrevTarget() or deviation)
396 {
397 const bool deviation2 = common::detectAndReportPoseDeviationWarning(
398 arm->rtStatusInNonRT.currentPose,
399 arm->rtStatusInNonRT.desiredPose,
400 "current pose",
401 "desired pose",
402 arm->nonRtConfig.safeDistanceMMToGoal,
403 arm->nonRtConfig.safeRotAngleDegreeToGoal,
404 "Additional task for task space MPs: " + mp->getMPName() +
405 " detects that the ");
406
407 if (mp->getStartFromPrevTarget() and not deviation2)
408 {
409 const common::DVec desiredPoseVec =
410 common::mat4ToDVec(arm->rtStatusInNonRT.desiredPose);
411 ARMARX_INFO << "User requested to start the current TS MP for " << nodeSet
412 << " with previous target pose:\n"
413 << common::dVecToString(desiredPoseVec);
414 mp->validateInitialState(desiredPoseVec);
415 }
416 else
417 {
418 const common::DVec currentPoseVec =
419 common::mat4ToDVec(arm->rtStatusInNonRT.currentPose);
421 << "Deviation from current pose too large, reset TS MP for " << nodeSet
422 << " to current pose:\n" << common::dVecToString(currentPoseVec);
423 mp->validateInitialState(currentPoseVec);
424 }
425 }
426 ARMARX_VERBOSE << "done";
427 }
428
430 std::dynamic_pointer_cast<common::mp::TSMPInput>(mpData.input);
431 in->pose = arm->rtStatusInNonRT.currentPose;
432 in->vel = arm->rtStatusInNonRT.currentTwist;
433 in->deltaT = arm->nonRTDeltaT;
434 return;
435 }
436
437 if (role == "nullspace")
438 {
439 auto& arm = this->limb.at(nodeSet);
441 std::dynamic_pointer_cast<common::mp::JSMPInput>(mpData.input);
442 ARMARX_CHECK_EQUAL(arm->rtStatusInNonRT.nDoF,
443 arm->rtStatusInNonRT.jointPosition.size());
444 in->angleRadian = arm->rtStatusInNonRT.jointPosition;
445 in->angularVel = arm->rtStatusInNonRT.qvelFiltered;
446 in->deltaT = arm->nonRTDeltaT;
447 return;
448 }
449
450 if (role == "hand")
451 {
452 auto& hand = this->hands->hands.at(nodeSet);
454 std::dynamic_pointer_cast<common::mp::JSMPInput>(mpData.input);
455 if (hand->targetNonRT.jointPosition.has_value())
456 {
457 in->angleRadian = hand->targetNonRT.jointPosition.value();
458 in->deltaT = hand->nonRTDeltaT;
459 // ARMARX_VERBOSE << "__ " << VAROUT(in->angleRadian) << VAROUT(in->deltaT);
460 }
461 return;
462 }
463
464 if (role == "object")
465 {
466 if (not this->coordinator)
467 {
469 << "when using the object for MP, the coordinator must be first instantiated";
470 return;
471 }
472 const std::scoped_lock lock_vo_non_rt(this->coordinator->mtx_data_non_rt);
474 std::dynamic_pointer_cast<common::mp::TSMPInput>(mpData.input);
475 in->pose = this->coordinator->dataNonRt.currentPose;
476 in->vel = this->coordinator->dataNonRt.currentVel;
477 in->deltaT = this->coordinator->dataNonRt.deltaT;
478 return;
479 }
480
481 ARMARX_WARNING << "Your mp role " << role << " is not supported";
482 }
483
484 template <typename TSControllerType, typename MPInterfaceType>
485 void
486 TSMPController<TSControllerType, MPInterfaceType>::processGroupSafety(
487 common::mp::MPInputOutput& mpData, // Pass the specific MP data structure
488 MPDebugData& buffer)
489 {
490 auto& mp = mpData.mp;
491 /// --------------------------------------------------------------------------------
492 /// A. Check/Trigger Force-Torque Safety Guards for this MP
493 /// --------------------------------------------------------------------------------
494 for (auto& ftGuard : mpConfig.ftGuard)
495 {
496 if (ftGuard.mpName == mp->getMPName())
497 {
498 bool const forceGuard =
499 (ftGuard.force.has_value() && ftGuard.force.value() >= mp->getCanonicalValue());
500 bool const torqueGuard = (ftGuard.torque.has_value() &&
501 ftGuard.torque.value() >= mp->getCanonicalValue());
502
503 auto& arm = this->limb.at(mp->getNodeSetName());
504
505 bool const resetForce =
506 not arm->controller.ftsensor.isForceGuardEnabled() and forceGuard;
507 bool const resetTorque =
508 not arm->controller.ftsensor.isTorqueGuardEnabled() and torqueGuard;
509 if (resetForce or resetTorque)
510 {
511 ARMARX_INFO << "Triggering force torque safety guard for "
512 << arm->kinematicChainName << " at can value "
513 << mp->getCanonicalValue();
514 }
515
516 arm->nonRtConfig.ftConfig.enableSafeGuardForce = forceGuard;
517 arm->nonRtConfig.ftConfig.enableSafeGuardTorque = torqueGuard;
518 arm->controller.ftsensor.enableSafeGuard(resetForce, resetTorque);
519 }
520 }
521
522 /// --------------------------------------------------------------------------------
523 /// B. Fetch MP desired pose/values and set to the buffer going to RT thread
524 /// --------------------------------------------------------------------------------
525 const std::string& role = mp->getRole();
526 const std::string& nodeSetName = mp->getNodeSetName();
527
528 if (role == "taskspace")
529 {
530 buffer.canonicalValue = mp->getCanonicalValue();
531 auto& arm = this->limb.at(nodeSetName);
532 auto out = std::dynamic_pointer_cast<common::mp::TSMPOutput>(mpData.output);
533
535 arm->rtStatusInNonRT.currentPose,
536 out->pose,
537 "current pose",
538 "desired pose",
539 arm->nonRtConfig.safeDistanceMMToGoal,
540 arm->nonRtConfig.safeRotAngleDegreeToGoal,
541 "Additional task for task space MPs: " + mp->getMPName() + " detects that the ");
542 groupDeviationFlag_.emplace(mp->getGroup(), flag);
543
544 arm->nonRtConfig.desiredPose = out->pose;
545 arm->nonRtConfig.desiredTwist = out->vel;
546 buffer.desiredPose.at(nodeSetName) = out->pose;
547 }
548 }
549
550 template <typename TSControllerType, typename MPInterfaceType>
551 void
552 TSMPController<TSControllerType, MPInterfaceType>::processMPOutput(
553 common::mp::MPInputOutput& mpData, // Pass the specific MP data structure
554 MPDebugData& buffer,
555 bool rtTargetSafe)
556 {
557 auto& mp = mpData.mp;
558 bool deviationFlag = true;
559 if (groupDeviationFlag_.count(mp->getGroup()))
560 {
561 deviationFlag = groupDeviationFlag_.at(mp->getGroup());
562 }
563 const std::string& role = mp->getRole();
564 const std::string& nodeSetName = mp->getNodeSetName();
565
566 if (role == "object")
567 {
568 buffer.canonicalValue = mp->getCanonicalValue();
569 if (this->coordinator)
570 {
571 auto out = std::dynamic_pointer_cast<common::mp::TSMPOutput>(mpData.output);
572 this->coordinator->cfgInNonRt.desiredPose = out->pose;
573 }
574 }
575 else if (role == "nullspace")
576 {
577 auto& arm = this->limb.at(nodeSetName);
578 auto out = std::dynamic_pointer_cast<common::mp::JSMPOutput>(mpData.output);
579 ARMARX_CHECK_EQUAL(arm->rtStatusInNonRT.nDoF, out->angleRadian.size());
580 if (not deviationFlag)
581 {
582 arm->nonRtConfig.desiredNullspaceJointAngles.value() = out->angleRadian;
583 }
584 }
585 else if (role == "hand")
586 {
587 auto& hand = this->hands->hands.at(nodeSetName);
588 auto out = std::dynamic_pointer_cast<common::mp::JSMPOutput>(mpData.output);
589 ARMARX_CHECK_EQUAL(hand->targetNonRT.jointPosition.value().size(),
590 out->angleRadian.size());
591 if (not deviationFlag)
592 {
593 hand->targetNonRT.jointPosition.value() = out->angleRadian;
594 }
595 // ARMARX_VERBOSE << "__ mp set target " << nodeSetName << ": "
596 // << VAROUT(mp->getCanonicalValue()) << VAROUT(out->angleRadian);
597 }
598
599 /// ----------------------------------------------------------------------------------
600 /// C. Upon MP stop, reset the nonRTConfig and User buffer, so that controller behaves
601 /// Like a normal NJointController without MP.
602 /// This is only a temporal solution, it has to be re-considered, e.g.,
603 /// - 1) whether to stop the whole group (task space/nullspace/hand) at the same time
604 /// - 2) all allow user to stop only partially;
605 /// E.g., In dishwasher skill, you want to trigger the stop at last 10%, but still
606 /// want to execute the rest of the finger motions to close and grasp the handle.
607 /// Otherwise, you will need to add a grasp motion after the skill for 1)
608 /// ----------------------------------------------------------------------------------
609 if (mp->isFinished())
610 {
611 ARMARX_VERBOSE << "-- reset buffer for nonRtConfig of " << mp->getMPName();
612
613 // Reset all limbs to safe state or existing RT state
614 for (auto& [name, arm] : this->limb)
615 {
616 // If RT was unsafe OR the MP calculated an unsafe deviation
617 if (!rtTargetSafe || deviationFlag) // Note: Logic preserved from your update
618 {
619 ARMARX_VERBOSE << "-- discard the last MP desired pose, use the existing RT "
620 "desired pose for "
621 << arm->kinematicChainName << ": \n"
622 << arm->rtStatusInNonRT.desiredPose;
623 arm->nonRtConfig.desiredPose = arm->rtStatusInNonRT.desiredPose;
624 }
625 arm->bufferConfigUserToNonRt.reinitAllBuffers(arm->nonRtConfig);
626 }
627
628 // Sync user config
629 for (auto& [name, arm] : this->limb)
630 {
631 this->userConfig.limbs.at(name) = arm->nonRtConfig;
632 }
633
634 // Sync hands
635 if (this->hands)
636 {
637 this->hands->reinitBuffer(this->userConfig.hands);
638 }
639
640 // Sync coordinator
641 if (this->coordinator)
642 {
643 this->coordinator->resetBufferUserCfgAfterMP();
644 }
645 }
646 }
647} // namespace armarx::control::njoint_mp_controller::task_space
648
649//#include "Template_impl.h"
static void WaitFor(const Duration &duration)
Wait for a certain duration on the virtual clock.
Definition Clock.cpp:99
static Duration SecondsDouble(double seconds)
Constructs a duration in seconds.
Definition Duration.cpp:78
A simple triple buffer for lockfree comunication between a single writer and a single reader.
The Variant class is described here: Variants.
Definition Variant.h:224
bool resetMPsV1(const ::armarx::aron::data::dto::DictPtr &dto, const std::map< std::string, VirtualRobot::RobotNodeSetPtr > &rnsMap, const std::shared_ptr< common::coordination::Coordination > &coordinator)
Definition MPPool.cpp:604
std::recursive_mutex mtx_mps
Definition MPPool.h:147
bool isFinished(const std::string &mpName="all", const Ice::Current &iceCurrent=Ice::emptyCurrent) override
Definition MPPool.cpp:386
std::map< std::string, MPInputOutput > mps
Definition MPPool.h:146
void requestStop(const std::string &mpName="all", const Ice::Current &iceCurrent=Ice::emptyCurrent) override
Definition MPPool.cpp:237
void onPublish(const SensorAndControl &, const DebugDrawerInterfacePrx &, const DebugObserverInterfacePrx &) override
Definition Template.h:113
TSMPController(const RobotUnitPtr &robotUnit, const NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &)
Definition Template.h:82
void updateMPConfig(const ::armarx::aron::data::dto::DictPtr &dto, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
Definition Template.h:134
#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_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
std::shared_ptr< class Robot > RobotPtr
Definition Bus.h:19
This file is part of ArmarX.
std::shared_ptr< TSMPInput > TSMPInputPtr
Definition TSMP.h:46
std::shared_ptr< JSMPInput > JSMPInputPtr
Definition JSMP.h:47
This file is part of ArmarX.
bool detectAndReportPoseDeviationWarning(const Eigen::Matrix4f &pose1, const Eigen::Matrix4f &pose2, const std::string &namePose1, const std::string &namePose2, float positionThrMM, float angleThrDeg, const std::string &who)
Definition utils.cpp:773
Eigen::Matrix4f dVecToMat4(const DVec &dvec)
create Eigen:Matrix4f from 7D double vector.
Definition utils.cpp:325
void debugEigenPose(StringVariantBaseMap &datafields, const std::string &name, Eigen::Matrix4f pose)
Definition utils.cpp:140
std::vector< double > DVec
Definition utils.h:47
DVec mat4ToDVec(const Eigen::Matrix4f &mat)
convert Eigen:Matrix4f to 7D double vector.
Definition utils.cpp:359
std::string dVecToString(const DVec &dvec)
Definition utils.cpp:408
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugObserverInterface > DebugObserverInterfacePrx
std::map< std::string, VariantBasePtr > StringVariantBaseMap
IceUtil::Handle< class RobotUnit > RobotUnitPtr
Definition FTSensor.h:34
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugDrawerInterface > DebugDrawerInterfacePrx
detail::ControlThreadOutputBufferEntry SensorAndControl
#define ARMARX_TRACE
Definition trace.h:77