RobotUnitModuleControllerManagement.cpp
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 RobotAPI::ArmarXObjects::RobotUnit
17 * @author Raphael Grimm ( raphael dot grimm at kit dot edu )
18 * @date 2018
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
23
25
30
37
39{
40 template <class Cont>
41 static Ice::StringSeq
42 GetNonNullNames(const Cont& c)
43 {
44 Ice::StringSeq result;
45 result.reserve(c.size());
46 for (const auto& e : c)
47 {
48 if (e)
49 {
50 result.emplace_back(e->getName());
51 }
52 }
53 return result;
54 }
55
56 /**
57 * \brief This class allows minimal access to private members of \ref NJointControllerBase in a sane fashion for \ref ControllerManagement.
58 * \warning !! DO NOT ADD ANYTHING IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
59 */
61 {
63
64 static void
65 SetRequested(const NJointControllerBasePtr& nJointCtrl, bool requested)
66 {
67 nJointCtrl->isRequested = requested;
68 }
69 };
70} // namespace armarx::RobotUnitModule
71
73{
74 Ice::StringSeq
76 {
78 throwIfInControlThread(__PRETTY_FUNCTION__);
79 return GetNonNullNames(_module<ControlThreadDataBuffer>().copyRequestedNJointControllers());
80 }
81
82 Ice::StringSeq
84 {
85 throwIfInControlThread(__PRETTY_FUNCTION__);
86 return GetNonNullNames(_module<ControlThreadDataBuffer>().getActivatedNJointControllers());
87 }
88
89 void
90 ControllerManagement::checkNJointControllerClassName(const std::string& className) const
91 {
92 throwIfInControlThread(__PRETTY_FUNCTION__);
93 if (!NJointControllerRegistry::has(className))
94 {
95 std::stringstream ss;
96 ss << "Requested controller class '" << className
97 << "' unknown! Known classes:" << NJointControllerRegistry::getKeys()
98 << " (If this class exists in a different lib then load it in the property "
99 "definitions of the RT-unit. DO NOT load it via "
100 "loadLibFromPath(path) or loadLibFromPackage(package, lib)) (see "
101 "https://git.h2t.iar.kit.edu/sw/armarx-integration/robots/armar7/documentation/-/"
102 "issues/85)";
103 ARMARX_ERROR << ss.str();
104 throw InvalidArgumentException{ss.str()};
105 }
106 }
107
108 std::vector<NJointControllerBasePtr>
109 ControllerManagement::getNJointControllersNotNull(const std::vector<std::string>& names) const
110 {
111 throwIfInControlThread(__PRETTY_FUNCTION__);
112 auto guard = getGuard();
113 throwIfDevicesNotReady(__FUNCTION__);
114 std::vector<NJointControllerBasePtr> ctrl;
115 ctrl.reserve(names.size());
116 for (const auto& name : names)
117 {
118 ctrl.emplace_back(getNJointControllerNotNull(name));
119 }
120 return ctrl;
121 }
122
123 const NJointControllerBasePtr&
125 {
126 throwIfInControlThread(__PRETTY_FUNCTION__);
127 auto guard = getGuard();
128 throwIfDevicesNotReady(__FUNCTION__);
129 auto it = nJointControllers.find(name);
130 if (it == nJointControllers.end())
131 {
132 std::stringstream ss;
133 ss << "RobotUnit: there is no NJointControllerBase with name '" << name
134 << "'. Existing NJointControllers are: " << getNJointControllerNames();
135 throw InvalidArgumentException{ss.str()};
136 }
137 if (!it->second)
138 {
139 std::stringstream ss;
140 ss << "RobotUnit: The NJointControllerBase with name '" << name
141 << "'. Is a nullptr! This should never be the case (invariant)! \nMap:\n"
142 << nJointControllers;
143 ARMARX_FATAL << ss.str();
144 throw InvalidArgumentException{ss.str()};
145 }
146 return it->second;
147 }
148
149 void
150 ControllerManagement::deleteNJointController(const NJointControllerBasePtr& ctrl)
151 {
152 throwIfInControlThread(__PRETTY_FUNCTION__);
153 deleteNJointControllers(std::vector<NJointControllerBasePtr>{ctrl});
154 }
155
156 StringNJointControllerPrxDictionary
158 {
159 throwIfInControlThread(__PRETTY_FUNCTION__);
160 std::map<std::string, NJointControllerBasePtr> nJointControllersCopy;
161 {
162 auto guard = getGuard();
163 //copy to keep lock retention time low
164 nJointControllersCopy = nJointControllers;
165 }
166 StringNJointControllerPrxDictionary result;
167 for (const auto& pair : nJointControllersCopy)
168 {
169 result[pair.first] =
170 NJointControllerInterfacePrx::uncheckedCast(pair.second->getProxy(-1, true));
171 }
172 return result;
173 }
174
175 NJointControllerInterfacePrx
177 const std::string& instanceName,
178 const NJointControllerConfigPtr& config,
179 const Ice::Current&)
180 {
181 throwIfInControlThread(__PRETTY_FUNCTION__);
182 //no lock required
183 return NJointControllerInterfacePrx::uncheckedCast(
184 createNJointController(className, instanceName, config, true, false)
185 ->getProxy(-1, true));
186 }
187
188 NJointControllerInterfacePrx
190 const std::string& className,
191 const std::string& instanceName,
192 const StringVariantBaseMap& variants,
193 const Ice::Current&)
194 {
195 throwIfInControlThread(__PRETTY_FUNCTION__);
196 //no lock required
197 checkNJointControllerClassName(className);
198 if (!NJointControllerRegistry::get(className)->hasRemoteConfiguration())
199 {
200 std::stringstream ss;
201 ss << "Requested controller class '" << className << "' allows no remote configuration"
203 << " (Implement 'static WidgetDescription::WidgetPtr " << className
204 << "::GenerateConfigDescription()'"
205 << " and 'static NJointControllerConfigPtr " << className
206 << "::GenerateConfigFromVariants(const StringVariantBaseMap&)' to allow remote "
207 "configuration";
208 ARMARX_ERROR << ss.str();
209 throw InvalidArgumentException{ss.str()};
210 }
212 className,
213 instanceName,
214 NJointControllerRegistry::get(className)->GenerateConfigFromVariants(variants),
215 Ice::emptyCurrent /*to select ice overload*/);
216 }
217
218 NJointControllerInterfacePrx
220 const std::string& instanceName,
221 const NJointControllerConfigPtr& config,
222 const Ice::Current&)
223 {
225 throwIfInControlThread(__PRETTY_FUNCTION__);
226 {
228 auto guard = getGuard();
229 if (getNJointController(instanceName))
230 {
233 }
234 }
236 while (getNJointController(instanceName))
237 {
239 if (isShuttingDown())
240 {
242 return nullptr;
243 }
244 ARMARX_INFO << "wiating until controller '" << instanceName << "' is deleted";
245 }
246 while (getArmarXManager()->getIceManager()->isObjectReachable(instanceName))
247 {
249 if (isShuttingDown())
250 {
252 return nullptr;
253 }
254 ARMARX_INFO << "wiating until controller '" << instanceName << "' is removed from ice";
255 }
256 return NJointControllerInterfacePrx::uncheckedCast(
257 createNJointController(className, instanceName, config, true, false)
258 ->getProxy(-1, true));
259 }
260
261 const NJointControllerBasePtr&
263 const std::string& instanceName,
264 const NJointControllerConfigPtr& config,
265 bool deletable,
266 bool internal)
267 {
268 throwIfInControlThread(__PRETTY_FUNCTION__);
269 auto guard = getGuard();
270 throwIfDevicesNotReady(__FUNCTION__);
271 if (instanceName.empty())
272 {
273 ARMARX_ERROR << "The instance name is empty! (give a unique name)";
274 throw InvalidArgumentException{"The instance name is empty! (give a unique name)"};
275 }
276 //check if we would be able to create the class
277 checkNJointControllerClassName(className);
278 auto& factory = NJointControllerRegistry::get(className);
279
280 //check if the instance name is already in use
281 if (nJointControllers.count(instanceName))
282 {
283 std::stringstream ss;
284 ss << "There already is a controller instance with the name '" << instanceName
285 << "'. Use a different instance name instead."
286 << " Other used instance names are " << getNJointControllerNames();
287 ARMARX_ERROR << ss.str();
288 throw InvalidArgumentException{ss.str()};
289 }
290 if (nJointControllersToBeDeleted.count(instanceName))
291 {
292 std::stringstream ss;
293 ss << "The controller instance '" << instanceName
294 << "' is still pending deletion. Retry later or use a different name.";
295 ARMARX_ERROR << ss.str();
296 throw InvalidArgumentException{ss.str()};
297 }
298
299 //create the controller
301 NJointControllerBasePtr nJointCtrl =
302 factory->create(this, config, controllerCreateRobot, deletable, internal, instanceName);
303 ARMARX_CHECK_NOT_EQUAL(nJointCtrl->getControlDeviceUsedIndices().size(), 0)
304 << "The NJointControllerBase '" << nJointCtrl->getName()
305 << "' uses no ControlDevice! (It has to use at least one)";
306
307 getArmarXManager()->addObject(nJointCtrl, instanceName, false, false);
308 nJointControllers[instanceName] = std::move(nJointCtrl);
309 _module<Publisher>().getRobotUnitListenerProxy()->nJointControllerCreated(instanceName);
310 return nJointControllers.at(instanceName);
311 }
312
313 Ice::StringSeq
315 {
316 throwIfInControlThread(__PRETTY_FUNCTION__);
318 }
319
320 Ice::StringSeq
322 {
323 throwIfInControlThread(__PRETTY_FUNCTION__);
324 auto guard = getGuard();
325 return getMapKeys(nJointControllers);
326 }
327
328 std::vector<std::string>
330 const std::vector<NJointControllerBasePtr>& ctrls) const
331 {
332 throwIfInControlThread(__PRETTY_FUNCTION__);
333 std::vector<std::string> result;
334 result.reserve(ctrls.size());
335 for (const auto& ctrl : ctrls)
336 {
337 if (ctrl)
338 {
339 result.emplace_back(ctrl->getInstanceName());
340 }
341 }
342 return result;
343 }
344
345 void
346 ControllerManagement::activateNJointController(const std::string& name, const Ice::Current&)
347 {
348 throwIfInControlThread(__PRETTY_FUNCTION__);
350 }
351
352 void
354 const Ice::Current&)
355 {
356 throwIfInControlThread(__PRETTY_FUNCTION__);
358 }
359
360 void
361 ControllerManagement::activateNJointController(const NJointControllerBasePtr& ctrl)
362 {
363 throwIfInControlThread(__PRETTY_FUNCTION__);
364 activateNJointControllers(std::vector<NJointControllerBasePtr>{ctrl});
365 }
366
367 void
369 const std::vector<NJointControllerBasePtr>& ctrlsToActVec)
370 {
371 throwIfInControlThread(__PRETTY_FUNCTION__);
372 if (ctrlsToActVec.empty())
373 {
374 return;
375 }
376 auto guard = getGuard();
377 throwIfDevicesNotReady(__FUNCTION__);
378 //if not activate them
379 std::set<NJointControllerBasePtr, std::greater<NJointControllerBasePtr>> ctrlsToAct{
380 ctrlsToActVec.begin(), ctrlsToActVec.end()};
381 ARMARX_CHECK_EXPRESSION(!ctrlsToAct.count(nullptr));
382 //check if all already active
383 if (std::all_of(ctrlsToActVec.begin(),
384 ctrlsToActVec.end(),
385 [](const NJointControllerBasePtr& ctrl)
386 { return ctrl->isControllerActive(); }))
387 {
388 return;
389 }
390 //get already requested
391 const auto ctrlVector = _module<ControlThreadDataBuffer>().copyRequestedNJointControllers();
392 std::set<NJointControllerBasePtr, std::greater<NJointControllerBasePtr>>
393 ctrlsAlreadyRequested{ctrlVector.begin(), ctrlVector.end()};
394 ctrlsAlreadyRequested.erase(nullptr);
395 //check for conflict
396 std::vector<char> inuse;
397 //check requested controllers
398 {
399 auto r = NJointControllerBase::AreNotInConflict(ctrlsToAct.begin(), ctrlsToAct.end());
400 if (!r)
401 {
402 std::stringstream ss;
403 ss << "activateNJointControllers: requested controllers are in "
404 "conflict!\ncontrollers:\n"
405 << getNJointControllerNames(ctrlsToActVec);
406 ARMARX_ERROR << ss.str();
407 throw InvalidArgumentException{ss.str()};
408 }
409 inuse = std::move(*r);
410 }
411 ARMARX_DEBUG << "all requested controllers are conflict free" << std::flush;
412 auto printInUse = ARMARX_STREAM_PRINTER
413 {
414 for (const auto c : inuse)
415 {
416 out << (c ? 1 : 0);
417 }
418 };
419 ARMARX_DEBUG << "inuse field (request)\n" << printInUse;
420 //add already active controllers if they are conflict free
421 {
422 if (ctrlsAlreadyRequested.empty())
423 {
424 ARMARX_DEBUG << "no already requested NJointControllers";
425 }
426 for (const NJointControllerBasePtr& nJointCtrl : ctrlsAlreadyRequested)
427 {
428 if (ctrlsToAct.count(nJointCtrl))
429 {
430 continue;
431 }
432 auto r = nJointCtrl->isNotInConflictWith(inuse);
433 if (r)
434 {
435 ARMARX_DEBUG << "keeping already requested NJointControllerBase '"
436 << nJointCtrl->getInstanceName()
437 << "' in list of requested controllers";
438 ctrlsToAct.insert(nJointCtrl);
439 inuse = std::move(*r);
440 }
441 else
442 {
443 ARMARX_INFO << "removing already requested NJointControllerBase '"
444 << nJointCtrl->getInstanceName()
445 << "' from list of requested controllers";
446 }
447 }
448 ARMARX_DEBUG << "inuse field (all)\n" << printInUse;
449 }
450 _module<ControlThreadDataBuffer>().setActivateControllersRequest(ctrlsToAct);
451 }
452
453 void
454 ControllerManagement::deactivateNJointController(const std::string& name, const Ice::Current&)
455 {
456 throwIfInControlThread(__PRETTY_FUNCTION__);
458 }
459
460 void
462 const Ice::Current&)
463 {
464 throwIfInControlThread(__PRETTY_FUNCTION__);
466 }
467
468 void
469 ControllerManagement::deactivateNJointController(const NJointControllerBasePtr& ctrl)
470 {
471 throwIfInControlThread(__PRETTY_FUNCTION__);
472 deactivateNJointControllers(std::vector<NJointControllerBasePtr>{ctrl});
473 }
474
475 void
477 const std::vector<NJointControllerBasePtr>& ctrlsDeacVec)
478 {
479 throwIfInControlThread(__PRETTY_FUNCTION__);
480 auto guard = getGuard();
481 throwIfDevicesNotReady(__FUNCTION__);
482 if (ctrlsDeacVec.empty())
483 {
484 return;
485 }
486 const auto ctrlVector = _module<ControlThreadDataBuffer>().copyRequestedNJointControllers();
487 std::set<NJointControllerBasePtr, std::greater<NJointControllerBasePtr>> ctrls{
488 ctrlVector.begin(), ctrlVector.end()};
489 const std::size_t ctrlsNum = ctrls.size();
490 for (const auto& nJointCtrlToDeactivate : ctrlsDeacVec)
491 {
492 ctrls.erase(nJointCtrlToDeactivate);
493 }
494 if (ctrls.size() == ctrlsNum)
495 {
496 return;
497 }
498 _module<ControlThreadDataBuffer>().setActivateControllersRequest(ctrls);
499 }
500
501 void
502 ControllerManagement::deleteNJointController(const std::string& name, const Ice::Current&)
503 {
504 throwIfInControlThread(__PRETTY_FUNCTION__);
506 }
507
508 void
509 ControllerManagement::deleteNJointControllers(const Ice::StringSeq& names, const Ice::Current&)
510 {
511 throwIfInControlThread(__PRETTY_FUNCTION__);
513 }
514
515 void
517 const Ice::Current&)
518 {
519 throwIfInControlThread(__PRETTY_FUNCTION__);
520 auto guard = getGuard();
521 throwIfDevicesNotReady(__FUNCTION__);
522 auto ctrlsToActVec =
523 getNJointControllersNotNull(newSetup); //also checks if these controllers exist
524 _module<ControlThreadDataBuffer>().setActivateControllersRequest(
525 {ctrlsToActVec.begin(), ctrlsToActVec.end()});
526 }
527
528 void
530 const std::vector<NJointControllerBasePtr>& ctrlsToDelVec)
531 {
532 throwIfInControlThread(__PRETTY_FUNCTION__);
533 auto guard = getGuard();
534 throwIfDevicesNotReady(__FUNCTION__);
535 if (ctrlsToDelVec.empty())
536 {
537 return;
538 }
539 //check if all can be deleted
540 for (const auto& nJointCtrl : ctrlsToDelVec)
541 {
542 if (!nJointCtrl->isDeletable())
543 {
544 throw LogicError{"The NJointControllerBase '" + nJointCtrl->getInstanceName() +
545 "' can't be deleted since this operation is not allowed for this "
546 "controller! (no NJointControllerBase was deleted)"};
547 }
548 if (nJointCtrl->isControllerActive() || nJointCtrl->isControllerRequested())
549 {
550 throw LogicError{"The NJointControllerBase '" + nJointCtrl->getInstanceName() +
551 "' can't be deleted since it is active or requested! (no "
552 "NJointControllerBase was deleted)"};
553 }
554 }
555 for (const auto& nJointCtrl : ctrlsToDelVec)
556 {
557 const auto name = nJointCtrl->getInstanceName();
558 //deletion is done in a different thread since this call may be done by the controller (protection against use after free)
559 ARMARX_CHECK_EQUAL(nJointControllersToBeDeleted.count(name), 0)
560 << "The controller '" << name << "' is already pending deletion";
561 nJointControllersToBeDeleted[name] = std::move(nJointCtrl);
562 nJointControllers.erase(name);
563 ARMARX_VERBOSE << "added NJointControllerBase '" << name << "' to be deleted";
564 }
565 }
566
567 void
569 const Ice::Current&)
570 {
571 throwIfInControlThread(__PRETTY_FUNCTION__);
573 }
574
575 void
577 const Ice::Current&)
578 {
579 throwIfInControlThread(__PRETTY_FUNCTION__);
581 }
582
583 void
585 {
586 throwIfInControlThread(__PRETTY_FUNCTION__);
588 }
589
590 void
592 const std::vector<NJointControllerBasePtr>& ctrlsToDelVec)
593 {
594 throwIfInControlThread(__PRETTY_FUNCTION__);
595 auto guard = getGuard();
596 throwIfDevicesNotReady(__FUNCTION__);
597 if (ctrlsToDelVec.empty())
598 {
599 return;
600 }
601 deactivateNJointControllers(ctrlsToDelVec);
602 while (std::any_of(ctrlsToDelVec.begin(),
603 ctrlsToDelVec.end(),
604 [](const NJointControllerBasePtr& ctrl)
605 { return ctrl->isControllerActive(); }))
606 {
607 if (isShuttingDown())
608 {
609 return;
610 }
611 std::this_thread::sleep_for(std::chrono::microseconds{100});
612 }
613 deleteNJointControllers(ctrlsToDelVec);
614 }
615
616 NJointControllerClassDescription
618 const Ice::Current&) const
619 {
620 throwIfInControlThread(__PRETTY_FUNCTION__);
623 {
624 //this phase should only last short so busy waiting is ok
625 std::this_thread::sleep_for(std::chrono::milliseconds(50));
626 }
627 auto guard = getGuard();
628 throwIfDevicesNotReady(__FUNCTION__);
629 checkNJointControllerClassName(className);
630 NJointControllerClassDescription data;
631 data.className = className;
632 if (NJointControllerRegistry::get(className)->hasRemoteConfiguration())
633 {
634 data.configDescription =
635 NJointControllerRegistry::get(className)->GenerateConfigDescription(
636 controllerCreateRobot,
637 _module<Devices>().getControlDevicesConstPtr(),
638 _module<Devices>().getSensorDevicesConstPtr());
639 }
640 return data;
641 }
642
643 NJointControllerClassDescriptionSeq
645 {
646 throwIfInControlThread(__PRETTY_FUNCTION__);
647 std::size_t tries = 200;
650 {
651 //this phase should only last short so busy waiting is ok
652 std::this_thread::sleep_for(std::chrono::milliseconds(50));
653 if (!--tries)
654 {
655 throw RuntimeError{"RobotUnit::getNJointControllerClassDescriptions: it took too "
656 "long to for the unit to get in a valid state"};
657 }
658 }
659 auto guard = getGuard();
660 NJointControllerClassDescriptionSeq r;
661 r.reserve(NJointControllerRegistry::getKeys().size());
662 for (const auto& key : NJointControllerRegistry::getKeys())
663 {
664 r.emplace_back(getNJointControllerClassDescription(key));
665 }
666 return r;
667 }
668
669 NJointControllerInterfacePrx
670 ControllerManagement::getNJointController(const std::string& name, const Ice::Current&) const
671 {
672 throwIfInControlThread(__PRETTY_FUNCTION__);
673 NJointControllerBasePtr ctrl;
674 {
675 auto guard = getGuard();
676 auto it = nJointControllers.find(name);
677 if (it == nJointControllers.end())
678 {
679 return nullptr;
680 }
681 ctrl = it->second;
682 }
683 return NJointControllerInterfacePrx::uncheckedCast(ctrl->getProxy(-1, true));
684 }
685
686 NJointControllerStatus
688 const Ice::Current&) const
689 {
690 throwIfInControlThread(__PRETTY_FUNCTION__);
691 auto guard = getGuard();
692 throwIfDevicesNotReady(__FUNCTION__);
693 return getNJointControllerNotNull(name)->getControllerStatus();
694 }
695
696 NJointControllerStatusSeq
698 {
699 throwIfInControlThread(__PRETTY_FUNCTION__);
700 auto guard = getGuard();
701 if (!areDevicesReady())
702 {
703 return {};
704 }
705 NJointControllerStatusSeq r;
706 r.reserve(nJointControllers.size());
707 for (const auto& nJointCtrl : nJointControllers)
708 {
709 r.emplace_back(nJointCtrl.second->getControllerStatus());
710 }
711 return r;
712 }
713
714 NJointControllerDescription
716 const Ice::Current&) const
717 {
718 throwIfInControlThread(__PRETTY_FUNCTION__);
719 NJointControllerBasePtr nJointCtrl;
720 {
721 auto guard = getGuard();
722 throwIfDevicesNotReady(__FUNCTION__);
723 nJointCtrl = getNJointControllerNotNull(name);
724 }
725 return nJointCtrl->getControllerDescription();
726 }
727
728 NJointControllerDescriptionSeq
730 {
731 throwIfInControlThread(__PRETTY_FUNCTION__);
732 std::map<std::string, NJointControllerBasePtr> nJointControllersCopy;
733 {
734 auto guard = getGuard();
735 if (!areDevicesReady())
736 {
737 return {};
738 }
739 nJointControllersCopy = nJointControllers;
740 }
741 NJointControllerDescriptionSeq r;
742 r.reserve(nJointControllersCopy.size());
743 for (const auto& nJointCtrl : nJointControllersCopy)
744 {
745 r.emplace_back(nJointCtrl.second->getControllerDescription());
746 }
747 return r;
748 }
749
750 NJointControllerDescriptionWithStatus
752 const Ice::Current&) const
753 {
754 throwIfInControlThread(__PRETTY_FUNCTION__);
755 NJointControllerBasePtr nJointCtrl;
756 {
757 auto guard = getGuard();
758 throwIfDevicesNotReady(__FUNCTION__);
759 nJointCtrl = getNJointControllerNotNull(name);
760 }
761 return nJointCtrl->getControllerDescriptionWithStatus();
762 }
763
764 NJointControllerDescriptionWithStatusSeq
766 {
767 throwIfInControlThread(__PRETTY_FUNCTION__);
768 std::map<std::string, NJointControllerBasePtr> nJointControllersCopy;
769 {
770 auto guard = getGuard();
771 if (!areDevicesReady())
772 {
773 return {};
774 }
775 nJointControllersCopy = nJointControllers;
776 }
777 NJointControllerDescriptionWithStatusSeq r;
778 r.reserve(nJointControllersCopy.size());
779 for (const auto& nJointCtrl : nJointControllersCopy)
780 {
781 r.emplace_back(nJointCtrl.second->getControllerDescriptionWithStatus());
782 }
783 return r;
784 }
785
786 void
787 ControllerManagement::removeNJointControllers(
788 std::map<std::string, NJointControllerBasePtr>& ctrls,
789 bool blocking,
790 RobotUnitListenerPrx l)
791 {
792 throwIfInControlThread(__PRETTY_FUNCTION__);
793 for (auto& n2NJointCtrl : ctrls)
794 {
795 NJointControllerBasePtr& nJointCtrl = n2NJointCtrl.second;
796 if (blocking)
797 {
798 ARMARX_VERBOSE << "deleted NJointControllerBase " << n2NJointCtrl.first;
799 getArmarXManager()->removeObjectBlocking(nJointCtrl->getName());
800 }
801 else
802 {
803 ARMARX_VERBOSE << "deleted NJointControllerBase " << n2NJointCtrl.first;
804 getArmarXManager()->removeObjectBlocking(nJointCtrl->getName());
805 }
806 if (l)
807 {
808 l->nJointControllerDeleted(n2NJointCtrl.first);
809 }
810 }
811 ctrls.clear();
812 }
813
814 void
815 ControllerManagement::removeNJointControllersToBeDeleted(bool blocking, RobotUnitListenerPrx l)
816 {
817 throwIfInControlThread(__PRETTY_FUNCTION__);
818 removeNJointControllers(nJointControllersToBeDeleted, blocking, l);
819 }
820
821 void
822 ControllerManagement::_preFinishRunning()
823 {
824 throwIfInControlThread(__PRETTY_FUNCTION__);
825 //NJoint queued for deletion (some could still be in the queue)
826 ARMARX_DEBUG << "remove NJointControllers queued for deletion";
827 removeNJointControllersToBeDeleted();
828 ARMARX_DEBUG << "remove NJointControllers queued for deletion...done";
829 //NJoint
830 ARMARX_DEBUG << "remove NJointControllers";
831 removeNJointControllers(nJointControllers);
832 ARMARX_DEBUG << "remove NJointControllers...done";
833 }
834
835 void
836 ControllerManagement::_postFinishRunning()
837 {
838 throwIfInControlThread(__PRETTY_FUNCTION__);
839 nJointControllers.clear();
840 }
841
845
846 void
847 ControllerManagement::_preOnInitRobotUnit()
848 {
849 throwIfInControlThread(__PRETTY_FUNCTION__);
850 controllerCreateRobot = _module<RobotData>().cloneRobot();
851 }
852
853 void
854 ControllerManagement::updateNJointControllerRequestedState(
855 const std::set<NJointControllerBasePtr>& request)
856 {
857 throwIfInControlThread(__PRETTY_FUNCTION__);
858 ARMARX_DEBUG << "set requested state for NJoint controllers";
859 for (const auto& name2NJoint : nJointControllers)
860 {
861 NJointControllerAttorneyForControllerManagement::SetRequested(
862 name2NJoint.second, request.count(name2NJoint.second));
863 }
864 }
865} // namespace armarx::RobotUnitModule
#define ARMARX_STREAM_PRINTER
use this macro to write output code that is executed when printed and thus not executed if the debug ...
Definition Logging.h:308
constexpr T c
IceManagerPtr getIceManager() const
Returns the IceManager.
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
ArmarXManagerPtr getArmarXManager() const
Returns the ArmarX manager used to add and remove components.
static std::optional< std::vector< char > > AreNotInConflict(ItT first, ItT last)
static const std::unique_ptr< NJointControllerRegistryEntry > & get(const std::string &key)
Definition Registrar.h:85
NJointControllerDescriptionWithStatusSeq getNJointControllerDescriptionsWithStatuses(const Ice::Current &=Ice::emptyCurrent) const override
Returns the status and description of all NJointControllers.
NJointControllerClassDescription getNJointControllerClassDescription(const std::string &className, const Ice::Current &=Ice::emptyCurrent) const override
getNJointControllerClassDescription
NJointControllerDescription getNJointControllerDescription(const std::string &name, const Ice::Current &=Ice::emptyCurrent) const override
Returns the description of the NJointControllerBase.
const NJointControllerBasePtr & getNJointControllerNotNull(const std::string &name) const
Returns a pointer to the NJointControllerBase.
StringNJointControllerPrxDictionary getAllNJointControllers(const Ice::Current &=Ice::emptyCurrent) const override
Returns proxies to all NJointControllers.
void activateNJointControllers(const Ice::StringSeq &names, const Ice::Current &=Ice::emptyCurrent) override
Requests activation for the given NJointControllers.
void deactivateNJointController(const std::string &name, const Ice::Current &=Ice::emptyCurrent) override
Requests deactivation for the given NJointControllerBase.
NJointControllerStatusSeq getNJointControllerStatuses(const Ice::Current &=Ice::emptyCurrent) const override
Returns the status of all NJointControllers.
NJointControllerClassDescriptionSeq getNJointControllerClassDescriptions(const Ice::Current &=Ice::emptyCurrent) const override
getNJointControllerClassDescriptions
NJointControllerDescriptionWithStatus getNJointControllerDescriptionWithStatus(const std::string &name, const Ice::Current &=Ice::emptyCurrent) const override
Returns the status and description of the NJointControllerBase.
NJointControllerInterfacePrx createOrReplaceNJointController(const std::string &className, const std::string &instanceName, const NJointControllerConfigPtr &config, const Ice::Current &=Ice::emptyCurrent) override
Deletes any NJointControllerBase with the given name and creates a new one.
Ice::StringSeq getActivatedNJointControllerNames(const Ice::Current &=Ice::emptyCurrent) const override
Returns the names of all activated NJointControllers.
void deactivateAndDeleteNJointControllers(const Ice::StringSeq &names, const Ice::Current &) override
Queues the given NJointControllers for deletion and deactivates them if necessary.
void activateNJointController(const std::string &name, const Ice::Current &=Ice::emptyCurrent) override
Requests activation for the given NJointControllerBase.
NJointControllerDescriptionSeq getNJointControllerDescriptions(const Ice::Current &=Ice::emptyCurrent) const override
Returns the description of all NJointControllers.
NJointControllerStatus getNJointControllerStatus(const std::string &name, const Ice::Current &=Ice::emptyCurrent) const override
Returns the status of the NJointControllerBase.
Ice::StringSeq getNJointControllerNames(const Ice::Current &=Ice::emptyCurrent) const override
Returns the names of all NJointControllers.
void deactivateNJointControllers(const Ice::StringSeq &names, const Ice::Current &=Ice::emptyCurrent) override
Requests deactivation for the given NJointControllers.
std::vector< armarx::NJointControllerBasePtr > getNJointControllersNotNull(const std::vector< std::string > &names) const
Returns pointers to the NJointControllers.
void switchNJointControllerSetup(const Ice::StringSeq &newSetup, const Ice::Current &=Ice::emptyCurrent) override
Changes the set of requested NJointControllers to the given set.
Ice::StringSeq getNJointControllerClassNames(const Ice::Current &=Ice::emptyCurrent) const override
Returns the names of all available classes of NJointControllerBase.
void deactivateAndDeleteNJointController(const std::string &name, const Ice::Current &=Ice::emptyCurrent) override
Queues the given NJointControllerBase for deletion and deactivates it if necessary.
Ice::StringSeq getRequestedNJointControllerNames(const Ice::Current &=Ice::emptyCurrent) const override
Returns the names of all requested NJointControllers.
void deleteNJointController(const std::string &name, const Ice::Current &=Ice::emptyCurrent) override
Queues the given NJointControllerBase for deletion.
NJointControllerInterfacePrx getNJointController(const std::string &name, const Ice::Current &=Ice::emptyCurrent) const override
Returns a proxy to the NJointControllerBase.
NJointControllerInterfacePrx createNJointController(const std::string &className, const std::string &instanceName, const NJointControllerConfigPtr &config, const Ice::Current &=Ice::emptyCurrent) override
Cretes a NJointControllerBase.
NJointControllerInterfacePrx createNJointControllerFromVariantConfig(const std::string &className, const std::string &instanceName, const StringVariantBaseMap &variants, const Ice::Current &=Ice::emptyCurrent) override
Cretes a NJointControllerBase.
void deleteNJointControllers(const Ice::StringSeq &names, const Ice::Current &=Ice::emptyCurrent) override
Queues the given NJointControllers for deletion.
RobotUnitState getRobotUnitState() const
Returns the RobotUnit's State.
T & _module()
Returns this as ref to the given type.
bool areDevicesReady() const
Returns whether Devices are ready.
GuardType getGuard() const
Returns a guard to the RobotUnits mutex.
void throwIfInControlThread(const std::string &fnc) const
Throws if the current thread is the ControlThread.
bool isShuttingDown() const
Returns whether the RobotUnit is shutting down.
void throwIfDevicesNotReady(const std::string &fnc) const
Throws if the Devices are not ready.
This class allows minimal access to private members of NJointControllerBase in a sane fashion for Con...
#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_EQUAL(lhs, rhs)
This macro evaluates whether lhs is inequal (!=) rhs and if it turns out to be false it will throw an...
#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:179
#define ARMARX_FATAL
The logging level for unexpected behaviour, that will lead to a seriously malfunctioning program and ...
Definition Logging.h:197
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:194
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:182
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:185
std::map< std::string, VariantBasePtr > StringVariantBaseMap
void getMapKeys(const MapType &map, OutputIteratorType it)
Definition algorithm.h:173
#define ARMARX_TRACE
Definition trace.h:75