RobotUnitModuleControlThread.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::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#pragma once
24
25#include <thread>
26
27#include <RobotAPI/interface/units/RobotUnit/RobotUnitInterface.h>
28
31#include "RobotUnitModuleBase.h"
32
33namespace armarx
34{
35 class DynamicsHelper;
37} // namespace armarx
38
40{
42 {
43 public:
45 {
47 "NjointController_AllowedExecutionTimePerControlDeviceUntilWarning",
48 2,
49 "A Warning will be printed, If the execution time in micro seconds of a "
50 "NJointControllerBase "
51 "exceeds this parameter times the number of ControlDevices.");
53 "NjointController_AllowedExecutionTimePerControlDeviceUntilError",
54 20,
55 "An Error will be printed, If the execution time in micro seconds of a "
56 "NJointControllerBase "
57 "exceeds this parameter times the number of ControlDevices.");
59 "EnableInverseDynamics",
60 false,
61 "If true, inverse dynamics are calculated for all joints given in the "
62 "InverseDynamicsRobotJointSets property during each loop of "
63 "the rt control thread.");
64 defineOptionalProperty<std::string>("InverseDynamicsRobotJointSets",
65 "LeftArm,RightArm",
66 "Comma separated list of robot nodesets for which "
67 "the inverse dynamics should be calculcated.");
69 "InverseDynamicsRobotBodySet",
70 "RobotCol",
71 "Robot nodeset of which the masses should be used for the inverse dynamics");
72 }
73 };
74
75 /**
76 * @ingroup Library-RobotUnit-Modules
77 * @brief This \ref ModuleBase "Module" manages the \ref ControlThread.
78 *
79 * It offers the basic functions called in the \ref ControlThread.
80 *
81 * @see ModuleBase
82 */
83 class ControlThread : virtual public ModuleBase, virtual public RobotUnitControlThreadInterface
84 {
85 friend class ModuleBase;
86 enum class EmergencyStopStateRequest
87 {
88 RequestActive,
89 RequestInactive,
90 RequestNone,
91 };
92
93 protected:
95 {
96 /**
97 * @brief This modus is used if the RTThread is supported to control
98 * which controllers are running. (e.g. for Calibrating)
99 */
102 };
103
104 public:
105 /**
106 * @brief Returns the singleton instance of this class
107 * @return The singleton instance of this class
108 */
109 static ControlThread&
114
115 // //////////////////////////////////////////////////////////////////////////////////////// //
116 // ///////////////////////////////// RobotUnitModule hooks //////////////////////////////// //
117 // //////////////////////////////////////////////////////////////////////////////////////// //
118 private:
119 ///@see \ref ModuleBase::_preFinishControlThreadInitialization
120 void _preFinishControlThreadInitialization();
121 ///@see \ref ModuleBase::_preOnInitRobotUnit
122 void _preOnInitRobotUnit();
123 // //////////////////////////////////////////////////////////////////////////////////////// //
124 // ///////////////////////////////////// ice interface //////////////////////////////////// //
125 // //////////////////////////////////////////////////////////////////////////////////////// //
126 public:
127 /**
128 * @brief Sets the \ref EmergencyStopState
129 * @param state The \ref EmergencyStopState to set
130 */
131 void setEmergencyStopState(EmergencyStopState state);
132
133 /**
134 * @brief Returns the \ref ControlThread's target \ref EmergencyStopState
135 * @return The \ref EmergencyStopState
136 */
137 EmergencyStopState getEmergencyStopState() const;
138
139 /**
140 * @brief Returns the \ref ControlThread's \ref EmergencyStopState
141 * @return The \ref EmergencyStopState
142 */
143 EmergencyStopState getRtEmergencyStopState() const;
144 // //////////////////////////////////////////////////////////////////////////////////////// //
145 // /////////////////////////////////// Module interface /////////////////////////////////// //
146 // //////////////////////////////////////////////////////////////////////////////////////// //
147 public:
148 /**
149 * @brief Teturns he \ref ControlThread's thread id
150 * @return The \ref ControlThread's thread id
151 * @see controlThreadId
152 */
153 std::thread::id
155 {
156 return controlThreadId;
157 }
158
159 private:
160 /**
161 * @brief Sets the \ref EmergencyStopState without updating the topic.
162 * For use in \ref RobotUnitEmergencyStopMaster.
163 * @param state The \ref EmergencyStopState to set
164 */
165 void setEmergencyStopStateNoReportToTopic(EmergencyStopState state);
166 /**
167 * @brief Sets the emergency stop state to the request from rt (if there was a request).
168 * For use in \ref Publisher.
169 */
170 void processEmergencyStopRequest();
171
172 // //////////////////////////////////////////////////////////////////////////////////////// //
173 // ///////////////////////////////////// rt interface ///////////////////////////////////// //
174 // //////////////////////////////////////////////////////////////////////////////////////// //
175 protected:
176 /**
177 * @brief Returns the simox robot used in the control thread
178 * @return The simox robot used in the control thread
179 */
182 {
183 return rtRobot;
184 }
185
186 /**
187 * @brief Changes the set of active controllers.
188 * Changes can be caused by a new set of requested controllers or emergency stop
189 * @return Whether active controllers were changed
190 */
192
193 /**
194 * @brief Searches for the \ref NJointControllerBase responsible for the given \ref JointController and deactivates it.
195 * Does not commit the new set of activated controllers)
196 * @param ctrlDevIndex The control device index causing the problem.
197 */
198 void rtDeactivateAssignedNJointControllerBecauseOfError(std::size_t ctrlDevIndex);
199 /**
200 * @brief Deactivates a NJointControllerBase and sets all used ControlDevices to EmergencyStop.
201 * Does not commit the new set of activated controllers)
202 * @param nJointCtrlIndex The NJointControllerBase to deactivate (index in controllersActivated)
203 */
204 void rtDeactivateNJointControllerBecauseOfError(std::size_t nJointCtrlIndex);
205 /**
206 * @brief Runs NJoint controllers
207 * @param sensorValuesTimestamp Timestamp of the current \ref SensorValueBase SensorValues
208 * @param timeSinceLastIteration Time between the last two updates of \ref SensorValueBase SensorValues
209 */
210 void rtRunNJointControllers(const IceUtil::Time& sensorValuesTimestamp,
211 const IceUtil::Time& timeSinceLastIteration);
212 /**
213 * @brief Runs Joint controllers and writes target values to ControlDevices
214 * @param sensorValuesTimestamp Timestamp of the current \ref SensorValueBase SensorValues
215 * @param timeSinceLastIteration Time between the last two updates of \ref SensorValueBase SensorValues
216 */
217 void rtRunJointControllers(const IceUtil::Time& sensorValuesTimestamp,
218 const IceUtil::Time& timeSinceLastIteration);
219 /**
220 * @brief Calls \ref SensorDevice::rtReadSensorValues for all \ref SensorDevice "SensorDevices".
221 * @param sensorValuesTimestamp Timestamp of the current \ref SensorValueBase SensorValues
222 * @param timeSinceLastIteration Time between the last two updates of \ref SensorValueBase SensorValues
223 */
224 void rtReadSensorDeviceValues(const IceUtil::Time& sensorValuesTimestamp,
225 const IceUtil::Time& timeSinceLastIteration);
226 /**
227 * @brief Execute code after updating the sensor values. Default implementation calculates the inverse dynamics.
228 * @param sensorValuesTimestamp Timestamp of the current \ref SensorValueBase SensorValues
229 * @param timeSinceLastIteration Time between the last two updates of \ref SensorValueBase SensorValues
230 */
231 void virtual rtPostReadSensorDeviceValues(const IceUtil::Time& sensorValuesTimestamp,
232 const IceUtil::Time& timeSinceLastIteration);
233 /// @brief Deactivates all NJointControllers generating invalid targets.
235 /// @brief Calls \ref JointController::rtResetTarget for all active Joint controllers
236 void rtResetAllTargets();
237
238 /**
239 * @brief Hook for deriving classes (called AFTER a NJointControllerBase is deactivated due to an error)
240 *
241 * This is useful when two Control devices can be controlled by different NJointControllers but either both or none
242 * have to be controlled.
243 *
244 * Since this hook is called after the controller with an error was deactivated an other call to
245 * \ref rtDeactivateAssignedNJointControllerBecauseOfError can't lead to a cyclic execution.
246 */
247 virtual void
248 rtDeactivatedNJointControllerBecauseOfError(const NJointControllerBasePtr& /*nJointCtrl*/)
249 {
250 }
251
252 /**
253 * @brief Updates the current \ref SensorValueBase "SensorValues" and \ref ControlTargetBase "ControlTargets"
254 * for code running outside of the \ref ControlThread
255 * @param sensorValuesTimestamp Timestamp of the current \ref SensorValueBase SensorValues
256 * @param timeSinceLastIteration Time between the last two updates of \ref SensorValueBase SensorValues
257 */
258 void rtUpdateSensorAndControlBuffer(const IceUtil::Time& sensorValuesTimestamp,
259 const IceUtil::Time& timeSinceLastIteration);
260
261 /**
262 * @brief Returns all \ref ControlDevice "ControlDevices"
263 * @return All \ref ControlDevice "ControlDevices"
264 */
265 const std::vector<ControlDevicePtr>& rtGetControlDevices() const;
266 /**
267 * @brief Returns all \ref SensorDevice "SensorDevices"
268 * @return All \ref SensorDevice "SensorDevices"
269 */
270 const std::vector<SensorDevicePtr>& rtGetSensorDevices();
271 /**
272 * @brief Returns the \ref RTThreadTimingsSensorDevice
273 * @return The \ref RTThreadTimingsSensorDevice
274 */
276
277 /**
278 * @brief Returns whether the rt thread is in emergency stop. (This function is for use in the \ref ControlThread)
279 * @return Whether the rt thread is in emergency stop.
280 */
281 bool
283 {
284 return rtIsInEmergencyStop_;
285 }
286
287 /**
288 * @brief Returns the \ref ControlThread's emergency stop state. (This function is for use in the \ref ControlThread)
289 * @return The \ref ControlThread's emergency stop state
290 */
291 EmergencyStopState
293 {
294 return rtIsInEmergencyStop_ ? EmergencyStopState::eEmergencyStopActive
295 : EmergencyStopState::eEmergencyStopInactive;
296 }
297
298 /**
299 * @brief Set an \ref EmergencyStopState request. This request will be executed by the \ref Publisher
300 * @param state The \ref EmergencyStopState to set
301 */
302 void rtSetEmergencyStopState(EmergencyStopState state);
303
305 void rtSetRobotGlobalPose(const Eigen::Matrix4f& gp, bool updateRobot = true);
306
307 /// Activate a joint controller from the rt loop (only works in switch mode RTThread)
308 void rtSetJointController(JointController* c, std::size_t index);
309 // //////////////////////////////////////////////////////////////////////////////////////// //
310 // //////////////////////////////////// implementation //////////////////////////////////// //
311 // //////////////////////////////////////////////////////////////////////////////////////// //
312 private:
313 /**
314 * @brief Returns the activated \ref JointController "JointControllers"
315 * @return The activated \ref JointController "JointControllers"
316 */
317 std::vector<JointController*>& rtGetActivatedJointControllers();
318 const std::vector<JointController*>& rtGetActivatedJointControllers() const;
319 /**
320 * @brief Returns the activated \ref NJointControllerBase "NJointControllers"
321 * @return The activated \ref NJointControllerBase "NJointControllers"
322 */
323 std::vector<NJointControllerBase*>& rtGetActivatedNJointControllers();
324 const std::vector<NJointControllerBase*>& rtGetActivatedNJointControllers() const;
325
326 /**
327 * @brief Returns a vector containing the index of the activated \ref NJointControllerBase
328 * for each \ref JointController
329 * @return A vector containing the index of the activated \ref NJointControllerBase
330 * for each \ref JointController
331 */
332 std::vector<std::size_t>& rtGetActivatedJointToNJointControllerAssignement();
333 const std::vector<std::size_t>& rtGetActivatedJointToNJointControllerAssignement() const;
334
335
336 /**
337 * @brief Returns the requested \ref JointController "JointControllers"
338 * @return The requested \ref JointController "JointControllers"
339 */
340 const std::vector<JointController*>& rtGetRequestedJointControllers() const;
341 /**
342 * @brief Returns the requested \ref NJointControllerBase "NJointControllers"
343 * @return The requested \ref NJointControllerBase "NJointControllers"
344 */
345 const std::vector<NJointControllerBase*>& rtGetRequestedNJointControllers() const;
346
347 /**
348 * @brief Returns a vector containing the index of the requested \ref NJointControllerBase
349 * for each \ref JointController
350 * @return A vector containing the index of the requested \ref NJointControllerBase
351 * for each \ref JointController
352 */
353 const std::vector<std::size_t>& rtGetRequestedJointToNJointControllerAssignement() const;
354
355 void rtSyncNJointControllerRobot(NJointControllerBase* njctrl);
356
357 void dumpRtControllerSetup(std::ostream& out,
358 const std::string& indent,
359 const std::vector<JointController*>& activeCdevs,
360 const std::vector<std::size_t>& activeJCtrls,
361 const std::vector<NJointControllerBase*>& assignement) const;
362 std::string dumpRtState() const;
363 // //////////////////////////////////////////////////////////////////////////////////////// //
364 // ///////////////////////////////////////// Data ///////////////////////////////////////// //
365 // //////////////////////////////////////////////////////////////////////////////////////// //
366 private:
367 ///@brief Whether the ControlThread is in emergency stop
368 std::atomic_bool rtIsInEmergencyStop_{false};
369 ///@brief Whether the ControlThread is supposed to be in emergency stop
370 std::atomic_bool emergencyStop{false};
371
372 ///@brief The \ref VirtualRobot::Robot used in the \ref ControlThread
374 ///@brief The \ref VirtualRobot::Robot's \ref VirtualRobot::RobotNode "VirtualRobot::RobotNode" used in the \ref ControlThread
375 std::vector<VirtualRobot::RobotNodePtr> rtRobotNodes;
376
377 ///@brief The \ref ControlThread's thread id
378 std::atomic<std::thread::id> controlThreadId;
379
380 /// @brief A Warning will be printed, if the execution time per ControlDev of a NJointControllerBase exceeds this parameter
381 std::size_t usPerDevUntilWarn;
382 /// @brief An Error will be printed, if the execution time per ControlDev of a NJointControllerBase exceeds this parameter
383 std::size_t usPerDevUntilError;
384
385 bool rtSwitchControllerSetupChangedControllers{false};
386 std::size_t numberOfInvalidTargetsInThisIteration{0};
387
388 std::vector<JointController*> preSwitchSetup_ActivatedJointControllers;
389 std::vector<std::size_t> preSwitchSetup_ActivatedJointToNJointControllerAssignement;
390 std::vector<NJointControllerBase*> preSwitchSetup_ActivatedNJointControllers;
391
392 std::vector<JointController*> postSwitchSetup_ActivatedJointControllers;
393 std::vector<std::size_t> postSwitchSetup_ActivatedJointToNJointControllerAssignement;
394 std::vector<NJointControllerBase*> postSwitchSetup_ActivatedNJointControllers;
395
396 std::vector<std::size_t> _activatedSynchronousNJointControllersIdx;
397 std::vector<std::size_t> _activatedAsynchronousNJointControllersIdx;
398
399 std::atomic<EmergencyStopStateRequest> emergencyStopStateRequest{
400 EmergencyStopStateRequest::RequestNone};
401
402 std::shared_ptr<DynamicsHelper> dynamicsHelpers;
403
404 std::size_t _maxControllerCount = 0;
405 // //////////////////////////////////////////////////////////////////////////////////////// //
406 // /////////////////////////////////////// Attorneys ////////////////////////////////////// //
407 // //////////////////////////////////////////////////////////////////////////////////////// //
408 private:
409 /**
410 * \brief This class allows minimal access to private members of \ref ControlThread in a sane fashion for \ref Publisher.
411 * \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 !!
412 */
414 /**
415 * \brief This class allows minimal access to private members of \ref ControlThread in a sane fashion for \ref RobotUnitEmergencyStopMaster.
416 * \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 !!
417 */
419 };
420} // namespace armarx::RobotUnitModule
uint8_t index
constexpr T c
The JointController class represents one joint in one control mode.
A high level controller writing its results into ControlTargets.
std::string prefix
Prefix of the properties such as namespace, domain, component name, etc.
PropertyDefinition< PropertyType > & defineOptionalProperty(const std::string &name, PropertyType defaultValue, const std::string &description="", PropertyDefinitionBase::PropertyConstness constness=PropertyDefinitionBase::eConstant)
This Module manages the ControlThread.
@ RTThread
This modus is used if the RTThread is supported to control which controllers are running.
EmergencyStopState getEmergencyStopState() const
Returns the ControlThread's target EmergencyStopState.
void rtSetJointController(JointController *c, std::size_t index)
Activate a joint controller from the rt loop (only works in switch mode RTThread)
friend class ControlThreadAttorneyForRobotUnitEmergencyStopMaster
This class allows minimal access to private members of ControlThread in a sane fashion for RobotUnitE...
static ControlThread & Instance()
Returns the singleton instance of this class.
void setEmergencyStopState(EmergencyStopState state)
Sets the EmergencyStopState.
const std::vector< ControlDevicePtr > & rtGetControlDevices() const
Returns all ControlDevices.
const std::vector< SensorDevicePtr > & rtGetSensorDevices()
Returns all SensorDevices.
std::thread::id getControlThreadId() const
Teturns he ControlThread's thread id.
void rtResetAllTargets()
Calls rtResetTarget for all active Joint controllers.
void rtUpdateSensorAndControlBuffer(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration)
Updates the current SensorValues and ControlTargets for code running outside of the ControlThread.
void rtHandleInvalidTargets()
Deactivates all NJointControllers generating invalid targets.
EmergencyStopState rtGetEmergencyStopState() const
Returns the ControlThread's emergency stop state.
RTThreadTimingsSensorDevice & rtGetThreadTimingsSensorDevice()
Returns the RTThreadTimingsSensorDevice.
virtual void rtDeactivatedNJointControllerBecauseOfError(const NJointControllerBasePtr &)
Hook for deriving classes (called AFTER a NJointControllerBase is deactivated due to an error)
friend class ControlThreadAttorneyForPublisher
This class allows minimal access to private members of ControlThread in a sane fashion for Publisher.
bool rtSwitchControllerSetup(SwitchControllerMode mode=SwitchControllerMode::IceRequests)
Changes the set of active controllers.
void rtDeactivateAssignedNJointControllerBecauseOfError(std::size_t ctrlDevIndex)
Searches for the NJointControllerBase responsible for the given JointController and deactivates it.
const VirtualRobot::RobotPtr & rtGetRobot() const
Returns the simox robot used in the control thread.
void rtSetEmergencyStopState(EmergencyStopState state)
Set an EmergencyStopState request.
void rtDeactivateNJointControllerBecauseOfError(std::size_t nJointCtrlIndex)
Deactivates a NJointControllerBase and sets all used ControlDevices to EmergencyStop.
EmergencyStopState getRtEmergencyStopState() const
Returns the ControlThread's EmergencyStopState.
void rtRunNJointControllers(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration)
Runs NJoint controllers.
bool rtIsInEmergencyStop() const
Returns whether the rt thread is in emergency stop.
void rtSetRobotGlobalPose(const Eigen::Matrix4f &gp, bool updateRobot=true)
void rtRunJointControllers(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration)
Runs Joint controllers and writes target values to ControlDevices.
virtual void rtPostReadSensorDeviceValues(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration)
Execute code after updating the sensor values.
void rtReadSensorDeviceValues(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration)
Calls rtReadSensorValues for all SensorDevices.
static ModuleBase & Instance()
Returns the singleton instance of this class.
std::shared_ptr< class Robot > RobotPtr
Definition Bus.h:19
This file offers overloads of toIce() and fromIce() functions for STL container types.