NJointControllerBase.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 RobotAPI::ArmarXObjects::NJointController
17 * @author Raphael Grimm ( raphael dot grimm at kit dot edu )
18 * @date 2017
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
23#pragma once
24
25#include <atomic>
26#include <map>
27#include <mutex>
28#include <optional>
29
30#include <VirtualRobot/VirtualRobot.h>
31
35#include <ArmarXCore/interface/core/ManagedIceObjectDefinitions.h>
36
37// #include <RobotAPI/components/units/RobotUnit/RobotUnit.h>
38
39#include <RobotAPI/interface/units/RobotUnit/NJointController.h>
40#include <RobotAPI/interface/units/RobotUnit/RobotUnitInterface.h>
41
42namespace IceProxy::armarx
43{
44 class DebugDrawerInterface;
45 class DebugObserverInterface;
46 class RobotUnitInterface;
47} // namespace IceProxy::armarx
48
49namespace armarx
50{
51 namespace RobotUnitModule
52 {
56 } // namespace RobotUnitModule
57
58 namespace detail
59 {
60 template <class>
63 } // namespace detail
64
65 namespace WidgetDescription
66 {
67 class Widget;
68 typedef ::IceInternal::Handle<::armarx::WidgetDescription::Widget> WidgetPtr;
69 typedef ::std::map<::std::string, ::armarx::WidgetDescription::WidgetPtr>
71 } // namespace WidgetDescription
72
74 class JointController;
75 class SensorValueBase;
77 using ConstControlDevicePtr = std::shared_ptr<const class ControlDevice>;
78 using ConstSensorDevicePtr = std::shared_ptr<const class SensorDevice>;
79
80 typedef ::IceInternal::ProxyHandle<::IceProxy::armarx::DebugDrawerInterface>
82 typedef ::IceInternal::ProxyHandle<::IceProxy::armarx::DebugObserverInterface>
84 typedef ::IceInternal::ProxyHandle<::IceProxy::armarx::RobotUnitInterface>
86
87 using ThreadPoolPtr = std::shared_ptr<class ThreadPool>;
88
92
94
95 /**
96 * @defgroup Library-RobotUnit-NJointControllers NJointControllers
97 * @ingroup Library-RobotUnit
98 */
99
100 /**
101 * @ingroup Library-RobotUnit-NJointControllers
102 * @brief A high level controller writing its results into \ref ControlTargetBase "ControlTargets".
103 *
104 * This is the abstract base class for all NJointControllers.
105 * It implements basic management routines required by the RobotUnit and some basic ice calls.
106 * \ref NJointControllerBase "NJointControllers" are instantiated and managed by the \ref RobotUnit.
107 *
108 * A \ref NJointControllerBase calculates \ref ControlTargetBase "ControlTargets" for a set of
109 * \ref ControlDevice "ControlDevices" in a specific ControlMode.
110 * This ControlMode is defined for each \ref ControlDevice during construction.
111 *
112 * \section nj-state Requested and Active
113 * A \ref NJointControllerBase can is requested / not requested and active / inactive.
114 * All four combinations are possible.
115 *
116 * \subsection nj-state-req Requested / Not Requested
117 * If the user wants this \ref NJointControllerBase to be executed it is in a requested state (see \ref isControllerRequested).
118 * Otherwise the controler is not requested.
119 *
120 * Calling \ref activateController sets the state to requested.
121 * Calling \ref deactivateController sets the state to not requested.
122 * If the \ref NJointControllerBase causes an error or a different \ref NJointControllerBase using one or more of the same
123 * \ref ControlDevice's is requested, this \ref NJointControllerBase is deactivated.
124 *
125 *
126 * \subsection nj-state-act Active / Inactive
127 * Is the \ref NJointControllerBase executed by the \ref RobotUnitModules::ControlThread "ControlThread" it is active
128 * (see \ref isControllerActive).
129 *
130 * To be executed by the \ref RobotUnitModules::ControlThread "ControlThread", the \ref NJointControllerBase has to be
131 * requested at some point in the past.
132 *
133 * If a controller is active, it has to write a valid \ref ControlTargetBase "ControlTarget"
134 * for each of its \ref ControlDevice "ControlDevicea" (if it fails, it will be deactivated).
135 *
136 * \section Constructor
137 * In the Constructor, a \ref NJointControllerBase has to declare all \ref ControlDevice "ControlDevices" it uses.
138 *
139 * The constructor takes a pointer to a configuration structure of the type \ref NJointControllerBase::ConfigPtrT.
140 * If an implementation requires a special configuration structure (e.g.: SomeOtherCfg), it has to override this type by calling adding
141 * \code{.cpp}
142 * using ConfigPtrT = SomeOtherCfgPtr;
143 * \endcode
144 * to it's clas definition.
145 * The type SomeOtherCfg has to derive \ref NJointControllerConfigPtr.
146 *
147 * There is a way to generate a small gui widget for controller construction (see this \ref nj-ctor-gui "section").
148 *
149 * \subsection nj-ctor-req-ctrl Using ControlTargets
150 * A \ref NJointControllerBase can use \ref peekControlDevice to examine a \ref ControlDevice before using it
151 * (e.g.: checking the supported \ref ControlTargetBase "ControlTargets").
152 *
153 * If a \ref ControlDevice should be used by this \ref NJointControllerBase, it has to call \ref useControlDevice.
154 * This sets the ControlMode for the \ref ControlDevice and returns a pointer to the \ref ControlTargetBase "ControlTarget".
155 * This pointer has to be used to send commands in each iteration of \ref rtRun.
156 * The ControlMode can't be changed afterwards (A new \ref NJointControllerBase has to be created).
157 *
158 *
159 * \subsection nj-ctor-req-sens Using SensorValues
160 * A \ref NJointControllerBase can use \ref peekSensorDevice to examine a \ref SensorDevice before using it.
161 *
162 * If a \ref SensorDevice should be used by this \ref NJointControllerBase, it has to call \ref useSensorDevice.
163 * This returns a pointer to the \ref SensorValueBase "SensorValue".
164 *
165 * \subsection nj-ctor-rob A synchronized Virtualrobot
166 * If the controller needs a simox robot in \ref rtRun, it should call \ref useSynchronizedRtRobot.
167 * This will provide a simoxRobot via \ref rtGetRobot.
168 * This robot is synchronized with the real robots state before calling \ref rtRun
169 *
170 * \section nj-parts Rt and non Rt
171 * Each \ref NJointControllerBase has two parts:
172 * \li The RT controll loop
173 * \li The NonRT ice communication
174 *
175 * \subsection rtcontrollloop The Rt controll loop (\ref rtRun)
176 * \warning This part has to satisfy realtime conditions!
177 * All realtime functions of \ref NJointControllerBase have the 'rt' prefix.
178 *
179 * Here the \ref NJointControllerBase has access to the robot's current state
180 * and has to write results into \ref ControlTargetBase "ControlTargets".
181 *
182 * It must not:
183 * \li call any blocking operation
184 * \li allocate ram on the heap (since this is a blocking operation)
185 * \li resize any datastructure (e.g. vector::resize) (this sometimes allocates ram on the heap)
186 * \li insert new datafields into datastructures (e.g. vector::push_back) (this sometimes allocates ram on the heap)
187 * \li write to any stream (e.g. ARMARX_VERBOSE, std::cout, print, filestreams) (this sometimes blocks/allocates ram on the heap)
188 * \li make network calls (e.g. through ice) (this blocks/allocates ram on the heap) (using begin_... end_... version of ice calls IS NO SOLUTION)
189 * \li do any expensive calculations (e.g. calculate IK, run some solver, invert big matrices)
190 *
191 * \subsection nonrtpart The NonRT ice communication
192 * This part consits of any ice communication.
193 * Here the \ref NJointControllerBase can get new controll parameters or targets from other components.
194 *
195 * \section rtnrtcomm Communication between RT and NonRT
196 * All communication between RT and NonRT has to be lockfree.
197 * The \ref NJointControllerBase has to use constructs like atomics or
198 * \ref TripleBuffer "TripleBuffers" (See \ref armarx::NJointControllerWithTripleBuffer).
199 *
200 * \image html NJointControllerGeneralDataFlow.svg "General Dataflow in a NJointControllerBase"
201 *
202 * \image html NJointControllerAtomicDataFlow.svg "Dataflow in a NJointControllerBase using atomics for communication between RT and NonRT"
203 *
204 * \image html NJointControllerTripleBufferDataFlow.svg "Dataflow in a NJointControllerBase using a triple buffer for communication between RT and NonRT"
205 *
206 *
207 * \image html NJointControllerDataFlow_Graph.svg "Dataflow in a NJointControllerBase as a Graph of the two participating domains"
208 * The above image shows the two participating domains: one RT thread and multiple ICE threads.
209 * If data has to flow along an arrow, you need some construct for non blocking message passing.
210 *
211 * \warning If you use \ref TrippleBuffer "TrippleBuffers" or \ref WriteBufferedTrippleBuffer "WriteBufferedTrippleBuffers" you need a separate one for each arrow.
212 *
213 * \section expensivework How to do expensive calculations
214 * You have to execute expensive calculations in a different worker thread.
215 * This thread could calculate target values at its own speed (e.g. 100 Hz).
216 *
217 * While rtRun runs at a higher frequency (e.g. 1000 Hz) and:
218 * \li reads target values
219 * \li optionally passes the target values to a PID controller
220 * \li writes them to the targets
221 * \li sends the sensor values to the worker thread.
222 *
223 * If you do some additional calculation in rtRun, you maybe need to pass config parameters from NonRT to RT using a nonblocking method.
224 *
225 * \image html NJointControllerWorkerThreadDataFlow.svg "Dataflow in a NJointControllerBase using a worker thread"
226 *
227 * \image html NJointControllerWorkerThreadDataFlow_Graph.svg "Dataflow in a NJointControllerBase using a worker thread as a Graph of the three participating domains"
228 * The above image shows the three participating domains: one RT thread, one worker trhead and multiple ICE threads.
229 * If data has to flow along an arrow, you need some construct for non blocking message passing.
230 *
231 * \warning If you use \ref TrippleBuffer "TrippleBuffers" or \ref WriteBufferedTrippleBuffer "WriteBufferedTrippleBuffers" you need a separate one for each arrow.
232 *
233 * \section nj-ctor-gui Providing a gui for controller construction.
234 * By implementing these functions:
235 * \code{.cpp}
236 static WidgetDescription::WidgetPtr GenerateConfigDescription
237 (
238 const VirtualRobot::RobotPtr& robot,
239 const std::map<std::string, ConstControlDevicePtr>& controlDevices,
240 const std::map<std::string, ConstSensorDevicePtr>& sensorDevices
241 ); //describes how the widget is supposed to look
242 static ConfigPtrT GenerateConfigFromVariants(const StringVariantBaseMap&); // turns the resulting variants into a config
243 * \endcode
244 *
245 * The \ref RobotUnitGui will provide a widget to configure and construct a \ref NJointControllerBase of this type.
246 *
247 * \section Examples
248 *
249 * More examples can be found in the Tutorials Package
250 *
251 * \subsection nj-example-1 A simple pass Position controller
252 * \note The code can be found in the Tutorial package
253 *
254 * \subsection nj-example-1-h Header
255 * Include headers
256 * \code{.cpp}
257 #include <RobotAPI/components/units/RobotUnit/ControlTargets/ControlTarget1DoFActuator.h>
258 #include <RobotAPI/components/units/RobotUnit/RobotUnit.h>
259 #include <RobotAPI/components/units/RobotUnit/SensorValues/SensorValue1DoFActuator.h>
260 * \endcode
261 *
262 * Open the namespace
263 * \code{.cpp}
264 namespace armarx
265 {
266 * \endcode
267 *
268 * Typedef some pointers
269 * \code{.cpp}
270 TYPEDEF_PTRS_HANDLE(NJointPositionPassThroughController);
271 TYPEDEF_PTRS_HANDLE(NJointPositionPassThroughControllerConfig);
272 * \endcode
273 *
274 * The config has to inherit \ref NJointControllerConfig and consists only of the joint name
275 * \code{.cpp}
276 class NJointPositionPassThroughControllerConfig : virtual public NJointControllerConfig
277 {
278 public:
279 NJointPositionPassThroughControllerConfig(const std::string& name): deviceName {name} {}
280 std::string deviceName;
281 };
282 * \endcode
283 *
284 * The controller class has to inherit \ref NJointControllerBase
285 * \code{.cpp}
286 class NJointPositionPassThroughController: public NJointControllerBase
287 {
288 public:
289 * \endcode
290 *
291 * The \ref NJointControllerBase provides a config widget for the \ref RobotUnitGuiPlugin
292 * \code{.cpp}
293 static WidgetDescription::WidgetPtr GenerateConfigDescription
294 (
295 const VirtualRobot::RobotPtr&,
296 const std::map<std::string, ConstControlDevicePtr>& controlDevices,
297 const std::map<std::string, ConstSensorDevicePtr>& sensorDevices
298 );
299 static NJointControllerConfigPtr GenerateConfigFromVariants(const StringVariantBaseMap& values);
300 * \endcode
301 *
302 * The ctor receives a pointer to the \ref RobotUnit, a pointer to the config and a pointer to a VirtualRobot model.
303 * \code{.cpp}
304 NJointPositionPassThroughController(
305 const RobotUnitPtr& prov,
306 NJointControllerConfigPtr config,
307 const VirtualRobot::RobotPtr& r
308 );
309 * \endcode
310 *
311 * The function to provide the class name.
312 * \code{.cpp}
313 std::string getClassName(const Ice::Current&) const override;
314 * \endcode
315 *
316 * This controller provides widgets for function calls.
317 * \code{.cpp}
318 WidgetDescription::StringWidgetDictionary getFunctionDescriptions(const Ice::Current&) const override;
319 void callDescribedFunction(const std::string& name, const StringVariantBaseMap& value, const Ice::Current&) override;
320 * \endcode
321 *
322 * The run function executed to calculate new targets
323 * \code{.cpp}
324 void rtRun(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration) override;
325 * \endcode
326 *
327 * Hooks for this \ref NJointControllerBase to execute code during publishing.
328 * \code{.cpp}
329 void onPublishActivation(const DebugDrawerInterfacePrx&, const DebugObserverInterfacePrx&) override;
330 void onPublishDeactivation(const DebugDrawerInterfacePrx& drawer, const DebugObserverInterfacePrx&) override;
331 void onPublish(const SensorAndControl&, const DebugDrawerInterfacePrx& drawer, const DebugObserverInterfacePrx&) override;
332 * \endcode
333 *
334 * This \ref NJointControllerBase uses one position \ref SensorValue1DoFActuatorPosition "SensorValue", calculates one
335 * position \ref ControlTarget1DoFActuatorPosition "ControlTarget" and stores the current position target and position value in atomics.
336 * \code{.cpp}
337 const SensorValue1DoFActuatorPosition* sensor;
338 ControlTarget1DoFActuatorPosition* target;
339 std::atomic<float> targetPos {0};
340 std::atomic<float> currentPos {0};
341 * \endcode
342 *
343 * Close the class and the namespace
344 * \code{.cpp}
345 };
346 }
347 * \endcode
348 *
349 * \subsection nj-example-1-c Source file
350 *
351 * Include the required headers.
352 * \code{.cpp}
353 #include <RobotAPI/libraries/core/Pose.h>
354
355 #include "NJointPositionPassThroughController.h"
356 * \endcode
357 *
358 * Open the namespace
359 * \code{.cpp}
360 namespace armarx
361 {
362 * \endcode
363 *
364 * This generates a config widget used to display a config gui in \ref RobotUnitGui.
365 * It consist out of a \ref HBoxLayout containing a \ref Label and a \ref StringComboBox
366 * \code{.cpp}
367 WidgetDescription::WidgetPtr NJointPositionPassThroughController::GenerateConfigDescription(const VirtualRobot::RobotPtr&, const std::map<std::string, ConstControlDevicePtr>& controlDevices, const std::map<std::string, ConstSensorDevicePtr>& sensorDevices)
368 {
369 using namespace armarx::WidgetDescription;
370 HBoxLayoutPtr layout = new HBoxLayout;
371 LabelPtr label = new Label;
372 label->text = "control device name";
373 layout->children.emplace_back(label);
374 StringComboBoxPtr box = new StringComboBox;
375 box->defaultIndex = 0;
376 * \endcode
377 *
378 * The \ref StringComboBox only contains the names of \ref ControlDevice "ControlDevices" accepting
379 * a position \ref ControlTarget1DoFActuatorPosition "ControlTarget" and providing a position
380 * \ref SensorValue1DoFActuatorPosition "SensorValue"
381 * \code{.cpp}
382 //filter control devices
383 for (const auto& name2dev : controlDevices)
384 {
385 const ConstControlDevicePtr& dev = name2dev.second;
386 const auto& name = name2dev.first;
387 if (
388 dev->hasJointController(ControlModes::Position1DoF) &&
389 dev->getJointController(ControlModes::Position1DoF)->getControlTarget()->isA<ControlTarget1DoFActuatorPosition>() &&
390 sensorDevices.count(name) &&
391 sensorDevices.at(name)->getSensorValue()->isA<SensorValue1DoFActuatorPosition>()
392 )
393 {
394 box->options.emplace_back(name);
395 }
396 }
397 box->name = "name";
398 layout->children.emplace_back(box);
399 return layout;
400 }
401 * \endcode
402 *
403 * This turns a map of variants into the config required by this \ref NJointControllerBase.
404 * The \ref Variant for the key 'name' defines the \ref ControlDevice.
405 * \code{.cpp}
406 NJointControllerConfigPtr NJointPositionPassThroughController::GenerateConfigFromVariants(const StringVariantBaseMap& values)
407 {
408 //you should check here for types null additional params etc
409 return new NJointPositionPassThroughControllerConfig {values.at("name")->getString()};
410 }
411 * \endcode
412 *
413 * The constructors implementation.
414 * \code{.cpp}
415 NJointPositionPassThroughController::NJointPositionPassThroughController(
416 const RobotUnitPtr& ru,
417 NJointControllerConfigPtr config,
418 const VirtualRobot::RobotPtr&
419 )
420 {
421 ARMARX_CHECK_EXPRESSION(ru);
422 * \endcode
423 *
424 * It checks whether the provided config has the correct type.
425 * \code{.cpp}
426 NJointPositionPassThroughControllerConfigPtr cfg = NJointPositionPassThroughControllerConfigPtr::dynamicCast(config);
427 ARMARX_CHECK_EXPRESSION(cfg) << "The provided config has the wrong type! The type is " << config->ice_id();
428 * \endcode
429 *
430 * Then it retrieves the \ref SensorValue1DoFActuatorPosition "SensorValue" and
431 * \ref ControlTarget1DoFActuatorPosition "ControlTarget", casts then to the required types and stores them to the member variables.
432 * \code{.cpp}
433 const SensorValueBase* sv = useSensorValue(cfg->deviceName);
434 ControlTargetBase* ct = useControlTarget(cfg->deviceName, ControlModes::Position1DoF);
435 ARMARX_CHECK_EXPRESSION(sv->asA<SensorValue1DoFActuatorPosition>());
436 ARMARX_CHECK_EXPRESSION(ct->asA<ControlTarget1DoFActuatorPosition>());
437 sensor = sv->asA<SensorValue1DoFActuatorPosition>();
438 target = ct->asA<ControlTarget1DoFActuatorPosition>();
439 }
440 * \endcode
441 *
442 * The class name has to be unique, hence the c++ class name should be used.
443 * \code{.cpp}
444 std::string NJointPositionPassThroughController::getClassName(const Ice::Current&) const
445 {
446 return "NJointPositionPassThroughController";
447 }
448
449 * \endcode
450 *
451 * This \ref NJointControllerBase provides two widgets for function calls.
452 * \code{.cpp}
453 WidgetDescription::StringWidgetDictionary NJointPositionPassThroughController::getFunctionDescriptions(const Ice::Current&) const
454 {
455 using namespace armarx::WidgetDescription;
456 * \endcode
457 *
458 * The first widget has a \ref Label and a \ref FloatSpinBox.
459 * \code{.cpp}
460 HBoxLayoutPtr layoutSetPos = new HBoxLayout;
461 {
462 LabelPtr label = new Label;
463 label->text = "positiontarget";
464 layoutSetPos->children.emplace_back(label);
465 FloatSpinBoxPtr spin = new FloatSpinBox;
466 spin->defaultValue = 0;
467 spin->max = 1;
468 spin->min = -1;
469 * \endcode
470 *
471 * The \ref FloatSpinBox creates a variant called 'spinmearound'
472 * \code{.cpp}
473 spin->name = "spinmearound";
474 layoutSetPos->children.emplace_back(spin);
475 }
476 * \endcode
477 *
478 * The second widget also has a \ref Label and a \ref FloatSpinBox.
479 * \code{.cpp}
480 VBoxLayoutPtr layoutSetHalfPos = new VBoxLayout;
481 {
482 LabelPtr label = new Label;
483 label->text = "positiontarget / 2";
484 layoutSetHalfPos->children.emplace_back(label);
485 FloatSpinBoxPtr spin = new FloatSpinBox;
486 spin->defaultValue = 0;
487 spin->max = 0.5;
488 spin->min = -0.5;
489 spin->name = "spinmehalfaround";
490 layoutSetHalfPos->children.emplace_back(spin);
491 }
492 * \endcode
493 *
494 * This returns a map of boths widgets.
495 * The keys will be used to identify the called function.
496 * \code{.cpp}
497 return {{"SetPosition", layoutSetPos}, {"SetPositionHalf", layoutSetHalfPos}};
498 }
499 * \endcode
500 *
501 * This function is called from the \ref RobotUnitGuiPlugin when the prior defined functions are called.
502 * Both functions set the target position.
503 * \code{.cpp}
504 void NJointPositionPassThroughController::callDescribedFunction(const std::string& name, const StringVariantBaseMap& value, const Ice::Current&)
505 {
506 if (name == "SetPosition")
507 {
508 //you should check here for types null additional params etc
509 targetPos = value.at("spinmearound")->getFloat();
510 }
511 else if (name == "SetPositionHalf")
512 {
513 //you should check here for types null additional params etc
514 targetPos = value.at("spinmehalfaround")->getFloat() * 2;
515 }
516 else
517 {
518 ARMARX_ERROR << "CALLED UNKNOWN REMOTE FUNCTION: " << name;
519 }
520 }
521 * \endcode
522 *
523 * The \ref rtRun function sets the \ref ControlTarget1DoFActuatorPosition "ControlTarget" to the
524 * target value set via the atomic and stores the current
525 * \ref SensorValue1DoFActuatorPosition "SensorValue" to the other atomic.
526 * \code{.cpp}
527 void NJointPositionPassThroughController::rtRun(const IceUtil::Time& t, const IceUtil::Time&)
528 {
529 ARMARX_RT_LOGF_ERROR("A MESSAGE PARAMETER %f", t.toSecondsDouble()).deactivateSpam(1);
530 ARMARX_RT_LOGF_IMPORTANT("A MESSAGE WITHOUT PARAMETERS").deactivateSpam(1);
531 target->position = targetPos;
532 currentPos = sensor->position;
533 }
534 * \endcode
535 *
536 * The publish activation \ref onPublishActivation "hook" does nothing, but could be used to call
537 * \ref DebugDraver::setRobotVisu.
538 * \code{.cpp}
539 void NJointPositionPassThroughController::onPublishActivation(const DebugDrawerInterfacePrx&, const DebugObserverInterfacePrx&)
540 {
541 //we could do some setup for the drawer here. e.g. add a robot
542 }
543
544 * \endcode
545 *
546 * The publish deactivation \ref onPublishDeactivation "hook" clears the \ref DebugDrawer layer
547 * \code{.cpp}
548 void NJointPositionPassThroughController::onPublishDeactivation(const DebugDrawerInterfacePrx& drawer, const DebugObserverInterfacePrx&)
549 {
550 drawer->removeLayer("Layer_" + getInstanceName());
551 }
552
553 * \endcode
554 *
555 * The publish \ref onPublish "hook" draws a sphere with radius of the position stored in the atomic times 2000 to the \ref DebugDrawer.
556 * \code{.cpp}
557 void NJointPositionPassThroughController::onPublish(const SensorAndControl&, const DebugDrawerInterfacePrx& drawer, const DebugObserverInterfacePrx&)
558 {
559 drawer->setSphereVisu("Layer_" + getInstanceName(), "positionball", new Vector3, armarx::DrawColor {1, 1, 1, 1}, currentPos * 2000);
560 }
561 * \endcode
562 *
563 * This registers a factory for this \ref NJointControllerBase.
564 * This factory is used by the \ref RobotUnit to create the \ref NJointControllerBase.
565 * The passed name has to match the name returned by \ref getClassName.
566 * \code{.cpp}
567 NJointControllerRegistration<NJointPositionPassThroughController> registrationControllerNJointPositionPassThroughController("NJointPositionPassThroughController");
568 * \endcode
569 *
570 * This statically asserts a factory for the type NJointPositionPassThroughController is present.
571 * \code{.cpp}
572 ARMARX_ASSERT_NJOINTCONTROLLER_HAS_CONSTRUCTION_GUI(NJointPositionPassThroughController);
573 * \endcode
574 * Close the namespace
575 * \code{.cpp}
576 }
577 * \endcode
578 */
580 virtual public NJointControllerInterface,
581 virtual public ManagedIceObject
582 {
583 // //////////////////////////////////////////////////////////////////////////////////////// //
584 // /////////////////////////////////////// typedefs /////////////////////////////////////// //
585 // //////////////////////////////////////////////////////////////////////////////////////// //
586 public:
587 using ConfigPtrT = NJointControllerConfigPtr;
590 const std::map<std::string, ConstControlDevicePtr>& controlDevices,
591 const std::map<std::string, ConstSensorDevicePtr>& sensorDevices);
592 template <class ConfigPrtType>
594 ConfigPrtType (*)(const StringVariantBaseMap&);
595 // //////////////////////////////////////////////////////////////////////////////////////// //
596 // ///////////////////////////// constructor setup functions ////////////////////////////// //
597 // //////////////////////////////////////////////////////////////////////////////////////// //
598 public:
599 /**
600 * @brief Get a const ptr to the given \ref SensorDevice
601 * \warning This function can only be called in a \ref NJointControllerBase's ctor (or functions called in it)
602 * @param deviceName The \ref SensorDevice's name
603 * @return A const ptr to the given \ref SensorDevice
604 */
605 ConstSensorDevicePtr peekSensorDevice(const std::string& deviceName) const;
606 /**
607 * @brief Get a const ptr to the given \ref ControlDevice
608 * \warning This function can only be called in a \ref NJointControllerBase's ctor (or functions called in it)
609 * @param deviceName The \ref ControlDevice's name
610 * @return A const ptr to the given \ref ControlDevice
611 */
612 ConstControlDevicePtr peekControlDevice(const std::string& deviceName) const;
613
614 /**
615 * @brief Declares to calculate the \ref ControlTargetBase "ControlTarget"
616 * for the given \ref ControlDevice in the given ControlMode when \ref rtRun is called
617 * \warning This function can only be called in a \ref NJointControllerBase's ctor (or functions called in it)
618 * @param deviceName The \ref ControlDevice's name
619 * @param controlMode The \ref ControlTargetBase "ControlTarget's" ControlMode
620 * @return A ptr to the given \ref ControlDevice's \ref ControlTargetBase "ControlTarget"in the given ControlMode
621 */
622 ControlTargetBase* useControlTarget(const std::string& deviceName,
623 const std::string& controlMode);
624
625 /**
626 * @brief Declares to calculate the \ref ControlTargetBase "ControlTarget"
627 * for the given \ref ControlDevice in the given ControlMode when \ref rtRun is called
628 * \warning This function can only be called in a \ref NJointControllerBase's ctor (or functions called in it)
629 * @param deviceName The \ref ControlDevice's name
630 * @param controlMode The \ref ControlTargetBase "ControlTarget's" ControlMode
631 * @return A ptr to the given \ref ControlDevice's \ref ControlTargetBase "ControlTarget"in the given ControlMode
632 */
633 template <class T>
634 T*
635 useControlTarget(const std::string& deviceName, const std::string& controlMode)
636 {
637 static_assert(std::is_base_of<ControlTargetBase, T>::value,
638 "The given type does not derive ControlTargetBase");
639 ControlTargetBase* const ptr = useControlTarget(deviceName, controlMode);
640 return dynamic_cast<T*>(ptr);
641 }
642
643 /**
644 * @brief Get a const ptr to the given \ref SensorDevice's \ref SensorValueBase "SensorValue"
645 * \warning This function can only be called in a \ref NJointControllerBase's ctor (or functions called in it)
646 * @param deviceName The \ref SensorDevice's name
647 * @return A const ptr to the given \ref SensorDevice's \ref SensorValueBase "SensorValue"
648 */
649 const SensorValueBase* useSensorValue(const std::string& sensorDeviceName) const;
650
651 /**
652 * @brief Get a const ptr to the given \ref SensorDevice's \ref SensorValueBase "SensorValue"
653 * \warning This function can only be called in a \ref NJointControllerBase's ctor (or functions called in it)
654 * @param deviceName The \ref SensorDevice's name
655 * @return A const ptr to the given \ref SensorDevice's \ref SensorValueBase "SensorValue"
656 */
657 template <class T>
658 const T*
659 useSensorValue(const std::string& deviceName) const
660 {
661 static_assert(std::is_base_of<SensorValueBase, T>::value,
662 "The given type does not derive SensorValueBase");
663 const SensorValueBase* const ptr = useSensorValue(deviceName);
664 return dynamic_cast<const T*>(ptr);
665 }
666
667 /**
668 * @brief Requests a VirtualRobot for use in \ref rtRun
669 * *
670 * \warning This function can only be called in a \ref NJointControllerBase's ctor (or functions called in it)
671 *
672 * The robot is updated before \ref rtRun is called and can be accessed via \rtGetRobot
673 * @param updateCollisionModel Whether the robot's collision model should be updated
674 * @see rtGetRobot
675 */
676 const VirtualRobot::RobotPtr& useSynchronizedRtRobot(bool updateCollisionModel = false);
677
678 // //////////////////////////////////////////////////////////////////////////////////////// //
679 // ////////////////////////////////// Component interface ///////////////////////////////// //
680 // //////////////////////////////////////////////////////////////////////////////////////// //
681 protected:
682 /// @see Component::getDefaultName
683 std::string
684 getDefaultName() const override
685 {
686 return getClassName();
687 }
688
689 /// @see Component::onInitComponent
690 void onInitComponent() final;
691 /// @see Component::onConnectComponent
692 void onConnectComponent() final;
693 /// @see Component::onDisconnectComponent
694 void onDisconnectComponent() final;
695 /// @see Component::onExitComponent
696 void onExitComponent() final;
697
698 virtual void
702
703 virtual void
707
708 virtual void
712
713 virtual void
717
718 // //////////////////////////////////////////////////////////////////////////////////////// //
719 // ////////////////////////////////// ThreadPool functionality///////////////////////////// //
720 // //////////////////////////////////////////////////////////////////////////////////////// //
721 protected:
723
724 /**
725 * @brief Executes a given task in a separate thread from the Application ThreadPool.
726 * @param taskName Descriptive name of this task to identify it on errors.
727 * @param task std::function object (or lambda) that is to be executed.
728 * @note This task will be joined in onExitComponent of the NJointControllerBase. So make sure it terminates, when the
729 * controller is deactivated or removed!
730 *
731 * @code{.cpp}
732 * runTask("PlotterTask", [&]
733 {
734 CycleUtil c(30);
735 getObjectScheduler()->waitForObjectStateMinimum(eManagedIceObjectStarted);
736 while (getState() == eManagedIceObjectStarted)
737 {
738 if (isControllerActive())
739 {
740 StringVariantBaseMap errors;
741 for (size_t i = 0; i < sensors.size(); i++)
742 {
743 errors[cfg->jointNames.at(i)] = new Variant(currentError(i));
744 }
745 dbgObs->setDebugChannel("TrajectoryController", errors);
746 }
747 c.waitForCycleDuration();
748 }
749 });
750 * @endcode
751 */
752 template <typename Task>
753 void
754 runTask(const std::string& taskName, Task&& task)
755 {
756 std::unique_lock lock(threadHandlesMutex);
757 ARMARX_CHECK_EXPRESSION(!taskName.empty());
758 ARMARX_CHECK_EXPRESSION(!threadHandles.count(taskName));
759 ARMARX_CHECK_EXPRESSION(getState() < eManagedIceObjectExiting);
760 ARMARX_VERBOSE << "Adding NJointControllerBase task named '" << taskName
761 << "' - current available thread count: "
762 << getThreadPool()->getAvailableTaskCount();
763 auto handlePtr = std::make_shared<ThreadPool::Handle>(getThreadPool()->runTask(task));
764 ARMARX_CHECK_EXPRESSION(handlePtr->isValid())
765 << "Could not add task (" << taskName << " - " << GetTypeString(task)
766 << " ) - available threads: " << getThreadPool()->getAvailableTaskCount();
767 threadHandles[taskName] = handlePtr;
768 }
769
770 std::map<std::string, std::shared_ptr<ThreadPool::Handle>> threadHandles;
772
773 // //////////////////////////////////////////////////////////////////////////////////////// //
774 // ///////////////////////////////////// ice interface //////////////////////////////////// //
775 // //////////////////////////////////////////////////////////////////////////////////////// //
776 public:
777 bool
778 isControllerActive(const Ice::Current& = Ice::emptyCurrent) const final override
779 {
780 return isActive;
781 }
782
783 bool
784 isControllerRequested(const Ice::Current& = Ice::emptyCurrent) const final override
785 {
786 return isRequested;
787 }
788
789 bool
790 isDeletable(const Ice::Current& = Ice::emptyCurrent) const final override
791 {
792 return deletable;
793 }
794
795 bool
796 hasControllerError(const Ice::Current& = Ice::emptyCurrent) const final override
797 {
798 return deactivatedBecauseOfError;
799 }
800
801 std::string getClassName(const Ice::Current& = Ice::emptyCurrent) const override = 0;
802
803 std::string
804 getInstanceName(const Ice::Current& = Ice::emptyCurrent) const final override
805 {
806 return instanceName_;
807 }
808
809 NJointControllerDescription
810 getControllerDescription(const Ice::Current& = Ice::emptyCurrent) const final override;
811 NJointControllerStatus
812 getControllerStatus(const Ice::Current& = Ice::emptyCurrent) const final override;
813 NJointControllerDescriptionWithStatus getControllerDescriptionWithStatus(
814 const Ice::Current& = Ice::emptyCurrent) const final override;
815 //RobotUnitInterfacePrx getRobotUnit(const Ice::Current& = Ice::emptyCurrent) const final override;
816
817 void activateController(const Ice::Current& = Ice::emptyCurrent) override;
818 void deactivateController(const Ice::Current& = Ice::emptyCurrent) override;
819 void deleteController(const Ice::Current& = Ice::emptyCurrent) final override;
820 void deactivateAndDeleteController(const Ice::Current& = Ice::emptyCurrent) final override;
821
823 getFunctionDescriptions(const Ice::Current& = Ice::emptyCurrent) const override
824 {
825 return {};
826 }
827
828 void
829 callDescribedFunction(const std::string&,
831 const Ice::Current& = Ice::emptyCurrent) override
832 {
833 }
834
835 // //////////////////////////////////////////////////////////////////////////////////////// //
836 // ///////////////////////////////////// rt interface ///////////////////////////////////// //
837 // //////////////////////////////////////////////////////////////////////////////////////// //
838 public: ///TODO make protected and use attorneys
839 /**
840 * @brief Returns the virtual robot used by this \ref NJointControllerBase in the \ref rtRun
841 * @return The virtual robot used by this \ref NJointControllerBase in the \ref rtRun
842 * @see useSynchronizedRtRobot
843 * @see rtGetRobotNodes
844 */
847 {
848 return rtRobot;
849 }
850
851 /**
852 * @brief Returns the nodes of the virtual robot used by this \ref NJointControllerBase in the \ref rtRun
853 * @return The nodes of the virtual robot used by this \ref NJointControllerBase in the \ref rtRun
854 * @see useSynchronizedRtRobot
855 * @see rtGetRobot
856 */
857 const std::vector<VirtualRobot::RobotNodePtr>&
859 {
860 return rtRobotNodes;
861 }
862
863 /**
864 * @brief Returns whether this \ref NJointControllerBase calculates a \ref ControlTargetBase "ControlTarget"
865 * for the given \ref ControlDevice
866 * @param deviceIndex The \ref ControlDevice's index
867 * @return Whether this \ref NJointControllerBase calculates a \ref ControlTargetBase "ControlTarget"
868 * for the given \ref ControlDevice
869 */
870 bool
871 rtUsesControlDevice(std::size_t deviceIndex) const
872 {
873 return controlDeviceUsedBitmap.at(deviceIndex);
874 }
875
876 /**
877 * @brief Returns the indices of all \ref ControlDevice's this \ref NJointControllerBase
878 * calculates a \ref ControlTargetBase "ControlTarget" for.
879 * @return The indices of all \ref ControlDevice's this \ref NJointControllerBase
880 * calculates a \ref ControlTargetBase "ControlTarget" for.
881 */
882 const std::vector<std::size_t>&
884 {
885 return controlDeviceUsedIndices;
886 }
887
888 /**
889 * @brief Sets the error state to true. This will deactivate this controller!
890 */
891 bool
893 {
894 return errorState;
895 }
896
897 /**
898 * @brief Returns the number of used \ref ControlDevice "ControlDevices"
899 * @return The number of used \ref ControlDevice "ControlDevices"
900 */
901 std::size_t
903 {
904 return controlDeviceUsedIndices.size();
905 }
906
907 /**
908 * @brief Returns the class name. (the c-string may be used for rt message logging)
909 * @return The class name. (the c-string may be used for rt message logging)
910 */
911 const std::string&
913 {
914 return rtClassName_;
915 }
916
917 /**
918 * @brief Returns the instance name. (the c-string may be used for rt message logging)
919 * @return The instance name. (the c-string may be used for rt message logging)
920 */
921 const std::string&
923 {
924 return instanceName_;
925 }
926
927 protected:
928 /**
929 * @brief This function is called before the controller is activated.
930 * You can use it to activate a thread again (DO NOT SPAWN NEW THREADS!) e.g. via a std::atomic_bool.
931 */
932 virtual void
936
937 /**
938 * @brief This function is called after the controller is deactivated.
939 * You can use it to deactivate a thread (DO NOT JOIN THREADS!) e.g. via a std::atomic_bool.
940 */
941 virtual void
945
946 /**
947 * @brief Sets the error state to true. This will deactivate this controller!
948 */
949 void
951 {
952 errorState.store(true);
953 }
954
955 private:
956 /**
957 * @brief Activates this controller in the \ref RobotUnitModules::ControlThread "ControlThread".
958 *
959 * Calls \ref rtPreActivateController
960 * @see rtDeactivateController
961 * @see rtDeactivateControllerBecauseOfError
962 * @see rtPreActivateController
963 */
964 void rtActivateController();
965 /**
966 * @brief Deactivates this controller in the \ref RobotUnitModules::ControlThread "ControlThread".
967 *
968 * Calls \ref rtPostDeactivateController
969 * @see rtActivateController
970 * @see rtDeactivateControllerBecauseOfError
971 * @see rtPostDeactivateController
972 */
973 void rtDeactivateController();
974 /**
975 * @brief Deactivates this controller in the \ref RobotUnitModules::ControlThread "ControlThread"
976 * and sets the error flag.
977 *
978 * Calls \ref rtPostDeactivateController
979 * This function is called when this \ref NJointControllerBase produces an error
980 * (e.g.: calculates an invalid \ref ControlTargetBase "ControlTarget", throws an exception)
981 * @see rtActivateController
982 * @see rtDeactivateController
983 * @see rtPostDeactivateController
984 */
985 void rtDeactivateControllerBecauseOfError();
986
987 public:
988 static const NJointControllerBasePtr NullPtr;
989
991
992 ~NJointControllerBase() override;
993 //ice interface (must not be called in the rt thread)
994
995 //c++ interface (local calls) (must be called in the rt thread)
996 // //////////////////////////////////////////////////////////////////////////////////////// //
997 // ///////////////////////////////////// used targets ///////////////////////////////////// //
998 // //////////////////////////////////////////////////////////////////////////////////////// //
999 public:
1000 //used control devices
1001 StringStringDictionary
1003 const Ice::Current& = Ice::emptyCurrent) const final override
1004 {
1005 return controlDeviceControlModeMap;
1006 }
1007
1008 const std::vector<char>&
1010 {
1011 return controlDeviceUsedBitmap;
1012 }
1013
1014 const std::vector<std::size_t>&
1016 {
1017 return controlDeviceUsedIndices;
1018 }
1019
1020 const std::map<std::string, const JointController*>&
1022 {
1023 return controlDeviceUsedJointController;
1024 }
1025
1026 //check for conflict
1027 std::optional<std::vector<char>>
1028 isNotInConflictWith(const NJointControllerBasePtr& other) const
1029 {
1030 return isNotInConflictWith(other->getControlDeviceUsedBitmap());
1031 }
1032
1033 std::optional<std::vector<char>> isNotInConflictWith(const std::vector<char>& used) const;
1034
1035 template <class ItT>
1036 static std::optional<std::vector<char>>
1037 AreNotInConflict(ItT first, ItT last)
1038 {
1039 if (first == last)
1040 {
1041 return std::vector<char>{};
1042 }
1043 std::size_t n = (*first)->getControlDeviceUsedBitmap().size();
1044 std::vector<char> inuse(n, false);
1045 while (first != last)
1046 {
1047 auto r = (*first)->isNotInConflictWith(inuse);
1048 if (!r)
1049 {
1050 return r;
1051 }
1052 inuse = std::move(*r);
1053 ++first;
1054 }
1055 return inuse;
1056 }
1057
1058 // //////////////////////////////////////////////////////////////////////////////////////// //
1059 // ////////////////////////////////////// publishing ////////////////////////////////////// //
1060 // //////////////////////////////////////////////////////////////////////////////////////// //
1061 protected:
1062 //publish thread hooks
1063 virtual void
1067
1068 virtual void
1072
1073 virtual void
1077 {
1078 }
1079
1080 private:
1081 void publish(const SensorAndControl& sac,
1082 const DebugDrawerInterfacePrx& draw,
1083 const DebugObserverInterfacePrx& observer);
1084 void deactivatePublish(const DebugDrawerInterfacePrx& draw,
1085 const DebugObserverInterfacePrx& observer);
1086 // //////////////////////////////////////////////////////////////////////////////////////// //
1087 // ///////////////////////////////////////// data ///////////////////////////////////////// //
1088 // //////////////////////////////////////////////////////////////////////////////////////// //
1089 private:
1090 /// @brief reference to the owning \ref RobotUnit
1091 RobotUnit& robotUnit;
1092 /// @brief Maps names of used \ref ControlDevice "ControlDevices" to the \ref JointController "JointController's" control mode
1093 StringStringDictionary controlDeviceControlModeMap;
1094 /// @brief Maps names of used \ref ControlDevice "ControlDevices" to the used \ref JointController for this \ref ControlDevice
1095 std::map<std::string, const JointController*> controlDeviceUsedJointController;
1096 /// @brief Bitmap of used \ref ControlDevice "ControlDevices" (1 == used, 0 == not used)
1097 std::vector<char> controlDeviceUsedBitmap;
1098 /// @brief Indices of used \ref ControlDevice "ControlDevices"
1099 std::vector<std::size_t> controlDeviceUsedIndices;
1100
1101 std::string rtClassName_;
1102 std::string instanceName_;
1103
1104 //this data is filled by the robot unit to provide convenience functions
1105 std::atomic_bool isActive{false};
1106 std::atomic_bool isRequested{false};
1107 std::atomic_bool deactivatedBecauseOfError{false};
1108 std::atomic_bool errorState{false};
1109 bool deletable{false};
1110 bool internal{false};
1111
1112 std::atomic_bool publishActive{false};
1113
1114 std::atomic_bool statusReportedActive{false};
1115 std::atomic_bool statusReportedRequested{false};
1116
1117 VirtualRobot::RobotPtr rtRobot;
1118 std::vector<VirtualRobot::RobotNodePtr> rtRobotNodes;
1119 // //////////////////////////////////////////////////////////////////////////////////////// //
1120 // /////////////////////////////////////// friends //////////////////////////////////////// //
1121 // //////////////////////////////////////////////////////////////////////////////////////// //
1122 private:
1123 /**
1124 * \brief This class allows minimal access to private members of \ref NJointControllerBase in a sane fashion for \ref RobotUnitModule::ControllerManagement.
1125 * \warning !! DO NOT ADD ADDITIONAL FRIENDS IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
1126 */
1128 /**
1129 * \brief This class allows minimal access to private members of \ref NJointControllerBase in a sane fashion for \ref RobotUnitModule::ControlThread.
1130 * \warning !! DO NOT ADD ADDITIONAL FRIENDS IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
1131 */
1133 /**
1134 * \brief This class allows minimal access to private members of \ref NJointControllerBase in a sane fashion for \ref RobotUnitModule::Publisher.
1135 * \warning !! DO NOT ADD ADDITIONAL FRIENDS IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
1136 */
1138 /**
1139 * \brief This is required for the factory
1140 * \warning !! DO NOT ADD ADDITIONAL FRIENDS IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
1141 */
1142 template <class>
1144 };
1145
1147 {
1148 public: ///TODO make protected and use attorneys
1149 virtual void rtRun(const IceUtil::Time& sensorValuesTimestamp,
1150 const IceUtil::Time& timeSinceLastIteration) = 0;
1151
1152 virtual void
1153 rtSwapBufferAndRun(const IceUtil::Time& sensorValuesTimestamp,
1154 const IceUtil::Time& timeSinceLastIteration)
1155 {
1156 rtRun(sensorValuesTimestamp, timeSinceLastIteration);
1157 }
1158 };
1159
1161 {
1162 public: ///TODO make protected and use attorneys
1163 virtual void rtRunIterationBegin(const IceUtil::Time& sensorValuesTimestamp,
1164 const IceUtil::Time& timeSinceLastIteration) = 0;
1165 virtual void rtRunIterationEnd(const IceUtil::Time& sensorValuesTimestamp,
1166 const IceUtil::Time& timeSinceLastIteration) = 0;
1167 };
1168
1170 using NJointControllerPtr = SynchronousNJointControllerPtr;
1171} // namespace armarx
#define TYPEDEF_PTRS_HANDLE(T)
virtual void rtRunIterationEnd(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration)=0
virtual void rtRunIterationBegin(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration)=0
TODO make protected and use attorneys.
Brief description of class JointControlTargetBase.
The JointController class represents one joint in one control mode.
ManagedIceObject(ManagedIceObject const &other)
int getState() const
Retrieve current state of the ManagedIceObject.
A high level controller writing its results into ControlTargets.
void rtSetErrorState()
Sets the error state to true.
bool isControllerActive(const Ice::Current &=Ice::emptyCurrent) const final override
const SensorValueBase * useSensorValue(const std::string &sensorDeviceName) const
Get a const ptr to the given SensorDevice's SensorValue.
ConfigPrtType(*)(const StringVariantBaseMap &) GenerateConfigFromVariantsFunctionSignature
void callDescribedFunction(const std::string &, const StringVariantBaseMap &, const Ice::Current &=Ice::emptyCurrent) override
std::size_t rtGetNumberOfUsedControlDevices() const
Returns the number of used ControlDevices.
const T * useSensorValue(const std::string &deviceName) const
Get a const ptr to the given SensorDevice's SensorValue.
virtual void rtPostDeactivateController()
This function is called after the controller is deactivated.
void runTask(const std::string &taskName, Task &&task)
Executes a given task in a separate thread from the Application ThreadPool.
virtual void rtPreActivateController()
This function is called before the controller is activated.
std::string getClassName(const Ice::Current &=Ice::emptyCurrent) const override=0
void deactivateController(const Ice::Current &=Ice::emptyCurrent) override
bool rtUsesControlDevice(std::size_t deviceIndex) const
Returns whether this NJointControllerBase calculates a ControlTarget for the given ControlDevice.
NJointControllerStatus getControllerStatus(const Ice::Current &=Ice::emptyCurrent) const final override
const std::map< std::string, const JointController * > & getControlDevicesUsedJointController()
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
std::optional< std::vector< char > > isNotInConflictWith(const NJointControllerBasePtr &other) const
NJointControllerConfigPtr ConfigPtrT
const std::string & rtGetClassName() const
Returns the class name.
const std::vector< char > & getControlDeviceUsedBitmap() const
void deleteController(const Ice::Current &=Ice::emptyCurrent) final override
bool hasControllerError(const Ice::Current &=Ice::emptyCurrent) const final override
const std::vector< VirtualRobot::RobotNodePtr > & rtGetRobotNodes()
Returns the nodes of the virtual robot used by this NJointControllerBase in the rtRun.
const std::vector< std::size_t > & getControlDeviceUsedIndices() const
virtual void onPublishActivation(const DebugDrawerInterfacePrx &, const DebugObserverInterfacePrx &)
const VirtualRobot::RobotPtr & rtGetRobot()
TODO make protected and use attorneys.
bool isDeletable(const Ice::Current &=Ice::emptyCurrent) const final override
ConstControlDevicePtr peekControlDevice(const std::string &deviceName) const
Get a const ptr to the given ControlDevice.
T * useControlTarget(const std::string &deviceName, const std::string &controlMode)
Declares to calculate the ControlTarget for the given ControlDevice in the given ControlMode when rtR...
const std::string & rtGetInstanceName() const
Returns the instance name.
void activateController(const Ice::Current &=Ice::emptyCurrent) override
virtual void onPublishDeactivation(const DebugDrawerInterfacePrx &, const DebugObserverInterfacePrx &)
bool isControllerRequested(const Ice::Current &=Ice::emptyCurrent) const final override
bool rtGetErrorState() const
Sets the error state to true.
const std::vector< std::size_t > & rtGetControlDeviceUsedIndices() const
Returns the indices of all ControlDevice's this NJointControllerBase calculates a ControlTarget for.
virtual void onPublish(const SensorAndControl &, const DebugDrawerInterfacePrx &, const DebugObserverInterfacePrx &)
ConstSensorDevicePtr peekSensorDevice(const std::string &deviceName) const
Get a const ptr to the given SensorDevice.
WidgetDescription::StringWidgetDictionary getFunctionDescriptions(const Ice::Current &=Ice::emptyCurrent) const override
StringStringDictionary getControlDeviceUsedControlModeMap(const Ice::Current &=Ice::emptyCurrent) const final override
NJointControllerDescription getControllerDescription(const Ice::Current &=Ice::emptyCurrent) const final override
NJointControllerDescriptionWithStatus getControllerDescriptionWithStatus(const Ice::Current &=Ice::emptyCurrent) const final override
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...
std::map< std::string, std::shared_ptr< ThreadPool::Handle > > threadHandles
static const NJointControllerBasePtr NullPtr
void deactivateAndDeleteController(const Ice::Current &=Ice::emptyCurrent) final override
ThreadPoolPtr getThreadPool() const
std::string getDefaultName() const override
WidgetDescription::WidgetPtr(*)( const VirtualRobot::RobotPtr &, const std::map< std::string, ConstControlDevicePtr > &controlDevices, const std::map< std::string, ConstSensorDevicePtr > &sensorDevices) GenerateConfigDescriptionFunctionSignature
static std::optional< std::vector< char > > AreNotInConflict(ItT first, ItT last)
This class allows minimal access to private members of NJointControllerBase in a sane fashion for Con...
This class allows minimal access to private members of NJointControllerBase in a sane fashion for Con...
This class allows minimal access to private members of NJointControllerBase in a sane fashion for Pub...
The RobotUnit class manages a robot and its controllers.
Definition RobotUnit.h:192
The SensorValueBase class.
virtual void rtSwapBufferAndRun(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration)
virtual void rtRun(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration)=0
TODO make protected and use attorneys.
#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_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
std::shared_ptr< class Robot > RobotPtr
Definition Bus.h:19
::IceInternal::Handle<::armarx::WidgetDescription::Widget > WidgetPtr
::std::map<::std::string, ::armarx::WidgetDescription::WidgetPtr > StringWidgetDictionary
This file offers overloads of toIce() and fromIce() functions for STL container types.
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugObserverInterface > DebugObserverInterfacePrx
::IceInternal::ProxyHandle<::IceProxy::armarx::RobotUnitInterface > RobotUnitInterfacePrx
std::map< std::string, VariantBasePtr > StringVariantBaseMap
std::string GetTypeString(const std::type_info &tinf, bool withoutNamespaceSpecifier=false)
std::shared_ptr< ThreadPool > ThreadPoolPtr
Definition Application.h:76
SynchronousNJointController NJointController
std::shared_ptr< const class ControlDevice > ConstControlDevicePtr
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugDrawerInterface > DebugDrawerInterfacePrx
SynchronousNJointControllerPtr NJointControllerPtr
detail::ControlThreadOutputBufferEntry SensorAndControl
std::shared_ptr< const class SensorDevice > ConstSensorDevicePtr