forked from ros-controls/ros2_control
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcontroller_manager.hpp
More file actions
597 lines (511 loc) · 25.4 KB
/
Copy pathcontroller_manager.hpp
File metadata and controls
597 lines (511 loc) · 25.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
// Copyright 2020 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CONTROLLER_MANAGER__CONTROLLER_MANAGER_HPP_
#define CONTROLLER_MANAGER__CONTROLLER_MANAGER_HPP_
#include <map>
#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include "controller_interface/chainable_controller_interface.hpp"
#include "controller_interface/controller_interface.hpp"
#include "controller_interface/controller_interface_base.hpp"
#include "controller_manager/controller_spec.hpp"
#include "controller_manager_msgs/srv/configure_controller.hpp"
#include "controller_manager_msgs/srv/list_controller_types.hpp"
#include "controller_manager_msgs/srv/list_controllers.hpp"
#include "controller_manager_msgs/srv/list_hardware_components.hpp"
#include "controller_manager_msgs/srv/list_hardware_interfaces.hpp"
#include "controller_manager_msgs/srv/load_controller.hpp"
#include "controller_manager_msgs/srv/reload_controller_libraries.hpp"
#include "controller_manager_msgs/srv/set_hardware_component_state.hpp"
#include "controller_manager_msgs/srv/switch_controller.hpp"
#include "controller_manager_msgs/srv/unload_controller.hpp"
#include "diagnostic_updater/diagnostic_updater.hpp"
#include "hardware_interface/resource_manager.hpp"
#include "pluginlib/class_loader.hpp"
#include "rclcpp/executor.hpp"
#include "rclcpp/node.hpp"
#include "std_msgs/msg/string.hpp"
namespace controller_manager
{
class ParamListener;
class Params;
using ControllersListIterator = std::vector<controller_manager::ControllerSpec>::const_iterator;
rclcpp::NodeOptions get_cm_node_options();
class ControllerManager : public rclcpp::Node
{
public:
static constexpr bool kWaitForAllResources = false;
static constexpr auto kInfiniteTimeout = 0;
ControllerManager(
std::unique_ptr<hardware_interface::ResourceManager> resource_manager,
std::shared_ptr<rclcpp::Executor> executor,
const std::string & manager_node_name = "controller_manager",
const std::string & node_namespace = "",
const rclcpp::NodeOptions & options = get_cm_node_options());
ControllerManager(
std::shared_ptr<rclcpp::Executor> executor,
const std::string & manager_node_name = "controller_manager",
const std::string & node_namespace = "",
const rclcpp::NodeOptions & options = get_cm_node_options());
ControllerManager(
std::shared_ptr<rclcpp::Executor> executor, const std::string & urdf,
bool activate_all_hw_components, const std::string & manager_node_name = "controller_manager",
const std::string & node_namespace = "",
const rclcpp::NodeOptions & options = get_cm_node_options());
virtual ~ControllerManager();
void robot_description_callback(const std_msgs::msg::String & msg);
void init_resource_manager(const std::string & robot_description);
controller_interface::ControllerInterfaceBaseSharedPtr load_controller(
const std::string & controller_name, const std::string & controller_type);
/// load_controller loads a controller by name, the type must be defined in the parameter server.
/**
* \param[in] controller_name as a string.
* \return controller
* \see Documentation in controller_manager_msgs/LoadController.srv
*/
controller_interface::ControllerInterfaceBaseSharedPtr load_controller(
const std::string & controller_name);
controller_interface::return_type unload_controller(const std::string & controller_name);
std::vector<ControllerSpec> get_loaded_controllers() const;
template <
typename T, typename std::enable_if<
std::is_convertible<T *, controller_interface::ControllerInterfaceBase *>::value,
T>::type * = nullptr>
controller_interface::ControllerInterfaceBaseSharedPtr add_controller(
std::shared_ptr<T> controller, const std::string & controller_name,
const std::string & controller_type)
{
ControllerSpec controller_spec;
controller_spec.c = controller;
controller_spec.info.name = controller_name;
controller_spec.info.type = controller_type;
controller_spec.last_update_cycle_time = std::make_shared<rclcpp::Time>(0);
return add_controller_impl(controller_spec);
}
controller_interface::ControllerInterfaceBaseSharedPtr add_controller(
const ControllerSpec & controller_spec)
{
return add_controller_impl(controller_spec);
}
/// configure_controller Configure controller by name calling their "configure" method.
/**
* \param[in] controller_name as a string.
* \return configure controller response
* \see Documentation in controller_manager_msgs/ConfigureController.srv
*/
controller_interface::return_type configure_controller(const std::string & controller_name);
/// switch_controller Deactivates some controllers and activates others.
/**
* \param[in] activate_controllers is a list of controllers to activate.
* \param[in] deactivate_controllers is a list of controllers to deactivate.
* \param[in] set level of strictness (BEST_EFFORT or STRICT)
* \see Documentation in controller_manager_msgs/SwitchController.srv
*/
controller_interface::return_type switch_controller(
const std::vector<std::string> & activate_controllers,
const std::vector<std::string> & deactivate_controllers, int strictness,
bool activate_asap = kWaitForAllResources,
const rclcpp::Duration & timeout = rclcpp::Duration::from_nanoseconds(kInfiniteTimeout));
/// Read values to state interfaces.
/**
* Read current values from hardware to state interfaces.
* **The method called in the (real-time) control loop.**
*
* \param[in] time The time at the start of this control loop iteration
* \param[in] period The measured period of the last control loop iteration
*/
void read(const rclcpp::Time & time, const rclcpp::Duration & period);
/// Run update on controllers
/**
* Call update of all controllers.
* **The method called in the (real-time) control loop.**
*
* \param[in] time The time at the start of this control loop iteration
* \param[in] period The measured period of the last control loop iteration
*/
controller_interface::return_type update(
const rclcpp::Time & time, const rclcpp::Duration & period);
/// Write values from command interfaces.
/**
* Write values from command interface into hardware.
* **The method called in the (real-time) control loop.**
*
* \param[in] time The time at the start of this control loop iteration
* \param[in] period The measured period of the last control loop iteration
*/
void write(const rclcpp::Time & time, const rclcpp::Duration & period);
/// Deterministic (real-time safe) callback group, e.g., update function.
/**
* Deterministic (real-time safe) callback group for the update function. Default behavior
* is read hardware, update controller and finally write new values to the hardware.
*/
// TODO(anyone): Due to issues with the MutliThreadedExecutor, this control loop does not rely on
// the executor (see issue #260).
// rclcpp::CallbackGroup::SharedPtr deterministic_callback_group_;
/// Interface for external components to check if Resource Manager is initialized.
/**
* Checks if components in Resource Manager are loaded and initialized.
* \returns true if they are initialized, false otherwise.
*/
bool is_resource_manager_initialized() const
{
return resource_manager_ && resource_manager_->are_components_initialized();
}
/// Update rate of the main control loop in the controller manager.
/**
* Update rate of the main control loop in the controller manager.
* The method is used for per-controller update rate support.
*
* \returns update rate of the controller manager.
*/
unsigned int get_update_rate() const;
protected:
void init_services();
controller_interface::ControllerInterfaceBaseSharedPtr add_controller_impl(
const ControllerSpec & controller);
void manage_switch();
/// Deactivate chosen controllers from real-time controller list.
/**
* Deactivate controllers with names \p controllers_to_deactivate from list \p rt_controller_list.
* The controller list will be iterated as many times as there are controller names.
*
* \param[in] rt_controller_list controllers in the real-time list.
* \param[in] controllers_to_deactivate names of the controller that have to be deactivated.
*/
void deactivate_controllers(
const std::vector<ControllerSpec> & rt_controller_list,
const std::vector<std::string> controllers_to_deactivate);
/**
* Switch chained mode for all the controllers with respect to the following cases:
* - a preceding controller is getting activated --> switch controller to chained mode;
* - all preceding controllers are deactivated --> switch controller from chained mode.
*
* \param[in] chained_mode_switch_list list of controller to switch chained mode.
* \param[in] to_chained_mode flag if controller should be switched *to* or *from* chained mode.
*/
void switch_chained_mode(
const std::vector<std::string> & chained_mode_switch_list, bool to_chained_mode);
/// Activate chosen controllers from real-time controller list.
/**
* Activate controllers with names \p controllers_to_activate from list \p rt_controller_list.
* The controller list will be iterated as many times as there are controller names.
*
* \param[in] rt_controller_list controllers in the real-time list.
* \param[in] controllers_to_activate names of the controller that have to be activated.
*/
void activate_controllers(
const std::vector<ControllerSpec> & rt_controller_list,
const std::vector<std::string> controllers_to_activate);
/// Activate chosen controllers from real-time controller list.
/**
* Activate controllers with names \p controllers_to_activate from list \p rt_controller_list.
* The controller list will be iterated as many times as there are controller names.
*
* *NOTE*: There is currently not difference to `activate_controllers` method.
* Check https://github.com/ros-controls/ros2_control/issues/263 for more information.
*
* \param[in] rt_controller_list controllers in the real-time list.
* \param[in] controllers_to_activate names of the controller that have to be activated.
*/
void activate_controllers_asap(
const std::vector<ControllerSpec> & rt_controller_list,
const std::vector<std::string> controllers_to_activate);
void list_controllers_srv_cb(
const std::shared_ptr<controller_manager_msgs::srv::ListControllers::Request> request,
std::shared_ptr<controller_manager_msgs::srv::ListControllers::Response> response);
void list_hardware_interfaces_srv_cb(
const std::shared_ptr<controller_manager_msgs::srv::ListHardwareInterfaces::Request> request,
std::shared_ptr<controller_manager_msgs::srv::ListHardwareInterfaces::Response> response);
void load_controller_service_cb(
const std::shared_ptr<controller_manager_msgs::srv::LoadController::Request> request,
std::shared_ptr<controller_manager_msgs::srv::LoadController::Response> response);
void configure_controller_service_cb(
const std::shared_ptr<controller_manager_msgs::srv::ConfigureController::Request> request,
std::shared_ptr<controller_manager_msgs::srv::ConfigureController::Response> response);
void reload_controller_libraries_service_cb(
const std::shared_ptr<controller_manager_msgs::srv::ReloadControllerLibraries::Request> request,
std::shared_ptr<controller_manager_msgs::srv::ReloadControllerLibraries::Response> response);
void switch_controller_service_cb(
const std::shared_ptr<controller_manager_msgs::srv::SwitchController::Request> request,
std::shared_ptr<controller_manager_msgs::srv::SwitchController::Response> response);
void unload_controller_service_cb(
const std::shared_ptr<controller_manager_msgs::srv::UnloadController::Request> request,
std::shared_ptr<controller_manager_msgs::srv::UnloadController::Response> response);
void list_controller_types_srv_cb(
const std::shared_ptr<controller_manager_msgs::srv::ListControllerTypes::Request> request,
std::shared_ptr<controller_manager_msgs::srv::ListControllerTypes::Response> response);
void list_hardware_components_srv_cb(
const std::shared_ptr<controller_manager_msgs::srv::ListHardwareComponents::Request> request,
std::shared_ptr<controller_manager_msgs::srv::ListHardwareComponents::Response> response);
void set_hardware_component_state_srv_cb(
const std::shared_ptr<controller_manager_msgs::srv::SetHardwareComponentState::Request> request,
std::shared_ptr<controller_manager_msgs::srv::SetHardwareComponentState::Response> response);
// Per controller update rate support
unsigned int update_loop_counter_ = 0;
unsigned int update_rate_;
std::vector<std::vector<std::string>> chained_controllers_configuration_;
std::unique_ptr<hardware_interface::ResourceManager> resource_manager_;
private:
std::vector<std::string> get_controller_names();
std::pair<std::string, std::string> split_command_interface(
const std::string & command_interface);
void init_controller_manager();
void initialize_parameters();
/**
* Clear request lists used when switching controllers. The lists are shared between "callback"
* and "control loop" threads.
*/
void clear_requests();
/**
* If a controller is deactivated all following controllers (if any exist) should be switched
* 'from' the chained mode.
*
* \param[in] controllers list with controllers.
*/
void propagate_deactivation_of_chained_mode(const std::vector<ControllerSpec> & controllers);
/// Check if all the following controllers will be in active state and in the chained mode
/// after controllers' switch.
/**
* Check recursively that all following controllers of the @controller_it
* - are already active,
* - will not be deactivated,
* - or will be activated.
* The following controllers are added to the request to switch in the chained mode or removed
* from the request to switch from the chained mode.
*
* For each controller the whole chain of following controllers is checked.
*
* NOTE: The automatically adding of following controller into activate list is not implemented
* yet.
*
* \param[in] controllers list with controllers.
* \param[in] strictness if value is equal "MANIPULATE_CONTROLLERS_CHAIN" then all following
* controllers will be automatically added to the activate request list if they are not in the
* deactivate request.
* \param[in] controller_it iterator to the controller for which the following controllers are
* checked.
*
* \returns return_type::OK if all following controllers pass the checks, otherwise
* return_type::ERROR.
*/
controller_interface::return_type check_following_controllers_for_activate(
const std::vector<ControllerSpec> & controllers, int strictness,
const ControllersListIterator controller_it);
/// Check if all the preceding controllers will be in inactive state after controllers' switch.
/**
* Check that all preceding controllers of the @controller_it
* - are inactive,
* - will be deactivated,
* - and will not be activated.
*
* NOTE: The automatically adding of preceding controllers into deactivate list is not implemented
* yet.
*
* \param[in] controllers list with controllers.
* \param[in] strictness if value is equal "MANIPULATE_CONTROLLERS_CHAIN" then all preceding
* controllers will be automatically added to the deactivate request list.
* \param[in] controller_it iterator to the controller for which the preceding controllers are
* checked.
*
* \returns return_type::OK if all preceding controllers pass the checks, otherwise
* return_type::ERROR.
*/
controller_interface::return_type check_preceeding_controllers_for_deactivate(
const std::vector<ControllerSpec> & controllers, int strictness,
const ControllersListIterator controller_it);
/// Checks if the fallback controllers of the given controllers are in the right
/// state, so they can be activated immediately
/**
* \param[in] controllers is a list of controllers to activate.
* \param[in] controller_it is the iterator pointing to the controller to be activated.
* \return return_type::OK if all fallback controllers are in the right state, otherwise
* return_type::ERROR.
*/
controller_interface::return_type check_fallback_controllers_state_pre_activation(
const std::vector<ControllerSpec> & controllers, const ControllersListIterator controller_it);
/**
* @brief Inserts a controller into an ordered list based on dependencies to compute the
* controller chain.
*
* This method computes the controller chain by inserting the provided controller name into an
* ordered list of controllers based on dependencies. It ensures that controllers are inserted in
* the correct order so that dependencies are satisfied.
*
* @param ctrl_name The name of the controller to be inserted into the chain.
* @param controller_iterator An iterator pointing to the position in the ordered list where the
* controller should be inserted.
* @param append_to_controller Flag indicating whether the controller should be appended or
* prepended to the parsed iterator.
* @note The specification of controller dependencies is in the ControllerChainSpec,
* containing information about following and preceding controllers. This struct should include
* the neighboring controllers with their relationships to the provided controller.
* `following_controllers` specify controllers that come after the provided controller.
* `preceding_controllers` specify controllers that come before the provided controller.
*/
void update_list_with_controller_chain(
const std::string & ctrl_name, std::vector<std::string>::iterator controller_iterator,
bool append_to_controller);
void controller_activity_diagnostic_callback(diagnostic_updater::DiagnosticStatusWrapper & stat);
void hardware_components_diagnostic_callback(diagnostic_updater::DiagnosticStatusWrapper & stat);
void controller_manager_diagnostic_callback(diagnostic_updater::DiagnosticStatusWrapper & stat);
/**
* @brief determine_controller_node_options - A method that retrieves the controller defined node
* options and adapts them, based on if there is a params file to be loaded or the use_sim_time
* needs to be set
* @param controller - controller info
* @return The node options that will be set to the controller LifeCycleNode
*/
rclcpp::NodeOptions determine_controller_node_options(const ControllerSpec & controller) const;
std::shared_ptr<controller_manager::ParamListener> cm_param_listener_;
std::shared_ptr<controller_manager::Params> params_;
diagnostic_updater::Updater diagnostics_updater_;
std::shared_ptr<rclcpp::Executor> executor_;
std::shared_ptr<pluginlib::ClassLoader<controller_interface::ControllerInterface>> loader_;
std::shared_ptr<pluginlib::ClassLoader<controller_interface::ChainableControllerInterface>>
chainable_loader_;
/// Best effort (non real-time safe) callback group, e.g., service callbacks.
/**
* Best effort (non real-time safe) callback group for callbacks that can possibly break
* real-time requirements, for example, service callbacks.
*/
rclcpp::CallbackGroup::SharedPtr best_effort_callback_group_;
/**
* The RTControllerListWrapper class wraps a double-buffered list of controllers
* to avoid needing to lock the real-time thread when switching controllers in
* the non-real-time thread.
*
* There's always an "updated" list and an "outdated" one
* There's always an "used by rt" list and an "unused by rt" list
*
* The updated state changes on the switch_updated_list()
* The rt usage state changes on the update_and_get_used_by_rt_list()
*/
class RTControllerListWrapper
{
// *INDENT-OFF*
public:
// *INDENT-ON*
/// update_and_get_used_by_rt_list Makes the "updated" list the "used by rt" list
/**
* \warning Should only be called by the RT thread, no one should modify the
* updated list while it's being used
* \return reference to the updated list
*/
std::vector<ControllerSpec> & update_and_get_used_by_rt_list();
/**
* get_unused_list Waits until the "outdated" and "unused by rt"
* lists match and returns a reference to it
* This referenced list can be modified safely until switch_updated_controller_list()
* is called, at this point the RT thread may start using it at any time
* \param[in] guard Guard needed to make sure the caller is the only one accessing the unused by
* rt list
*/
std::vector<ControllerSpec> & get_unused_list(
const std::lock_guard<std::recursive_mutex> & guard);
/// get_updated_list Returns a const reference to the most updated list.
/**
* \warning May or may not being used by the realtime thread, read-only reference for safety
* \param[in] guard Guard needed to make sure the caller is the only one accessing the unused by
* rt list
*/
const std::vector<ControllerSpec> & get_updated_list(
const std::lock_guard<std::recursive_mutex> & guard) const;
/**
* switch_updated_list Switches the "updated" and "outdated" lists, and waits
* until the RT thread is using the new "updated" list.
* \param[in] guard Guard needed to make sure the caller is the only one accessing the unused by
* rt list
*/
void switch_updated_list(const std::lock_guard<std::recursive_mutex> & guard);
// Mutex protecting the controllers list
// must be acquired before using any list other than the "used by rt"
mutable std::recursive_mutex controllers_lock_;
// *INDENT-OFF*
private:
// *INDENT-ON*
/// get_other_list get the list not pointed by index
/**
* \param[in] index int
*/
int get_other_list(int index) const;
void wait_until_rt_not_using(
int index, std::chrono::microseconds sleep_delay = std::chrono::microseconds(200)) const;
std::vector<ControllerSpec> controllers_lists_[2];
/// The index of the controller list with the most updated information
int updated_controllers_index_ = 0;
/// The index of the controllers list being used in the real-time thread.
int used_by_realtime_controllers_index_ = -1;
};
RTControllerListWrapper rt_controllers_wrapper_;
std::unordered_map<std::string, ControllerChainSpec> controller_chain_spec_;
std::vector<std::string> ordered_controllers_names_;
/// mutex copied from ROS1 Control, protects service callbacks
/// not needed if we're guaranteed that the callbacks don't come from multiple threads
std::mutex services_lock_;
rclcpp::Service<controller_manager_msgs::srv::ListControllers>::SharedPtr
list_controllers_service_;
rclcpp::Service<controller_manager_msgs::srv::ListControllerTypes>::SharedPtr
list_controller_types_service_;
rclcpp::Service<controller_manager_msgs::srv::LoadController>::SharedPtr load_controller_service_;
rclcpp::Service<controller_manager_msgs::srv::ConfigureController>::SharedPtr
configure_controller_service_;
rclcpp::Service<controller_manager_msgs::srv::ReloadControllerLibraries>::SharedPtr
reload_controller_libraries_service_;
rclcpp::Service<controller_manager_msgs::srv::SwitchController>::SharedPtr
switch_controller_service_;
rclcpp::Service<controller_manager_msgs::srv::UnloadController>::SharedPtr
unload_controller_service_;
rclcpp::Service<controller_manager_msgs::srv::ListHardwareComponents>::SharedPtr
list_hardware_components_service_;
rclcpp::Service<controller_manager_msgs::srv::ListHardwareInterfaces>::SharedPtr
list_hardware_interfaces_service_;
rclcpp::Service<controller_manager_msgs::srv::SetHardwareComponentState>::SharedPtr
set_hardware_component_state_service_;
std::vector<std::string> activate_request_, deactivate_request_;
std::vector<std::string> to_chained_mode_request_, from_chained_mode_request_;
std::vector<std::string> activate_command_interface_request_,
deactivate_command_interface_request_;
std::map<std::string, std::vector<std::string>> controller_chained_reference_interfaces_cache_;
std::map<std::string, std::vector<std::string>> controller_chained_state_interfaces_cache_;
rclcpp::NodeOptions cm_node_options_;
std::string robot_description_;
rclcpp::Subscription<std_msgs::msg::String>::SharedPtr robot_description_subscription_;
rclcpp::TimerBase::SharedPtr robot_description_notification_timer_;
controller_manager::MovingAverageStatistics periodicity_stats_;
struct SwitchParams
{
void reset()
{
do_switch = false;
started = false;
strictness = 0;
activate_asap = false;
}
bool do_switch;
bool started;
// Switch options
int strictness;
bool activate_asap;
std::chrono::nanoseconds timeout;
// conditional variable and mutex to wait for the switch to complete
std::condition_variable cv;
std::mutex mutex;
};
SwitchParams switch_params_;
};
} // namespace controller_manager
#endif // CONTROLLER_MANAGER__CONTROLLER_MANAGER_HPP_