In this post, you will learn how to create ros2 XML launch files. You’ll discover how ros2 XML launch files are similar to and different from their ros1 counterparts.
Step 1: Get a Copy of the ROS package containing the code used in the post
Click here to copy the project. It would be copied to your cloud account at The Construct. That done, open the project using the Run button. This might take a few moments, please be patient.
PS: If you don’t have an account on the The Construct, you would need to create one. Once you create an account or log in, you will be able to follow the steps to read and write parameters in ros1 and ros2.
You might also want to try this on a local PC if you have ROS installed. In that case you need to read on and duplicate the source code of the package in your own local workspace. However, please note that we cannot support local PCs and you will have to fix any errors you run into on your own.
Step 2: Explore the source code using the IDE
Open the IDE by clicking on the icon as shown above. You should now see something similar to the image below:
The main file we will work with in this post is the one highlighted in red in the image above:
Double-click on the file in the IDE to open and study the contents. We will discuss this file in the following steps.
Step 3: Understand how to create ros2 XML launch files
Wait first! I thought ros2 launch files are only written in Python! Yes, Python is one of the options when writing ros2 launch files; we can also use XML files, especially if we are writing simple launch files that do not need to leverage Python’s powerful API.
On line 2, we define an argument (variable) use_sim_time with a default value of true.
On line 3, we include another launch file, turtlebot3_world.launch.py for launching the TurtleBot3 world. The launch file can be found in the turtlebot3_gazebo package.
On line 4, we pass a required argument use_sim_time to the included launch file, assigning it the value of the use_sim_time defined on line 2.
On line 6, we define a node to be started by the launch file. This node can be found in the package patrol_action_server, the node executable is patrol_action_server_exe and the name of the node would appear as patrol_action_server.
In short, this launch file launches the TurtleBot3 world and starts the Patrol action server. The same launch file can be written in Python, but this XML looks simpler and easier to understand. And it does all we want it to do, and we can even include Python-based launch files!
Step 4: Understand how ros2 XML launch files are similar to/different from ros1 XML launch files
If you are familiar with ros1 launch files, you should already notice some similarities:
The same <launch> tag.
Similar <arg> tag.
Familiar <include> tag.
Similar <node> tag.
Now if we were writing the same launch file in ros1, it would be something like this (PS: we can’t include ros2 launch file in a ros1 launch file in reality):
Did you like this post? Do you have any questions about how to read and write parameters in ros1 and ros2? Whatever the case, please leave a comment on the comments section below, so we can interact and learn from each other.
If you want to learn about other ROS topics, please let us know in the comments area and we will do a video or post about it.
In this post, you will learn how to read and write parameters in ros1 and ros2, using C++ nodes. You will see the slight differences in the ros1 and ros2 nodes and parameter files.
Step 1: Get a Copy of the ROS package containing the code used in the post
Click here to copy the project. It would be copied to your cloud account at The Construct. That done, open the project using the Run button. This might take a few moments, please be patient.
PS: If you don’t have an account on the The Construct, you would need to create one. Once you create an account or log in, you will be able to follow the steps to read and write parameters in ros1 and ros2.
You might also want to try this on a local PC if you have ROS installed. In that case you need to read on and duplicate the source code of the package in your own local workspace. However, please note that we cannot support local PCs and you will have to fix any errors you run into on your own.
Step 2: Explore the source code using the IDE
Open the IDE by clicking on the icon as shown above. You should now see something similar to the image below:
The six main files we will work with in this post are highlighted in red in the image above. These files are:
Double-click on each of the files in the IDE to open and study the contents. We will examine some of these files in the following steps.
Step 3: Understand how to read and write (load) parameters in ROS1
Now it’s time to see how to read and write parameters in ros1, working in the ros1 workspace.
Open a web shell and run the following commands:
cd ~/catkin_ws
source /opt/ros/noetic/setup.bash
source devel/setup.bash
roscore
The code block above changes to the ros1 workspace, sources it, and then starts the roscore (needed for ros1). Now let’s see a list of the current ros1 parameters available. Open another web shell and type the following:
But wait…are we getting the parameters in the YAML file (catkin_ws/src/yaml_parameters_ros1/config/params_demo_ros1.yaml) and their correct values? Let’s see what’s the in there!
Gosh, we are not getting these parameters nor their values, and you probably know why! So far we have been reading the parameters but have loaded them. Now let’s get that done: enter the launch file catkin_ws/src/yaml_parameters_ros1/launch/ros1_params_cpp_demo.launch.
Can you spot the differences between the formal and the latter outputs of these commands? Sure you can! So, well, that’s how to read and load parameter in ros1!
Step 4: Understand how to read and write (load) parameters in ROS2
Now let’s change to the ros2 workspace.
cd ~/ros2_ws
source /opt/ros/foxy/setup.bash
source install/setup.bash
In ros2 we need to have a node running before we can check for parameters, because there is no parameter server in ros2. Let’s try running the node then. The logic behind this node is contained in the ros2_ws/src/yaml_parameters/src/yaml_params_ros2.cpp file:
#include <rclcpp/rclcpp.hpp>
class MainNode : public rclcpp::Node {
public:
MainNode() : rclcpp::Node("node", rclcpp::NodeOptions()) {
// example: declare parameters, default value given
declare_parameter("param0", 1);
declare_parameter("param1", 0.1);
declare_parameter("param2", "default");
declare_parameter("param3.weight", 1);
declare_parameter("param3.name", "default");
declare_parameter("param4", false);
// example: declare a variable when declaring a parameter
declare_parameter("param5", std::vector<bool>(3, false));
declare_parameter("param6", std::vector<int64_t>(4, 1));
declare_parameter("param7", std::vector<double>(4, 0.1));
declare_parameter("param8", std::vector<std::string>(5, "default"));
// Get parameter values one by one
auto p0 = get_parameter("param0").as_int();
auto p1 = get_parameter("param1").as_double();
auto p2 = get_parameter("param2").as_string();
auto p3weight = get_parameter("param3.weight").as_int();
auto p3name = get_parameter("param3.name").as_string();
auto p4 = get_parameter("param4").as_bool();
auto p5 = get_parameter("param5").as_bool_array();
auto p6 = get_parameter("param6").as_integer_array();
auto p7 = get_parameter("param7").as_double_array();
auto p8 = get_parameter("param8").as_string_array();
// Print parameters
RCLCPP_INFO(get_logger(), "Integer parameter: %ld", p0);
RCLCPP_INFO(get_logger(), "Double parameter: %f", p1);
RCLCPP_INFO(get_logger(), "String parameter: %s", p2.c_str());
RCLCPP_INFO(get_logger(), "Nested integer parameter: %ld", p3weight);
RCLCPP_INFO(get_logger(), "Nested string parameter: %s", p3name.c_str());
RCLCPP_INFO(get_logger(), "Boolean parameter: %d", p4);
RCLCPP_INFO(get_logger(), "Boolean vector parameter [0]: %d",
static_cast<int>(p5[0]));
RCLCPP_INFO(get_logger(), "Integer vector parameter [0]: %d",
static_cast<int>(p6[0]));
RCLCPP_INFO(get_logger(), "Double vector parameter [0]: %f",
static_cast<double>(p7[0]));
RCLCPP_INFO(get_logger(), "String vector parameter [0]: %s", p8[0].c_str());
}
};
int main(int argc, char **argv) {
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<MainNode>());
rclcpp::shutdown();
return 0;
}
No, we are not :(. But not to worry, the launch file ros2_ws/src/yaml_parameters/launch/yaml_parameters.launch.py comes to the rescue! Let’s examine its content.
#!/usr/bin/env python3
import os
from launch import LaunchDescription
from launch_ros.actions import Node
from ament_index_python.packages import get_package_share_directory
def generate_launch_description():
return LaunchDescription([
Node(
package='yaml_parameters',
executable='main_node',
name='parameter_types_example',
parameters=[os.path.join(
get_package_share_directory('yaml_parameters'),
'config', 'params_demo_ros2.yaml')],
output='screen'),
])
Oh my, it’s a Python! Let’s set it loose and see what happens! Stop the currently running program with Ctrl + C and run the following in its place and check that your output is similar.
The launch file simply loads the parameters in the YAML file and also runs the node we run earlier.
Well, that’s it!
Step 5: Check your learning
Do you understand how to read and write parameters in ros1 and ros2, using C++ nodes?
Did you notice the slight differences in the format of the YAML files for ros1 and ros2?
Did you notice that you the ros2 parameters are tied to specific nodes vs existing in a parameter server in ros1?
If you didn’t get any of the points above, please go over the post again, more carefully this time.
Extra Step: Watch the video to understand how to read and write parameters in ros1 and ros2
Here you go:
Feedback
Did you like this post? Do you have any questions about how to read and write parameters in ros1 and ros2? Whatever the case, please leave a comment on the comments section below, so we can interact and learn from each other.
If you want to learn about other ROS topics, please let us know in the comments area and we will do a video or post about it.