Skip to content

Commit e797046

Browse files
committed
make possible to create only on node for pub/sub in distributed cm
1 parent 8c7a3f1 commit e797046

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
@@ -60,6 +60,8 @@ rclcpp::NodeOptions get_cm_node_options();
6060

6161
class ControllerManager : public rclcpp::Node
6262
{
63+
enum class controller_manager_type : std::uint8_t;
64+
6365
public:
6466
static constexpr bool kWaitForAllResources = false;
6567
static constexpr auto kInfiniteTimeout = 0;
@@ -190,6 +192,10 @@ class ControllerManager : public rclcpp::Node
190192
CONTROLLER_MANAGER_PUBLIC
191193
unsigned int get_update_rate() const;
192194

195+
// Per controller update rate support
196+
CONTROLLER_MANAGER_PUBLIC
197+
bool use_multiple_nodes() const;
198+
193199
// Per controller update rate support
194200
CONTROLLER_MANAGER_PUBLIC
195201
std::chrono::milliseconds distributed_interfaces_publish_period() const;
@@ -199,13 +205,21 @@ class ControllerManager : public rclcpp::Node
199205
void init_services();
200206

201207
CONTROLLER_MANAGER_PUBLIC
202-
void configure_controller_manager();
208+
void get_and_initialize_distributed_parameters();
209+
210+
CONTROLLER_MANAGER_PUBLIC
211+
controller_manager_type determine_controller_manager_type();
212+
213+
CONTROLLER_MANAGER_PUBLIC
214+
void configure_controller_manager(const controller_manager_type & cm_type);
203215

204216
CONTROLLER_MANAGER_PUBLIC
205217
void init_distributed_sub_controller_manager();
206218

207219
CONTROLLER_MANAGER_PUBLIC
208-
void init_distributed_main_controller_services();
220+
void init_distributed_central_controller_manager();
221+
222+
CONTROLLER_MANAGER_PUBLIC void init_distributed_central_controller_manager_services();
209223

210224
CONTROLLER_MANAGER_PUBLIC
211225
void register_sub_controller_manager_srv_cb(
@@ -427,8 +441,18 @@ class ControllerManager : public rclcpp::Node
427441
*/
428442
rclcpp::CallbackGroup::SharedPtr best_effort_callback_group_;
429443

444+
enum class controller_manager_type : std::uint8_t
445+
{
446+
standard_controller_manager,
447+
distributed_central_controller_manager,
448+
distributed_sub_controller_manager,
449+
unkown_type // indicating something went wrong and type could not be determined
450+
};
451+
430452
bool distributed_ = false;
431453
bool sub_controller_manager_ = false;
454+
bool use_multiple_nodes_ = false;
455+
std::shared_ptr<rclcpp_lifecycle::LifecycleNode> distributed_pub_sub_node_ = nullptr;
432456
std::chrono::milliseconds distributed_interfaces_publish_period_ = std::chrono::milliseconds(12);
433457

434458
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
@@ -174,7 +174,9 @@ ControllerManager::ControllerManager(
174174
diagnostics_updater_.add(
175175
"Controllers Activity", this, &ControllerManager::controller_activity_diagnostic_callback);
176176
init_services();
177-
configure_controller_manager();
177+
get_and_initialize_distributed_parameters();
178+
auto cm_type = determine_controller_manager_type();
179+
configure_controller_manager(cm_type);
178180
}
179181

180182
ControllerManager::ControllerManager(
@@ -199,7 +201,9 @@ ControllerManager::ControllerManager(
199201
diagnostics_updater_.add(
200202
"Controllers Activity", this, &ControllerManager::controller_activity_diagnostic_callback);
201203
init_services();
202-
configure_controller_manager();
204+
get_and_initialize_distributed_parameters();
205+
auto cm_type = determine_controller_manager_type();
206+
configure_controller_manager(cm_type);
203207
}
204208

205209
void ControllerManager::init_resource_manager(const std::string & robot_description)
@@ -304,11 +308,7 @@ void ControllerManager::init_services()
304308
qos_services, best_effort_callback_group_);
305309
}
306310

307-
// TODO(Manuel) don't like this, this is for fast poc
308-
// probably better to create factory and handle creation of correct controller manager type
309-
// there. Since asynchronous control should be supported im the future as well and we don't
310-
// want dozen of ifs.
311-
void ControllerManager::configure_controller_manager()
311+
void ControllerManager::get_and_initialize_distributed_parameters()
312312
{
313313
if (!get_parameter("distributed", distributed_))
314314
{
@@ -324,50 +324,102 @@ void ControllerManager::configure_controller_manager()
324324
sub_controller_manager_ ? "true" : "false");
325325
}
326326

327+
int64_t distributed_interfaces_publish_period;
328+
if (get_parameter("distributed_interfaces_publish_period", distributed_interfaces_publish_period))
329+
{
330+
distributed_interfaces_publish_period_ =
331+
std::chrono::milliseconds(distributed_interfaces_publish_period);
332+
}
333+
334+
else
335+
{
336+
RCLCPP_WARN(
337+
get_logger(),
338+
"'distributed_interfaces_publish_period' parameter not set, using default value.");
339+
}
340+
341+
if (!get_parameter("use_multiple_nodes", use_multiple_nodes_))
342+
{
343+
RCLCPP_WARN(
344+
get_logger(), "'use_multiple_nodes' parameter not set, using default value:%s",
345+
use_multiple_nodes_ ? "true" : "false");
346+
}
347+
}
348+
349+
void ControllerManager::configure_controller_manager(const controller_manager_type & cm_type)
350+
{
351+
switch (cm_type)
352+
{
353+
case controller_manager_type::distributed_central_controller_manager:
354+
init_distributed_central_controller_manager();
355+
break;
356+
357+
case controller_manager_type::distributed_sub_controller_manager:
358+
init_distributed_sub_controller_manager();
359+
break;
360+
case controller_manager_type::standard_controller_manager:
361+
//nothing special to configure
362+
break;
363+
default:
364+
throw std::logic_error(
365+
"Controller manager configuration not possible. Not a known controller manager type."
366+
"Did you maybe set `distributed:false` and `sub_controller_manager:true`?"
367+
"Note:Only distributed controller manager can be a sub controller manager.");
368+
break;
369+
}
370+
}
371+
372+
// TODO(Manuel) don't like this, this is for fast poc
373+
// probably better to create factory and handle creation of correct controller manager type
374+
// there. Since asynchronous control should be supported im the future as well and we don't
375+
// want dozen of ifs.
376+
ControllerManager::controller_manager_type ControllerManager::determine_controller_manager_type()
377+
{
327378
bool std_controller_manager = !distributed_ && !sub_controller_manager_;
328379
bool distributed_sub_controller_manager = distributed_ && sub_controller_manager_;
329380
bool central_controller_manager = distributed_ && !sub_controller_manager_;
330381
if (distributed_sub_controller_manager)
331382
{
332-
init_distributed_sub_controller_manager();
383+
return controller_manager_type::distributed_sub_controller_manager;
333384
}
334385
// This means we are the central controller manager
335386
else if (central_controller_manager)
336387
{
337-
init_distributed_main_controller_services();
388+
return controller_manager_type::distributed_central_controller_manager;
338389
}
339390
// std controller manager or error. std controller manager needs no special setup.
340-
else
391+
else if (std_controller_manager)
341392
{
342-
if (!std_controller_manager)
343-
{
344-
throw std::logic_error(
345-
"Controller manager configured with: distributed:false and sub_controller_manager:true. "
346-
"Only distributed controller manager can be a sub controller manager.");
347-
}
393+
return controller_manager_type::standard_controller_manager;
348394
}
395+
return controller_manager_type::unkown_type;
349396
}
350397

351398
void ControllerManager::init_distributed_sub_controller_manager()
352399
{
353-
int64_t distributed_interfaces_publish_period;
354-
if (get_parameter("distributed_interfaces_publish_period", distributed_interfaces_publish_period))
355-
{
356-
distributed_interfaces_publish_period_ =
357-
std::chrono::milliseconds(distributed_interfaces_publish_period);
358-
}
359-
else
400+
if (!use_multiple_nodes())
360401
{
361-
RCLCPP_WARN(
362-
get_logger(),
363-
"'distributed_interfaces_publish_period' parameter not set, using default value.");
402+
rclcpp::NodeOptions node_options;
403+
distributed_pub_sub_node_ = std::make_shared<rclcpp_lifecycle::LifecycleNode>(
404+
std::string(get_name()) + "_pub_sub_node", get_namespace(), node_options, false);
364405
}
365406
add_hardware_state_publishers();
366407
add_hardware_command_forwarders();
367408
register_sub_controller_manager();
368409
}
369410

370-
void ControllerManager::init_distributed_main_controller_services()
411+
void ControllerManager::init_distributed_central_controller_manager()
412+
{
413+
if (!use_multiple_nodes())
414+
{
415+
rclcpp::NodeOptions node_options;
416+
distributed_pub_sub_node_ = std::make_shared<rclcpp_lifecycle::LifecycleNode>(
417+
std::string(get_name()) + "_pub_sub_node", get_namespace(), node_options, false);
418+
}
419+
init_distributed_central_controller_manager_services();
420+
}
421+
422+
void ControllerManager::init_distributed_central_controller_manager_services()
371423
{
372424
distributed_system_srv_callback_group_ =
373425
create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
@@ -398,7 +450,8 @@ void ControllerManager::register_sub_controller_manager_srv_cb(
398450
distributed_state_interfaces;
399451
distributed_state_interfaces.reserve(sub_ctrl_mng_wrapper->get_state_publisher_count());
400452
distributed_state_interfaces =
401-
resource_manager_->import_state_interfaces_of_sub_controller_manager(sub_ctrl_mng_wrapper);
453+
resource_manager_->import_state_interfaces_of_sub_controller_manager(
454+
sub_ctrl_mng_wrapper, get_namespace(), distributed_pub_sub_node_);
402455

403456
for (const auto & state_interface : distributed_state_interfaces)
404457
{
@@ -421,7 +474,8 @@ void ControllerManager::register_sub_controller_manager_srv_cb(
421474
distributed_command_interfaces;
422475
distributed_command_interfaces.reserve(sub_ctrl_mng_wrapper->get_command_forwarder_count());
423476
distributed_command_interfaces =
424-
resource_manager_->import_command_interfaces_of_sub_controller_manager(sub_ctrl_mng_wrapper);
477+
resource_manager_->import_command_interfaces_of_sub_controller_manager(
478+
sub_ctrl_mng_wrapper, get_namespace(), distributed_pub_sub_node_);
425479

426480
for (const auto & command_interface : distributed_command_interfaces)
427481
{
@@ -458,7 +512,7 @@ void ControllerManager::add_hardware_state_publishers()
458512
std::vector<std::shared_ptr<distributed_control::StatePublisher>> state_publishers_vec;
459513
state_publishers_vec.reserve(resource_manager_->available_state_interfaces().size());
460514
state_publishers_vec = resource_manager_->create_hardware_state_publishers(
461-
get_namespace(), distributed_interfaces_publish_period());
515+
get_namespace(), distributed_interfaces_publish_period(), distributed_pub_sub_node_);
462516

463517
for (auto const & state_publisher : state_publishers_vec)
464518
{
@@ -480,7 +534,7 @@ void ControllerManager::add_hardware_command_forwarders()
480534
std::vector<std::shared_ptr<distributed_control::CommandForwarder>> command_forwarder_vec;
481535
command_forwarder_vec.reserve(resource_manager_->available_command_interfaces().size());
482536
command_forwarder_vec = resource_manager_->create_hardware_command_forwarders(
483-
get_namespace(), distributed_interfaces_publish_period());
537+
get_namespace(), distributed_interfaces_publish_period(), distributed_pub_sub_node_);
484538

485539
for (auto const & command_forwarder : command_forwarder_vec)
486540
{
@@ -2204,6 +2258,8 @@ std::pair<std::string, std::string> ControllerManager::split_command_interface(
22042258

22052259
unsigned int ControllerManager::get_update_rate() const { return update_rate_; }
22062260

2261+
bool ControllerManager::use_multiple_nodes() const { return use_multiple_nodes_; }
2262+
22072263
std::chrono::milliseconds ControllerManager::distributed_interfaces_publish_period() const
22082264
{
22092265
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)