Set parameters to multiple rclcpp::Node instances in a single executable / share object across nodes/components
Hello,
I am looking in to a autonomy application setup, where I have one map and several "applications" (=nodes?) accessing its data. For organizational purposes I would like a separate nodes for the map and every other component, as each might have individual subscriptions. As the autonomy nodes will have to query data from the same map, I thought about moving the node to a separate component and communicate via ROS2 services. But this is to slow for the application at hand. Thus I came up with the following setup:
Main executable
#include <pluginlib/class_loader.hpp>
#include <test_pkg/TesteNode1.hpp>
#include <test_pkg/TesteNode2.hpp>
#include <map_pkg/MapNode.hpp>
int main(int argc, char** argv)
{
setvbuf(stdout, NULL, _IONBF, BUFSIZ);
rclcpp::init(argc, argv);
rclcpp::executors::MultiThreadedExecutor executor;
const auto logger = rclcpp::get_logger("OrganizerMain");
RCLCPP_WARN(logger, "main started");
auto map_node = std::make_shared<map_pkg::MapNode>(
rclcpp::NodeOptions().use_intra_process_comms(true));
auto node_1 = std::make_shared<test_pkg::TesteNode1>(
rclcpp::NodeOptions().use_intra_process_comms(true));
node_1->setMap(map_node->getMap());
auto node_2 = std::make_shared<test_pkg::TesteNode2>(
rclcpp::NodeOptions().use_intra_process_comms(true));
node_2->setMap(map_node->getMap());
executor.add_node(map_node);
executor.add_node(node_1);
executor.add_node(node_2);
executor.spin();
rclcpp::shutdown();
return 0;
}
TestNode1 (TestNode2 similar)
...
TesteNode1::TesteNode1(const rclcpp::NodeOptions& _options)
: Node("TesteNode1", _options) {
this->declare_parameter("test_param", "hello world");
RCLCPP_INFO_STREAM(this->get_logger(), "test_param=" << this->get_parameter("test_param").as_string());
}
...
launch file test.py
from launch import LaunchDescription
import launch_ros.actions
def generate_launch_description():
return LaunchDescription([
launch_ros.actions.Node(
namespace= "",
package='test_pkg',
executable='test_node',
output='screen',
emulate_tty=True,
parameters=[
{ "test_param": "Hello1" }
],
)
]
)
Output
$ ros2 launch test_pkg test.py
[INFO] [launch]: All log files can be found below /home/user/.ros/log/2023-06-01-15-41-43-435154-ubuntu-246267
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [test_node-1]: process started with pid [246268]
[tester_node-1] [WARN] [1685626903.514494813] [OrganizerMain]: main started
[tester_node-1] [INFO] [1685626903.523197282] [MapNode]: MapNode started
[tester_node-1] [INFO] [1685626903.523408988] [MapNode]: ...
[tester_node-1] [INFO] [1685626903.532038474] [TesteNode1]: test_param=Hello1
[tester_node-1] [INFO] [1685626903.534378075] [TesteNode2]: test_param=Hello1
The issue running this is the parameter configuration, as I would like to choose different parameters for the nodes in the future and would not like to accidentally mix then in the different nodes.
Question: Is this possible in the launch file or does anyone has another idea how to set this up? Something like from launch import LaunchDescription import launch_ros.actions
def generate_launch_description():
return LaunchDescription([
launch_ros.actions.Node(
namespace= "",
package='test_pkg',
executable='test_node',
output='screen',
emulate_tty=True,
parameters=[
{ "node1" : [
{ "test_param": "Hello1" }
]},
{ "node2" : [
{ "test_param": "Hello2" }
]}
],
)
]
)
TLDR;
I looked a lot into composition and use it in other places, but indicated by the lines
node_1->setMap(map_node->getMap());
node_2->setMap(map_node->getMap());
the setup needs a linking to the map inside test nodes TestNode1 and TestNode2 and the queries to the map are usually of a type response/request with request parameters (e.g. like a position of interest) so I can not use polling. Additionally I tried a service implementation, but with > 100 requests in 1s this is not usable.
Asked by basti.hunter on 2023-06-01 09:08:50 UTC
Comments