Skip to content

Commit eb1e51c

Browse files
committed
make possible to create only on node for pub/sub in distributed cm
1 parent 3e89b21 commit eb1e51c

File tree

9 files changed

+194
-81
lines changed

9 files changed

+194
-81
lines changed

controller_manager/include/controller_manager/controller_manager.hpp

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ rclcpp::NodeOptions get_cm_node_options();
6262

6363
class ControllerManager : public rclcpp::Node
6464
{
65+
enum class controller_manager_type : std::uint8_t;
66+
6567
public:
6668
static constexpr bool kWaitForAllResources = false;
6769
static constexpr auto kInfiniteTimeout = 0;
@@ -198,6 +200,10 @@ class ControllerManager : public rclcpp::Node
198200
CONTROLLER_MANAGER_PUBLIC
199201
unsigned int get_update_rate() const;
200202

203+
// Per controller update rate support
204+
CONTROLLER_MANAGER_PUBLIC
205+
bool use_multiple_nodes() const;
206+
201207
// Per controller update rate support
202208
CONTROLLER_MANAGER_PUBLIC
203209
std::chrono::milliseconds distributed_interfaces_publish_period() const;
@@ -207,13 +213,21 @@ class ControllerManager : public rclcpp::Node
207213
void init_services();
208214

209215
CONTROLLER_MANAGER_PUBLIC
210-
void configure_controller_manager();
216+
void get_and_initialize_distributed_parameters();
217+
218+
CONTROLLER_MANAGER_PUBLIC
219+
controller_manager_type determine_controller_manager_type();
220+
221+
CONTROLLER_MANAGER_PUBLIC
222+
void configure_controller_manager(const controller_manager_type & cm_type);
211223

212224
CONTROLLER_MANAGER_PUBLIC
213225
void init_distributed_sub_controller_manager();
214226

215227
CONTROLLER_MANAGER_PUBLIC
216-
void init_distributed_main_controller_services();
228+
void init_distributed_central_controller_manager();
229+
230+
CONTROLLER_MANAGER_PUBLIC void init_distributed_central_controller_manager_services();
217231

218232
CONTROLLER_MANAGER_PUBLIC
219233
void register_sub_controller_manager_srv_cb(
@@ -435,8 +449,18 @@ class ControllerManager : public rclcpp::Node
435449
*/
436450
rclcpp::CallbackGroup::SharedPtr best_effort_callback_group_;
437451

452+
enum class controller_manager_type : std::uint8_t
453+
{
454+
standard_controller_manager,
455+
distributed_central_controller_manager,
456+
distributed_sub_controller_manager,
457+
unkown_type // indicating something went wrong and type could not be determined
458+
};
459+
438460
bool distributed_ = false;
439461
bool sub_controller_manager_ = false;
462+
bool use_multiple_nodes_ = false;
463+
std::shared_ptr<rclcpp_lifecycle::LifecycleNode> distributed_pub_sub_node_ = nullptr;
440464
std::chrono::milliseconds distributed_interfaces_publish_period_ = std::chrono::milliseconds(12);
441465

442466
rclcpp::CallbackGroup::SharedPtr distributed_system_srv_callback_group_;

controller_manager/src/controller_manager.cpp

Lines changed: 87 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,9 @@ ControllerManager::ControllerManager(
181181
diagnostics_updater_.add(
182182
"Controllers Activity", this, &ControllerManager::controller_activity_diagnostic_callback);
183183
init_services();
184-
configure_controller_manager();
184+
get_and_initialize_distributed_parameters();
185+
auto cm_type = determine_controller_manager_type();
186+
configure_controller_manager(cm_type);
185187
}
186188

187189
ControllerManager::ControllerManager(
@@ -209,7 +211,9 @@ ControllerManager::ControllerManager(
209211
diagnostics_updater_.add(
210212
"Controllers Activity", this, &ControllerManager::controller_activity_diagnostic_callback);
211213
init_services();
212-
configure_controller_manager();
214+
get_and_initialize_distributed_parameters();
215+
auto cm_type = determine_controller_manager_type();
216+
configure_controller_manager(cm_type);
213217
}
214218

215219
void ControllerManager::subscribe_to_robot_description_topic()
@@ -354,11 +358,7 @@ void ControllerManager::init_services()
354358
qos_services, best_effort_callback_group_);
355359
}
356360

357-
// TODO(Manuel) don't like this, this is for fast poc
358-
// probably better to create factory and handle creation of correct controller manager type
359-
// there. Since asynchronous control should be supported im the future as well and we don't
360-
// want dozen of ifs.
361-
void ControllerManager::configure_controller_manager()
361+
void ControllerManager::get_and_initialize_distributed_parameters()
362362
{
363363
if (!get_parameter("distributed", distributed_))
364364
{
@@ -374,50 +374,102 @@ void ControllerManager::configure_controller_manager()
374374
sub_controller_manager_ ? "true" : "false");
375375
}
376376

377+
int64_t distributed_interfaces_publish_period;
378+
if (get_parameter("distributed_interfaces_publish_period", distributed_interfaces_publish_period))
379+
{
380+
distributed_interfaces_publish_period_ =
381+
std::chrono::milliseconds(distributed_interfaces_publish_period);
382+
}
383+
384+
else
385+
{
386+
RCLCPP_WARN(
387+
get_logger(),
388+
"'distributed_interfaces_publish_period' parameter not set, using default value.");
389+
}
390+
391+
if (!get_parameter("use_multiple_nodes", use_multiple_nodes_))
392+
{
393+
RCLCPP_WARN(
394+
get_logger(), "'use_multiple_nodes' parameter not set, using default value:%s",
395+
use_multiple_nodes_ ? "true" : "false");
396+
}
397+
}
398+
399+
void ControllerManager::configure_controller_manager(const controller_manager_type & cm_type)
400+
{
401+
switch (cm_type)
402+
{
403+
case controller_manager_type::distributed_central_controller_manager:
404+
init_distributed_central_controller_manager();
405+
break;
406+
407+
case controller_manager_type::distributed_sub_controller_manager:
408+
init_distributed_sub_controller_manager();
409+
break;
410+
case controller_manager_type::standard_controller_manager:
411+
//nothing special to configure
412+
break;
413+
default:
414+
throw std::logic_error(
415+
"Controller manager configuration not possible. Not a known controller manager type."
416+
"Did you maybe set `distributed:false` and `sub_controller_manager:true`?"
417+
"Note:Only distributed controller manager can be a sub controller manager.");
418+
break;
419+
}
420+
}
421+
422+
// TODO(Manuel) don't like this, this is for fast poc
423+
// probably better to create factory and handle creation of correct controller manager type
424+
// there. Since asynchronous control should be supported im the future as well and we don't
425+
// want dozen of ifs.
426+
ControllerManager::controller_manager_type ControllerManager::determine_controller_manager_type()
427+
{
377428
bool std_controller_manager = !distributed_ && !sub_controller_manager_;
378429
bool distributed_sub_controller_manager = distributed_ && sub_controller_manager_;
379430
bool central_controller_manager = distributed_ && !sub_controller_manager_;
380431
if (distributed_sub_controller_manager)
381432
{
382-
init_distributed_sub_controller_manager();
433+
return controller_manager_type::distributed_sub_controller_manager;
383434
}
384435
// This means we are the central controller manager
385436
else if (central_controller_manager)
386437
{
387-
init_distributed_main_controller_services();
438+
return controller_manager_type::distributed_central_controller_manager;
388439
}
389440
// std controller manager or error. std controller manager needs no special setup.
390-
else
441+
else if (std_controller_manager)
391442
{
392-
if (!std_controller_manager)
393-
{
394-
throw std::logic_error(
395-
"Controller manager configured with: distributed:false and sub_controller_manager:true. "
396-
"Only distributed controller manager can be a sub controller manager.");
397-
}
443+
return controller_manager_type::standard_controller_manager;
398444
}
445+
return controller_manager_type::unkown_type;
399446
}
400447

401448
void ControllerManager::init_distributed_sub_controller_manager()
402449
{
403-
int64_t distributed_interfaces_publish_period;
404-
if (get_parameter("distributed_interfaces_publish_period", distributed_interfaces_publish_period))
405-
{
406-
distributed_interfaces_publish_period_ =
407-
std::chrono::milliseconds(distributed_interfaces_publish_period);
408-
}
409-
else
450+
if (!use_multiple_nodes())
410451
{
411-
RCLCPP_WARN(
412-
get_logger(),
413-
"'distributed_interfaces_publish_period' parameter not set, using default value.");
452+
rclcpp::NodeOptions node_options;
453+
distributed_pub_sub_node_ = std::make_shared<rclcpp_lifecycle::LifecycleNode>(
454+
std::string(get_name()) + "_pub_sub_node", get_namespace(), node_options, false);
414455
}
415456
add_hardware_state_publishers();
416457
add_hardware_command_forwarders();
417458
register_sub_controller_manager();
418459
}
419460

420-
void ControllerManager::init_distributed_main_controller_services()
461+
void ControllerManager::init_distributed_central_controller_manager()
462+
{
463+
if (!use_multiple_nodes())
464+
{
465+
rclcpp::NodeOptions node_options;
466+
distributed_pub_sub_node_ = std::make_shared<rclcpp_lifecycle::LifecycleNode>(
467+
std::string(get_name()) + "_pub_sub_node", get_namespace(), node_options, false);
468+
}
469+
init_distributed_central_controller_manager_services();
470+
}
471+
472+
void ControllerManager::init_distributed_central_controller_manager_services()
421473
{
422474
distributed_system_srv_callback_group_ =
423475
create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
@@ -448,7 +500,8 @@ void ControllerManager::register_sub_controller_manager_srv_cb(
448500
distributed_state_interfaces;
449501
distributed_state_interfaces.reserve(sub_ctrl_mng_wrapper->get_state_publisher_count());
450502
distributed_state_interfaces =
451-
resource_manager_->import_state_interfaces_of_sub_controller_manager(sub_ctrl_mng_wrapper);
503+
resource_manager_->import_state_interfaces_of_sub_controller_manager(
504+
sub_ctrl_mng_wrapper, get_namespace(), distributed_pub_sub_node_);
452505

453506
for (const auto & state_interface : distributed_state_interfaces)
454507
{
@@ -471,7 +524,8 @@ void ControllerManager::register_sub_controller_manager_srv_cb(
471524
distributed_command_interfaces;
472525
distributed_command_interfaces.reserve(sub_ctrl_mng_wrapper->get_command_forwarder_count());
473526
distributed_command_interfaces =
474-
resource_manager_->import_command_interfaces_of_sub_controller_manager(sub_ctrl_mng_wrapper);
527+
resource_manager_->import_command_interfaces_of_sub_controller_manager(
528+
sub_ctrl_mng_wrapper, get_namespace(), distributed_pub_sub_node_);
475529

476530
for (const auto & command_interface : distributed_command_interfaces)
477531
{
@@ -508,7 +562,7 @@ void ControllerManager::add_hardware_state_publishers()
508562
std::vector<std::shared_ptr<distributed_control::StatePublisher>> state_publishers_vec;
509563
state_publishers_vec.reserve(resource_manager_->available_state_interfaces().size());
510564
state_publishers_vec = resource_manager_->create_hardware_state_publishers(
511-
get_namespace(), distributed_interfaces_publish_period());
565+
get_namespace(), distributed_interfaces_publish_period(), distributed_pub_sub_node_);
512566

513567
for (auto const & state_publisher : state_publishers_vec)
514568
{
@@ -530,7 +584,7 @@ void ControllerManager::add_hardware_command_forwarders()
530584
std::vector<std::shared_ptr<distributed_control::CommandForwarder>> command_forwarder_vec;
531585
command_forwarder_vec.reserve(resource_manager_->available_command_interfaces().size());
532586
command_forwarder_vec = resource_manager_->create_hardware_command_forwarders(
533-
get_namespace(), distributed_interfaces_publish_period());
587+
get_namespace(), distributed_interfaces_publish_period(), distributed_pub_sub_node_);
534588

535589
for (auto const & command_forwarder : command_forwarder_vec)
536590
{
@@ -2254,6 +2308,8 @@ std::pair<std::string, std::string> ControllerManager::split_command_interface(
22542308

22552309
unsigned int ControllerManager::get_update_rate() const { return update_rate_; }
22562310

2311+
bool ControllerManager::use_multiple_nodes() const { return use_multiple_nodes_; }
2312+
22572313
std::chrono::milliseconds ControllerManager::distributed_interfaces_publish_period() const
22582314
{
22592315
return distributed_interfaces_publish_period_;

hardware_interface/include/hardware_interface/distributed_control_interface/command_forwarder.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ class CommandForwarder final
2424
public:
2525
explicit CommandForwarder(
2626
std::unique_ptr<hardware_interface::LoanedCommandInterface> loaned_command_interface_ptr,
27-
const std::string & ns, std::chrono::milliseconds period_in_ms);
27+
const std::string & ns, std::chrono::milliseconds period_in_ms,
28+
std::shared_ptr<rclcpp_lifecycle::LifecycleNode> node);
2829

2930
CommandForwarder() = delete;
3031

hardware_interface/include/hardware_interface/distributed_control_interface/state_publisher.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ class StatePublisher final
2222
public:
2323
explicit StatePublisher(
2424
std::unique_ptr<hardware_interface::LoanedStateInterface> loaned_state_interface_ptr,
25-
const std::string & ns, std::chrono::milliseconds period_in_ms);
26-
25+
const std::string & ns, std::chrono::milliseconds period_in_ms,
26+
std::shared_ptr<rclcpp_lifecycle::LifecycleNode> node);
2727
StatePublisher() = delete;
2828

2929
~StatePublisher() {}

hardware_interface/include/hardware_interface/handle.hpp

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,8 @@ class ReadOnlyHandle : public HandleInterface, public ReadHandleInterface
148148
public:
149149
ReadOnlyHandle(
150150
const std::string & prefix_name, const std::string & interface_name,
151-
double * value_ptr = nullptr)
152-
: HandleInterface(prefix_name, interface_name, value_ptr)
151+
double * value_ptr = nullptr, std::shared_ptr<rclcpp_lifecycle::LifecycleNode> node = nullptr)
152+
: HandleInterface(prefix_name, interface_name, value_ptr, node)
153153
{
154154
}
155155

@@ -190,18 +190,22 @@ class DistributedReadOnlyHandle : public ReadOnlyHandle
190190
// TODO(Manuel): We should pass the initial value via service call, so that the value_ of ReadOnlyHandle
191191
// is initialized with a feasible value.
192192
DistributedReadOnlyHandle(
193-
const distributed_control::PublisherDescription & description, const std::string & ns = "/")
194-
: ReadOnlyHandle(description.prefix_name(), description.interface_name(), &value_),
193+
const distributed_control::PublisherDescription & description, const std::string & ns,
194+
std::shared_ptr<rclcpp_lifecycle::LifecycleNode> node)
195+
: ReadOnlyHandle(description.prefix_name(), description.interface_name(), &value_, node),
195196
get_value_topic_name_(description.topic_name()),
196197
namespace_(ns),
197198
interface_namespace_(description.get_namespace())
198199
{
199-
rclcpp::NodeOptions node_options;
200+
// if no node has been passed
200201
// create node for subscribing to StatePublisher described in StatePublisherDescription
201-
node_ = std::make_shared<rclcpp_lifecycle::LifecycleNode>(
202-
get_underscore_separated_name() + "_state_interface_subscriber", namespace_, node_options,
203-
false);
204-
202+
if (!node_.get())
203+
{
204+
rclcpp::NodeOptions node_options;
205+
node_ = std::make_shared<rclcpp_lifecycle::LifecycleNode>(
206+
get_underscore_separated_name() + "_state_interface_subscriber", namespace_, node_options,
207+
false);
208+
}
205209
// subscribe to topic provided by StatePublisher
206210
state_value_sub_ = node_->create_subscription<std_msgs::msg::Float64>(
207211
get_value_topic_name_, 10,
@@ -280,8 +284,8 @@ class ReadWriteHandle : public HandleInterface,
280284
public:
281285
ReadWriteHandle(
282286
const std::string & prefix_name, const std::string & interface_name,
283-
double * value_ptr = nullptr)
284-
: HandleInterface(prefix_name, interface_name, value_ptr)
287+
double * value_ptr = nullptr, std::shared_ptr<rclcpp_lifecycle::LifecycleNode> node = nullptr)
288+
: HandleInterface(prefix_name, interface_name, value_ptr, node)
285289
{
286290
}
287291

@@ -332,20 +336,25 @@ class DistributedReadWriteHandle : public ReadWriteHandle
332336
{
333337
public:
334338
DistributedReadWriteHandle(
335-
const distributed_control::PublisherDescription & description, const std::string & ns = "/")
336-
: ReadWriteHandle(description.prefix_name(), description.interface_name(), &value_),
339+
const distributed_control::PublisherDescription & description, const std::string & ns,
340+
std::shared_ptr<rclcpp_lifecycle::LifecycleNode> node)
341+
: ReadWriteHandle(description.prefix_name(), description.interface_name(), &value_, node),
337342
get_value_topic_name_(description.topic_name()),
338343
namespace_(ns),
339344
interface_namespace_(description.get_namespace()),
340345
forward_command_topic_name_(get_underscore_separated_name() + "_command_forwarding")
341346
{
342-
// create node for subscribing to StatePublisher described in StatePublisherDescription
343-
rclcpp::NodeOptions node_options;
344-
node_ = std::make_shared<rclcpp_lifecycle::LifecycleNode>(
345-
get_underscore_separated_name() + "_distributed_command_interface", namespace_, node_options,
346-
false);
347+
// if no node has been passed
348+
// create node for subscribing to CommandForwarder described in CommandForwarderDescription
349+
if (!node_.get())
350+
{
351+
rclcpp::NodeOptions node_options;
352+
node_ = std::make_shared<rclcpp_lifecycle::LifecycleNode>(
353+
get_underscore_separated_name() + "_distributed_command_interface", namespace_,
354+
node_options, false);
355+
}
347356

348-
// subscribe to topic provided by StatePublisher
357+
// subscribe to topic provided by CommandForwarder
349358
command_value_sub_ = node_->create_subscription<std_msgs::msg::Float64>(
350359
get_value_topic_name_, 10,
351360
std::bind(&DistributedReadWriteHandle::get_value_cb, this, std::placeholders::_1));

0 commit comments

Comments
 (0)