Building a ROS 2 project — Part 2

Sharad Maheshwari
6 min readFeb 12, 2022

--

Note: Check out Part 0 and Part 1 to understand how this series is set up.

Hello again!

In Part 0, we described our problem statement — Build a Trash Collection Robot in ROS 2. In Part 1, we set up the entire project with two custom packages — perception and brain.

Now it’s time to improve our project with two ROS features — Launch Files and Parameters

Let’s begin!

Note — To follow this lesson, you need to complete Part 0 and Part 1. The next set of steps is a continuation of Part 1.

Launch Files —

In part 1, we ran perception and brain nodes separately using the following two commands —

ros2 run perception perception
ros2 run brain brain

We will now use a launch file, which provides an interface to run multiple nodes at once (and much more).

Step 1 — Create a launch file
Create a launch directory

cd ros2_ws
mkdir launch && cd launch
gedit robot.launch.py

Add the following code to robot.launch.py —

Let’s look at what our launch file says —

  1. Line 5 — generate_launch_description is used by ROS 2 to understand what is to be launched
  2. Line 6 — Launch description object will contain complete information about all required nodes
  3. Line 7/13 — Each Node object needs information about that specific node (not limited to what is shown here). We have the following minimum requirements to define —
    a. package: name of the package
    b. namespace: namespace the node should be a part of
    c. executable: name of the executable (we defined in setup.py)
    d. name: name of the node

That’s all we need to understand launch basics at this point.

Step 2 — Run robot.launch.py —
Remember to source ROS2 and the project

source /opt/ros/galactic/setup.bash
cd ros2_ws
. install/setup.bash
ros2 launch launch/robot.launch.py

You will see the following —

Every 5 seconds, brain will request for perception camera’s battery status, which is something we already. But there’s a difference this time — both nodes are run using the launch file.

Step 3 — Publish on camera topic

Let’s try publishing on camera topic, which should be processed in perception for trash detection. brain should then receive this information from perception and decide if it should command the actuator to move.

Open a new terminal and while the system is up, run the following —

source /opt/ros/galactic/setup.bash
ros2 topic pub --once /camera std_msgs/String “data: trash”

We expected perception and brain to act on this information. But did it? Nope! We did not see anything on the terminal we’re using to run this system

What’s wrong? I’ll wait for you to guess!

Hint — Please look at the launch file

Here’s the problem — we asked robot_one namespace to be used for the two nodes. Thus, the nodes expect the topic to also be in the same namespace.

Solution: camera topic changes to robot_one/camera

source /opt/ros/galactic/setup.bash
ros2 topic pub --once /robot_one/camera std_msgs/String “data: trash”

If everyone was correct, you will see “Publishing: “I see trash"” and “Sending move request to actuator” from perception and brain respectively

Woot woot! Our launch file works!

In a ROS1/ROS2 project, launch files are used to run multiple nodes with one launch command. Running each node individually in a big project is impractical.

Well, launch files can do much more. That brings us to the next topic — ROS2 parameters.

ROS2 Parameters —

Since you know about ROS1, we don’t need to describe ROS parameters.

In this section, we’ll show how to use ROS 2 parameters using our launch file.
Up until now, we hard coded topic and service names in node files. But now we will set these using parameters and leverage our newly made launch file.

Let’s move straight to all the changes we need to do now.

Step 1 — Update perception node to use parameters
This is our new(updated) node file, perception_node.py—

Let’s talk about what changed in perception_node.py — Instead of hardcoding topic and service names, we now read them as parameters (which we will pass in our launch file). This servers as an example of parameter usage.

  1. Line 13 to 24 — To use parameters(both get and set), we first need to declare them here.
  2. Line 26/47 to 53 — After declaring parameters, we use ROS 2 API (in our custom method get_parameter_values) to get parameters values for camera topic, trashDetection topic and componentStatus service.
  3. Line 28 to 45 — Previously, we hardcoded the three values (2 topic names and 1 service name). Now, we read these as parameters and use them to create publisher, subscriber, and service)

Step 2 — Update brain node to use parameters
This is our new node file, brain_node.py—

Let’s talk about what changed in brain_node.py— Like the node file above, we read topic and service names passed in the launch file as parameters.

  1. Line 15 to 22 — To use a parameter (both get and set), we first need to declare them here.
  2. Line 24/47 to 51 — After declaring parameters, we use ROS 2 API (in our custom method get_parameter_values) to get parameters values for trashDetection topic and componentStatus service.
  3. Line 27 and Line 41— Previously, we hardcoded the three values (1 topic name and 1 service name). Now, we read these as parameters and use them to create publisher and service client

Step 3 — Update launch file to use parameters

This is our new launch file, robot.launch.py —

With a slight change in our previous launch file, we are ready to pass parameters to the two nodes.

Line 13 — Since brain needs trashDetectionTopic name and componentStatusService name, we pass this information as a dictionary (key — parameter name, value — parameter value)

Line 24 — Since perception needs cameraTopic name, trashDetectionTopic name and componentStatusService name, we pass this information as a dictionary (key — parameter name, value — parameter value)

Putting it all together —

That’s it! We now have all the pieces in place to run our Trash Collection Robot with two new ROS 2 features — launch files and parameters

Why the wait? Let’s run!

And don’t forget to build!

source /opt/ros/galactic/setup.bash
cd ros2_ws
colcon build
. install/setup.bash
ros2 launch launch/robot.launch.py

If everything is correct, your nodes will start running 😀

One a new terminal, we can try publishing on robot_one/camera again.

source /opt/ros/galactic/setup.bash
ros2 topic pub — once /robot_one/camera std_msgs/String “data: trash”

We will see perception and brain processing this information, like before!

Woot woot! We’re done with this lesson.

Recap —

We started this series by understanding our problem statement — Building a Trash Collection Robot. We then build all necessary packages and connected them together to bring our Robot to life. In this part, we improved our project with launch files and parameters.

I am quite happy with what we’ve done. I hope you are too! 😁

Behold! Shit gets real now!

We’re done with building a functional project for our Trash Collection Robot. But we’re starting an undervalued, but extremely important section — Building Test Infrastructure.

We’ll build unit and integration tests, and then use Docker and Github Actions for CI/CD. This section is imperative to build, maintain and scale a Robotics project.

See you again?
Also, I currently have shelved the next 2 parts until I find time for another side project I’m working on (also documenting on medium). But I’ll be back on this one soon

Ciao,
Sharad

--

--