Skip to content

Commit 8b4b553

Browse files
committed
make possible to export only subset of command/state interfaces, fix
adding node multiple times to executor
1 parent 9764f8f commit 8b4b553

File tree

2 files changed

+136
-54
lines changed

2 files changed

+136
-54
lines changed

controller_manager/include/controller_manager/controller_manager.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,10 @@ class ControllerManager : public rclcpp::Node
460460
bool distributed_ = false;
461461
bool sub_controller_manager_ = false;
462462
bool use_multiple_nodes_ = false;
463+
// TODO(Manuel): weak_ptr would probably be a better choice. This way has to be checked
464+
// if pointer points to an object. Don't like the nullptr thing and implicit checks
465+
// associated with it ... (create on distributed Handles and StatePublisher/CommandForwarder)
466+
// needs to be checked if is nullptr before usage
463467
std::shared_ptr<rclcpp_lifecycle::LifecycleNode> distributed_pub_sub_node_ = nullptr;
464468
std::chrono::milliseconds distributed_interfaces_publish_period_ = std::chrono::milliseconds(12);
465469

controller_manager/src/controller_manager.cpp

Lines changed: 132 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,6 @@ void ControllerManager::configure_controller_manager(const controller_manager_ty
403403
case controller_manager_type::distributed_central_controller_manager:
404404
init_distributed_central_controller_manager();
405405
break;
406-
407406
case controller_manager_type::distributed_sub_controller_manager:
408407
init_distributed_sub_controller_manager();
409408
break;
@@ -419,7 +418,7 @@ void ControllerManager::configure_controller_manager(const controller_manager_ty
419418
}
420419
}
421420

422-
// TODO(Manuel) don't like this, this is for fast poc
421+
// TODO(Manuel): don't like this, this is for fast poc
423422
// probably better to create factory and handle creation of correct controller manager type
424423
// there. Since asynchronous control should be supported im the future as well and we don't
425424
// want dozen of ifs.
@@ -447,12 +446,27 @@ ControllerManager::controller_manager_type ControllerManager::determine_controll
447446

448447
void ControllerManager::init_distributed_sub_controller_manager()
449448
{
449+
// if only one node per sub controller manager is used
450450
if (!use_multiple_nodes())
451451
{
452+
// create node for publishing/subscribing
452453
rclcpp::NodeOptions node_options;
453454
distributed_pub_sub_node_ = std::make_shared<rclcpp_lifecycle::LifecycleNode>(
454455
std::string(get_name()) + "_pub_sub_node", get_namespace(), node_options, false);
456+
//try to add to executor
457+
try
458+
{
459+
executor_->add_node(distributed_pub_sub_node_->get_node_base_interface());
460+
}
461+
catch (const std::runtime_error & e)
462+
{
463+
RCLCPP_WARN_STREAM(
464+
get_logger(),
465+
"ControllerManager: can not add node for distributed publishing/subscribing to executor:"
466+
<< e.what());
467+
}
455468
}
469+
456470
create_hardware_state_publishers();
457471
create_hardware_command_forwarders();
458472
register_sub_controller_manager();
@@ -465,6 +479,18 @@ void ControllerManager::init_distributed_central_controller_manager()
465479
rclcpp::NodeOptions node_options;
466480
distributed_pub_sub_node_ = std::make_shared<rclcpp_lifecycle::LifecycleNode>(
467481
std::string(get_name()) + "_pub_sub_node", get_namespace(), node_options, false);
482+
//try to add to executor
483+
try
484+
{
485+
executor_->add_node(distributed_pub_sub_node_->get_node_base_interface());
486+
}
487+
catch (const std::runtime_error & e)
488+
{
489+
RCLCPP_WARN_STREAM(
490+
get_logger(),
491+
"ControllerManager: can not add node for distributed publishing/subscribing to executor:"
492+
<< e.what());
493+
}
468494
}
469495
init_distributed_central_controller_manager_services();
470496
}
@@ -499,54 +525,66 @@ void ControllerManager::register_sub_controller_manager_srv_cb(
499525
std::vector<std::shared_ptr<hardware_interface::DistributedReadOnlyHandle>>
500526
distributed_state_interfaces;
501527
distributed_state_interfaces.reserve(sub_ctrl_mng_wrapper->get_state_publisher_count());
528+
// create distributed state interface and import into resource storage.
502529
distributed_state_interfaces =
503530
resource_manager_->import_state_interfaces_of_sub_controller_manager(
504531
sub_ctrl_mng_wrapper, get_namespace(), distributed_pub_sub_node_);
505532

506-
for (const auto & state_interface : distributed_state_interfaces)
533+
// register every node of state_interface at executor only if multiple nodes
534+
// are used. Otherwise the single nodes has already been added
535+
if (use_multiple_nodes())
507536
{
508-
try
509-
{
510-
executor_->add_node(state_interface->get_node()->get_node_base_interface());
511-
}
512-
catch (const std::runtime_error & e)
537+
for (const auto & state_interface : distributed_state_interfaces)
513538
{
514-
response->ok = false;
515-
RCLCPP_WARN_STREAM(
516-
get_logger(),
517-
"ControllerManager: Caught exception while trying to register sub controller manager. "
518-
"Exception:"
519-
<< e.what());
539+
try
540+
{
541+
executor_->add_node(state_interface->get_node()->get_node_base_interface());
542+
}
543+
catch (const std::runtime_error & e)
544+
{
545+
response->ok = false;
546+
RCLCPP_WARN_STREAM(
547+
get_logger(),
548+
"ControllerManager: Caught exception while trying to register node of distributed state "
549+
"interface of sub controller manager. Exception:"
550+
<< e.what());
551+
}
520552
}
521553
}
522554

523555
std::vector<std::shared_ptr<hardware_interface::DistributedReadWriteHandle>>
524556
distributed_command_interfaces;
525557
distributed_command_interfaces.reserve(sub_ctrl_mng_wrapper->get_command_forwarder_count());
558+
// create distributed command interface and import into resource storage.
526559
distributed_command_interfaces =
527560
resource_manager_->import_command_interfaces_of_sub_controller_manager(
528561
sub_ctrl_mng_wrapper, get_namespace(), distributed_pub_sub_node_);
529562

530563
for (const auto & command_interface : distributed_command_interfaces)
531564
{
532-
try
533-
{
534-
executor_->add_node(command_interface->get_node()->get_node_base_interface());
535-
}
536-
catch (const std::runtime_error & e)
565+
// register every node of command_interface at executor only if multiple nodes
566+
// are used. Otherwise the single nodes has already been added
567+
if (use_multiple_nodes())
537568
{
538-
response->ok = false;
539-
RCLCPP_WARN_STREAM(
540-
get_logger(),
541-
"ControllerManager: Caught exception while trying to register sub controller manager. "
542-
"Exception:"
543-
<< e.what());
569+
try
570+
{
571+
executor_->add_node(command_interface->get_node()->get_node_base_interface());
572+
}
573+
catch (const std::runtime_error & e)
574+
{
575+
response->ok = false;
576+
RCLCPP_WARN_STREAM(
577+
get_logger(),
578+
"ControllerManager: Caught exception while trying to register node of distributed "
579+
"command_interface of sub controller manager. Exception:"
580+
<< e.what());
581+
}
544582
}
545583
auto msg = controller_manager_msgs::msg::PublisherDescription();
546584
msg.ns = get_namespace();
547585
msg.name.prefix_name = command_interface->get_prefix_name();
548586
msg.name.interface_name = command_interface->get_interface_name();
549-
// TODO(Manuel) want topic name relative to namespace, but have to treat "root" namespace separate
587+
// TODO(Manuel): want topic name relative to namespace, but have to treat "root" namespace separate
550588
msg.publisher_topic = std::string("/") + command_interface->forward_command_topic_name();
551589
response->command_state_publishers.push_back(msg);
552590
}
@@ -559,52 +597,92 @@ void ControllerManager::register_sub_controller_manager_srv_cb(
559597

560598
void ControllerManager::create_hardware_state_publishers()
561599
{
562-
auto available_state_interfaces = resource_manager_->available_state_interfaces();
563-
564-
for (const auto & state_interface : available_state_interfaces)
600+
std::vector<std::string> state_interfaces_to_export = std::vector<std::string>({});
601+
// export every interface by default
602+
if (!get_parameter("export_state_interfaces", state_interfaces_to_export))
565603
{
566-
auto state_publisher = std::make_shared<distributed_control::StatePublisher>(
567-
std::move(std::make_unique<hardware_interface::LoanedStateInterface>(
568-
resource_manager_->claim_state_interface(state_interface))),
569-
get_namespace(), distributed_interfaces_publish_period(), distributed_pub_sub_node_);
570-
571-
resource_manager_->add_hardware_state_publishers(state_publisher);
604+
// get all available state interfaces
605+
state_interfaces_to_export = resource_manager_->available_state_interfaces();
606+
}
572607

608+
for (const auto & state_interface : state_interfaces_to_export)
609+
{
610+
std::shared_ptr<distributed_control::StatePublisher> state_publisher;
573611
try
574612
{
575-
executor_->add_node(state_publisher->get_node()->get_node_base_interface());
613+
state_publisher = std::make_shared<distributed_control::StatePublisher>(
614+
std::move(std::make_unique<hardware_interface::LoanedStateInterface>(
615+
resource_manager_->claim_state_interface(state_interface))),
616+
get_namespace(), distributed_interfaces_publish_period(), distributed_pub_sub_node_);
576617
}
577-
catch (const std::runtime_error & e)
618+
catch (const std::exception & e)
578619
{
579-
RCLCPP_WARN_STREAM(
580-
get_logger(), "ControllerManager: Can't create StatePublishers<"
581-
<< state_publisher->state_interface_name() << ">." << e.what());
620+
RCLCPP_ERROR(
621+
get_logger(), "Can't create StatePublisher for state interface<'%s'>: %s",
622+
state_interface.c_str(), e.what());
623+
continue;
624+
}
625+
626+
resource_manager_->add_hardware_state_publishers(state_publisher);
627+
628+
if (use_multiple_nodes())
629+
{
630+
try
631+
{
632+
executor_->add_node(state_publisher->get_node()->get_node_base_interface());
633+
}
634+
catch (const std::runtime_error & e)
635+
{
636+
RCLCPP_WARN_STREAM(
637+
get_logger(), "ControllerManager: Can't create StatePublishers<"
638+
<< state_publisher->state_interface_name() << ">." << e.what());
639+
}
582640
}
583641
}
584642
}
585643

586644
void ControllerManager::create_hardware_command_forwarders()
587645
{
588-
auto available_command_interfaces = resource_manager_->available_command_interfaces();
589-
590-
for (auto const & command_interface : available_command_interfaces)
646+
std::vector<std::string> command_interfaces_to_export = std::vector<std::string>({});
647+
// export every interface by default
648+
if (!get_parameter("export_command_interfaces", command_interfaces_to_export))
591649
{
592-
auto command_forwarder = std::make_shared<distributed_control::CommandForwarder>(
593-
std::move(std::make_unique<hardware_interface::LoanedCommandInterface>(
594-
resource_manager_->claim_command_interface(command_interface))),
595-
get_namespace(), distributed_interfaces_publish_period(), distributed_pub_sub_node_);
596-
597-
resource_manager_->add_hardware_command_forwarders(command_forwarder);
650+
// get all available command interfaces
651+
command_interfaces_to_export = resource_manager_->available_command_interfaces();
652+
}
598653

654+
for (auto const & command_interface : command_interfaces_to_export)
655+
{
656+
std::shared_ptr<distributed_control::CommandForwarder> command_forwarder;
599657
try
600658
{
601-
executor_->add_node(command_forwarder->get_node()->get_node_base_interface());
659+
command_forwarder = std::make_shared<distributed_control::CommandForwarder>(
660+
std::move(std::make_unique<hardware_interface::LoanedCommandInterface>(
661+
resource_manager_->claim_command_interface(command_interface))),
662+
get_namespace(), distributed_interfaces_publish_period(), distributed_pub_sub_node_);
602663
}
603-
catch (const std::runtime_error & e)
664+
catch (const std::exception & e)
604665
{
605-
RCLCPP_WARN_STREAM(
606-
get_logger(), "ControllerManager: Can't create CommandForwarder<"
607-
<< command_forwarder->command_interface_name() << ">." << e.what());
666+
RCLCPP_ERROR(
667+
get_logger(), "Can't create CommandForwarder for command interface<'%s'>: %s",
668+
command_interface.c_str(), e.what());
669+
continue;
670+
}
671+
672+
resource_manager_->add_hardware_command_forwarders(command_forwarder);
673+
674+
if (use_multiple_nodes())
675+
{
676+
try
677+
{
678+
executor_->add_node(command_forwarder->get_node()->get_node_base_interface());
679+
}
680+
catch (const std::runtime_error & e)
681+
{
682+
RCLCPP_WARN_STREAM(
683+
get_logger(), "ControllerManager: Can't create CommandForwarder<"
684+
<< command_forwarder->command_interface_name() << ">." << e.what());
685+
}
608686
}
609687
}
610688
}

0 commit comments

Comments
 (0)