ROS Notes Module2
ROS Notes Module2
COLCON (Collective Construction) is a command-line tool for building and managing multiple software
packages. It's particularly popular in the ROS 2 (Robot Operating System 2) ecosystem, but it's general
enough to be used with other systems too. COLCON automates and optimizes the build process,
making it easier to manage complex projects that consist of many interdependent packages.
Prerequisites:
1. Install COLCON:
On Ubuntu:
2. Set up your workspace: A typical ROS 2 workspace structure looks like this:
my_ws/
├── src/
├── build/
├── install/
└── log/
source /opt/ros/humble/[Link]
This ensures that your workspace can find the ROS 2 packages.
1. Create a workspace: In an empty directory (e.g., my_ws), create a src folder for the
packages:
mkdir -p my_ws/src
cd my_ws
2. Clone or add your packages to the src/ folder: For example, if you're cloning a package from
GitHub:
cd src
3. Build the workspace: After adding your packages to the src/ directory, go back to the root of
the workspace and run COLCON to build:
cd ..
colcon build
4. Source the install setup file: Once the build process is complete, you should source the
setup file to make the packages available to your environment:
source install/[Link]
5. Rebuilding after changes: If you modify any package and want to rebuild, you can run:
6. Build logs and troubleshooting: If there are build issues, COLCON generates detailed logs in
the log/ directory. To access them, you can:
cd log/latest_build
You can also use the --event-handlers argument for more verbose output:
Additional Options:
• Build specific packages: You can build only a few selected packages:
• Clean build: If you want to do a clean build (i.e., delete the previous build artifacts):
Package Dependencies:
For COLCON to handle package dependencies, ensure that all dependencies are available in your
workspace or installed system-wide. For ROS 2, most dependencies can be installed using:
By following these steps, you should be able to use COLCON to build and manage your packages
efficiently.
Creating a workspace in ROS 2 is an essential step to start working with ROS 2 packages. A workspace
is a directory where your ROS 2 packages are built, installed, and stored. It allows you to organize
your code and keep everything necessary to run your ROS 2 nodes, including custom and external
packages.
Before creating a workspace, make sure ROS 2 is installed on your system. You can follow the
installation instructions specific to your operating system from the official ROS 2 documentation.
source /opt/ros/<ros_distro>/[Link]
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws
Here, ros2_ws is the name of your workspace, but you can name it whatever you like.
Inside the src/ directory, you can clone or create ROS 2 packages. For example, if you want to clone a
ROS 2 package from GitHub:
cd src
Alternatively, you can create your own package by using ros2 pkg create command:
Once you have added packages to the src/ directory, go back to the root of the workspace and use
COLCON to build the packages:
cd ~/ros2_ws
colcon build
This will build all the packages in the src/ directory and place the compiled output in the install/ and
build/ directories.
After building the workspace, you need to source the environment setup file to use the packages
that were built. This step makes sure ROS 2 knows about your custom packages:
source install/[Link]
You need to do this every time you open a new terminal session, or you can add it to your ~/.bashrc
file for convenience:
source ~/.bashrc
You can verify that your workspace and packages are set up correctly by using ROS 2 commands:
This will list all the ROS 2 packages, including the ones you added in your workspace.
1. Create a workspace:
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws
2. Add a package:
cd src
cd ~/ros2_ws
colcon build
source install/[Link]
Now you're ready to develop and run ROS 2 nodes in your workspace
1. Create a directory for your workspace (if you don’t already have one):
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws
2. Source your ROS 2 environment:
source /opt/ros/<ros-distro>/[Link]
colcon build
source install/[Link]
cd ~/ros2_ws/src
2. Use the ros2 pkg create command to create a package with a Python build type:
Replace <package_name> with the name of the package. The --build-type ament_python specifies
that the package will use Python, and --dependencies lists the dependencies (such as rclpy for
Python ROS 2 nodes and std_msgs for standard message types).
<package_name>
├── [Link]
├── [Link]
├── [Link]
├── resource/
│ └── <package_name>
├── <package_name>/
│ └── __init__.py
├── tests/
└── ...
• [Link]: Defines the package’s metadata, such as its name, version, and dependencies.
• [Link]: Python setup script that specifies how to install the package.
• <package_name>/: This directory contains Python code, including the nodes you’ll write.
• resource/: Contains a file named after your package, used for declaring it as a ROS 2
resource.
<package format="3">
<name>your_package_name</name>
<version>0.0.0</version>
<buildtool_depend>ament_python</buildtool_depend>
<exec_depend>rclpy</exec_depend>
<exec_depend>std_msgs</exec_depend>
<export>
<build_type>ament_python</build_type>
</export>
</package>
5. Modify [Link]
The [Link] file is a Python script for packaging and installing the module. Update it to include your
package:
package_name = 'your_package_name'
setup(
name=package_name,
version='0.0.0',
packages=[package_name],
data_files=[
('share/ament_index/resource_index/packages',
['resource/' + package_name]),
],
install_requires=['setuptools'],
zip_safe=True,
maintainer='your_name',
maintainer_email='your_email@[Link]',
tests_require=['pytest'],
entry_points={
'console_scripts': [
'your_node_name = your_package_name.your_node:main'
],
},
)
7. Edit [Link] (Optional)
You can add the following lines to [Link] to specify the entry point:
[develop]
script_dir=$base/lib/<package_name>
[install]
install_scripts=$base/lib/<package_name>
cd ~/ros2_ws
colcon build
After building, source the workspace:
source install/[Link]
You can now run the node using the ros2 run command:
For example:
In ROS 2 (Robot Operating System 2), communication between nodes is facilitated through a
publisher-subscriber mechanism. A publisher sends messages to a specific topic, and a subscriber
listens to that topic to receive those messages. Let's implement a simple publisher and subscriber in
Python using rclpy, the ROS 2 Python client library.
import rclpy
class SimplePublisher(Node):
def __init__(self):
super().__init__('simple_publisher')
def timer_callback(self):
msg = String()
self.publisher_.publish(msg)
self.get_logger().info(f'Publishing: "{[Link]}"')
self.i += 1
def main(args=None):
[Link](args=args)
publisher = SimplePublisher()
try:
[Link](publisher)
except KeyboardInterrupt:
pass
publisher.destroy_node()
[Link]()
if __name__ == '__main__':
main()
This publisher:
The subscriber will listen to the /chatter topic and print the received messages.
# [Link]
import rclpy
class SimpleSubscriber(Node):
def __init__(self):
super().__init__('simple_subscriber')
[Link] = self.create_subscription(
String,
'chatter',
self.listener_callback,
10)
def main(args=None):
[Link](args=args)
subscriber = SimpleSubscriber()
try:
[Link](subscriber)
except KeyboardInterrupt:
pass
subscriber.destroy_node()
[Link]()
if __name__ == '__main__':
main()
This subscriber:
python3 [Link]
python3 [Link]
Now, the publisher will send messages to the /chatter topic, and the subscriber will receive
those messages and print them to the console.
Explanation:
1. Importing Libraries
import rclpy
from [Link] import Node
from std_msgs.msg import String
• rclpy: This is the ROS 2 client library for Python, which is used to interact with the
ROS system.
• Node: The Node class is a fundamental concept in ROS that allows communication
between different nodes in the network.
• String: The String class is a message type defined in std_msgs, representing
simple string data that will be published on a topic
• Node Name: The node is initialized with the name simple_publisher using the
super().__init__('simple_publisher') call.
• Publisher:
o self.publisher_ = self.create_publisher(String, 'chatter', 10):
This line creates a publisher that will publish String messages on the topic
'chatter'.
o The 10 in the create_publisher call represents the queue size for storing
messages before they are sent, which allows for some buffering.
• Timer: A timer is created with a period of 0.5 seconds ([Link] =
self.create_timer(timer_period, self.timer_callback)), meaning the
timer_callback function will be called every 0.5 seconds.
• Counter: self.i = 0 initializes a counter that will increment each time a message is
published.
4. Timer Callback
def timer_callback(self):
msg = String()
[Link] = f'Hello World: {self.i}'
self.publisher_.publish(msg)
self.get_logger().info(f'Publishing: "{[Link]}"')
self.i += 1
• This is the function that gets called every time the timer triggers (every 0.5 seconds).
• It creates a String message (msg = String()).
• The content of the message is set to "Hello World: <i>", where <i> is the current
value of self.i.
• The message is published on the 'chatter' topic using
self.publisher_.publish(msg).
• The log message self.get_logger().info(f'Publishing: "{[Link]}"')
prints the data being published for debugging purposes.
• Finally, self.i += 1 increments the counter i after each message is sent.
5. Main Function
def main(args=None):
[Link](args=args)
publisher = SimplePublisher()
try:
[Link](publisher)
except KeyboardInterrupt:
pass
publisher.destroy_node()
[Link]()
6. Entry Point
if __name__ == '__main__':
main()
• This block ensures that the main() function is called when the script is run directly.
Summary
This script is a simple ROS 2 publisher node that publishes a string message ("Hello
World: <i>") to the topic 'chatter' every 0.5 seconds. The node logs each message it
publishes.
2. Create the Subscriber Node
The subscriber will listen to the /chatter topic and print the received messages.
# [Link]
import rclpy
class SimpleSubscriber(Node):
def __init__(self):
super().__init__('simple_subscriber')
[Link] = self.create_subscription(
String,
'chatter',
self.listener_callback,
10)
def main(args=None):
[Link](args=args)
subscriber = SimpleSubscriber()
try:
[Link](subscriber)
except KeyboardInterrupt:
pass
subscriber.destroy_node()
[Link]()
if __name__ == '__main__':
main()
This subscriber:
This program is a ROS 2 subscriber node written in Python that listens to a topic called
chatter and logs the messages it receives. The messages are of type String. Here's a
detailed explanation of each part of the code:
1. Imports:
import rclpy
from [Link] import Node
from std_msgs.msg import String
• rclpy: This is the ROS 2 client library in Python, which provides functionality to create ROS
nodes, publish, subscribe, and handle communication.
• Node: The Node class is the basic building block of ROS communication, allowing you to
create and manage a ROS node.
• String: This is a simple string message type defined in the std_msgs package, which will
be used to receive messages from the chatter topic.
• The class SimpleSubscriber is created, inheriting from Node. This class defines the
behavior of a ROS 2 node that will subscribe to a topic and react to the received messages.
3. Initializing the Subscriber Node:
def __init__(self):
super().__init__('simple_subscriber')
[Link] = self.create_subscription(
String,'chatter',
self.listener_callback,10)
[Link] # prevent unused variable warning
• super().init('simple_subscriber'): This line calls the Node class constructor with the name
'simple_subscriber'. The node is now named simple_subscriber within the ROS 2
network.
• self.create_subscription: This method creates a subscription to a ROS 2 topic. Here’s what
each parameter means:
o String: The message type that will be received on the topic (in this case, a string).
o 'chatter': The name of the topic to subscribe to, which is 'chatter' in this case.
o self.listener_callback: The callback function that will be called whenever a
message is received. This function processes the received messages.
o 10: The queue size, which defines how many incoming messages can be buffered if
they are arriving faster than the node can process them.
• [Link]: This stores the subscription object to avoid a warning about an unused
variable.
• This is the callback function that is triggered whenever the node receives a message from
the chatter topic.
• [Link]: This contains the data from the received String message. The message object
msg has a data field that contains the actual string.
• self.get_logger().info(...): This logs the received message using the node's logger, displaying
the string message in the terminal (e.g., I heard: "Hello World: 0").
5. Main Function:
def main(args=None):
[Link](args=args)
subscriber = SimpleSubscriber()
try:
[Link](subscriber)
except KeyboardInterrupt:
pass
subscriber.destroy_node()
[Link]()
• [Link](): This initializes the ROS 2 system, getting everything ready for the node to start
working.
• subscriber = SimpleSubscriber(): This creates an instance of the SimpleSubscriber class,
initializing the node.
• [Link](subscriber): This function keeps the node alive and actively processing incoming
messages. It ensures the node continues to receive messages and triggers the callback
whenever a message arrives.
• try/except KeyboardInterrupt: This block handles a graceful shutdown when the user stops
the program by pressing Ctrl+C.
• subscriber.destroy_node(): Destroys the node cleanly when shutting down.
• [Link](): Shuts down the ROS 2 system after the node is destroyed, ensuring a
graceful exit.
6. Entry Point:
if __name__ == '__main__':
main()
• This block ensures that the main() function is called when the script is executed directly. If
the script is imported as a module, this block will not run.
Summary:
This program creates a simple ROS 2 subscriber node that listens to a topic called chatter
and logs each message it receives. The messages are of type String. It runs in a loop and
processes incoming messages until the user manually interrupts it (with Ctrl+C). The main
purpose of this node is to listen for messages and print them to the console for debugging or
observation.
python3 [Link]
python3 [Link]
Now, the publisher will send messages to the /chatter topic, and the subscriber will receive
those messages and print them to the console.
Explanation:
Creating a simple service in ROS 2 using Python involves setting up a node that provides a
service and another node (or the same one) to request it. Here's a step-by-step guide using
ROS 2 rclpy (the Python client library).
1. Prerequisites
Ensure ROS 2 is installed on your machine. This example assumes you have a ROS 2
workspace set up.
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws
colcon build
source install/[Link]
2. Create a Package
cd ~/ros2_ws/src
ros2 pkg create my_service_pkg --build-type ament_python --dependencies
rclpy example_interfaces
This creates a basic package. We’ll use the example_interfaces package, which provides a
simple AddTwoInts service.
File: my_service_pkg/add_two_ints_server.py
import rclpy
from [Link] import Node
from example_interfaces.srv import AddTwoInts
class AddTwoIntsService(Node):
def __init__(self):
super().__init__('add_two_ints_server')
[Link] = self.create_service(AddTwoInts, 'add_two_ints',
self.add_two_ints_callback)
self.get_logger().info('Service ready to add two integers.')
def main(args=None):
[Link](args=args)
node = AddTwoIntsService()
[Link](node)
[Link]()
if __name__ == '__main__':
main()
File: my_service_pkg/add_two_ints_client.py
import sys
import rclpy
from [Link] import Node
from example_interfaces.srv import AddTwoInts
class AddTwoIntsClient(Node):
def __init__(self):
super().__init__('add_two_ints_client')
[Link] = self.create_client(AddTwoInts, 'add_two_ints')
while not [Link].wait_for_service(timeout_sec=1.0):
self.get_logger().info('Waiting for service to become
available...')
self.get_logger().info('Service is now available!')
def main(args=None):
[Link](args=args)
if len([Link]) < 3:
print('Usage: ros2 run my_service_pkg add_two_ints_client <int_a>
<int_b>')
return
client = AddTwoIntsClient()
response = client.send_request(int([Link][1]), int([Link][2]))
print(f'Result: {[Link]}')
[Link]()
if __name__ == '__main__':
main()
5. Update [Link]
Modify the [Link] to make the scripts executable.
File: my_service_pkg/[Link]
from setuptools import setup
package_name = 'my_service_pkg'
setup(
name=package_name,
version='0.0.0',
packages=[package_name],
install_requires=['setuptools'],
zip_safe=True,
maintainer='your_name',
maintainer_email='your_email@[Link]',
description='Simple service and client example in ROS 2',
license='Apache License 2.0',
entry_points={
'console_scripts': [
'add_two_ints_server =my_service_pkg.add_two_ints_server:main',
'add_two_ints_client =my_service_pkg.add_two_ints_client:main',
],
},
)
cd ~/ros2_ws
colcon build
source install/[Link]
Result: 15
8. Explanation
• Service Node: Provides the AddTwoInts service that sums two integers.
• Client Node: Sends two integers as a request to the service and prints the result.
Q Creating custom msg and srv files in ROS 2
Creating custom message (msg) and service (srv) files in ROS 2 involves defining your own
message and service types, building them into your package, and then using them in nodes.
Below is a step-by-step guide for this.
Create a new package that will hold the custom messages and services.
cd ~/ros2_ws/src
ros2 pkg create my_custom_interfaces --build-type ament_cmake
Inside the new package, create the directories for message and service definitions.
cd ~/ros2_ws/src/my_custom_interfaces
mkdir msg srv
File: my_custom_interfaces/msg/[Link]
int64 num
File: my_custom_interfaces/srv/[Link]
# Request
int64 a
int64 b
int64 c
---
# Response
int64 sum
This service takes three integers as input and returns their sum.
5. Modify [Link]
File: my_custom_interfaces/[Link]
find_package(rosidl_default_generators REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME}
"msg/[Link]"
"srv/[Link]"
)
ament_package()
6. Modify [Link]
Ensure your [Link] includes dependencies for building messages and services.
File: my_custom_interfaces/[Link]
<build_depend>rosidl_default_generators</build_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
cd ~/ros2_ws
colcon build --packages-select my_custom_interfaces
source install/[Link]
You can now use the custom message and service in your Python nodes.
import rclpy
from [Link] import Node
from my_custom_interfaces.srv import AddThreeInts
class AddThreeIntsService(Node):
def __init__(self):
super().__init__('add_three_ints_server')
[Link] = self.create_service(AddThreeInts, 'add_three_ints',
self.handle_add_three_ints)
self.get_logger().info('Service ready to add three integers.')
def main():
[Link]()
node = AddThreeIntsService()
[Link](node)
[Link]()
if __name__ == '__main__':
main()
Example Client Node: add_three_ints_client.py
import rclpy
from [Link] import Node
from my_custom_interfaces.srv import AddThreeInts
class AddThreeIntsClient(Node):
def __init__(self):
super().__init__('add_three_ints_client')
[Link] = self.create_client(AddThreeInts, 'add_three_ints')
future = [Link].call_async(request)
rclpy.spin_until_future_complete(self, future)
return [Link]()
def main():
[Link]()
client = AddThreeIntsClient()
response = client.send_request(1, 2, 3)
print(f'Sum: {[Link]}')
[Link]()
if __name__ == '__main__':
main()
If you are working with an ament Python package, you’ll need to make sure your [Link]
is configured to include your new nodes.
10. Build and Run the Nodes
Make sure the package is built, and then run the service and client:
Sum: 6
Implementing custom interfaces (both messages and services) in ROS 2 involves creating
your own data structures that can be exchanged between nodes. Below is a detailed guide to
create, build, and use custom message and service interfaces in ROS 2.
Let’s start by creating a new package where the custom messages and services will reside.
cd ~/ros2_ws/src
ros2 pkg create my_custom_interfaces --build-type ament_cmake
This command creates the package named my_custom_interfaces with ament_cmake as the
build tool.
Navigate to the package directory and create the necessary subdirectories for messages and
services.
cd ~/ros2_ws/src/my_custom_interfaces
mkdir msg srv
File: msg/[Link]
int64 num
Create a service file that accepts three integers and returns their sum.
File: srv/[Link]
# Request
int64 a
int64 b
int64 c
---
# Response
int64 sum
Update [Link] to make sure ROS 2 builds the custom message and service.
5. Update [Link]
File: [Link]
<build_depend>rosidl_default_generators</build_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
cd ~/ros2_ws
colcon build --packages-select my_custom_interfaces
source install/[Link]
7. Implement Nodes Using Custom Interfaces
We’ll now create a service node and a client node that use the custom AddThreeInts
service.
File: add_three_ints_server.py
import rclpy
from [Link] import Node
from my_custom_interfaces.srv import AddThreeInts
class AddThreeIntsService(Node):
def __init__(self):
super().__init__('add_three_ints_server')
[Link] = self.create_service(AddThreeInts, 'add_three_ints',
self.handle_add_three_ints)
self.get_logger().info('AddThreeInts service is ready.')
def main(args=None):
[Link](args=args)
node = AddThreeIntsService()
[Link](node)
[Link]()
if __name__ == '__main__':
main()
File: add_three_ints_client.py
import rclpy
from [Link] import Node
from my_custom_interfaces.srv import AddThreeInts
class AddThreeIntsClient(Node):
def __init__(self):
super().__init__('add_three_ints_client')
[Link] = self.create_client(AddThreeInts, 'add_three_ints')
future = [Link].call_async(request)
rclpy.spin_until_future_complete(self, future)
return [Link]()
def main(args=None):
[Link](args=args)
client = AddThreeIntsClient()
response = client.send_request(3, 4, 5)
print(f'Result: {[Link]}')
[Link]()
if __name__ == '__main__':
main()
If you want to run your nodes as executables, modify the [Link] file.
File: [Link]
from setuptools import setup
package_name = 'my_custom_interfaces'
setup(
name=package_name,
version='0.0.0',
packages=[],
install_requires=['setuptools'],
zip_safe=True,
maintainer='your_name',
maintainer_email='your_email@[Link]',
description='Custom interfaces example in ROS 2',
license='Apache License 2.0',
entry_points={
'console_scripts': [
'add_three_ints_server =
my_custom_interfaces.add_three_ints_server:main',
'add_three_ints_client =
my_custom_interfaces.add_three_ints_client:main',
],
},
)
After adding the new nodes and making changes, build the package again.
cd ~/ros2_ws
colcon build
source install/[Link]
10. Run the Service and Client Nodes
Open two terminals and run the service and client nodes.
Client Output:
Result: 12
Service Output:
To confirm that the custom interfaces were generated successfully, you can use the following
commands:
Using parameters in a ROS 2 class allows you to set and manage configuration values that
can be adjusted without changing the code. Below is an example of how to use parameters
inside a ROS 2 node implemented as a Python class.
cd ~/ros2_ws/src
ros2 pkg create my_param_pkg --build-type ament_python --dependencies rclpy
Create a Python script that demonstrates how to declare, set, and get parameters within a
class.
File: my_param_pkg/param_node.py
import rclpy
from [Link] import Node
class ParameterNode(Node):
def __init__(self):
super().__init__('parameter_node')
# Get parameters
self.my_integer = self.get_parameter('my_integer').value
self.my_string = self.get_parameter('my_string').value
def timer_callback(self):
# Update parameters dynamically (if needed)
self.my_integer = self.get_parameter('my_integer').value
self.my_string = self.get_parameter('my_string').value
def main(args=None):
[Link](args=args)
node = ParameterNode()
try:
[Link](node)
except KeyboardInterrupt:
pass
node.destroy_node()
[Link]()
if __name__ == '__main__':
main()
3. Update [Link]
Make sure the script is properly registered in [Link].
File: [Link]
from setuptools import setup
package_name = 'my_param_pkg'
setup(
name=package_name,
version='0.0.0',
packages=[package_name],
install_requires=['setuptools'],
zip_safe=True,
maintainer='your_name',
maintainer_email='your_email@[Link]',
description='A ROS 2 node using parameters',
license='Apache License 2.0',
entry_points={
'console_scripts': [
'param_node = my_param_pkg.param_node:main',
],
},
)
cd ~/ros2_ws
colcon build --packages-select my_param_pkg
source install/[Link]
You can use ros2 param commands to get or set parameters dynamically.
4. Observe the updated value: The updated value will be logged after the next timer
callback.
8. Explanation
• Parameter Declaration:
o declare_parameter() is used to declare parameters with default values.
o Parameters must be declared before they can be accessed or set.
• Accessing Parameters:
o get_parameter('param_name').value retrieves the value of a declared
parameter.
• Dynamic Updates:
o Parameters can be updated dynamically using the ros2 param command or within
the node using a callback.
ros2doctor is a useful tool for diagnosing and identifying issues in a ROS 2 environment.
It checks your system configuration and identifies potential problems that could affect your
ROS 2 setup.
ros2doctor is included in the ros2cli package, but if it's not installed, you can install it
with the following command:
2. Running ros2doctor
You can run ros2doctor from the terminal to scan for common issues.
ros2 doctor
Sample Output:
yaml
=== ROS 2 SYSTEM STATUS ===
ROS 2 distro: humble
System OS: Ubuntu 22.04
Python version: 3.10.6
RMW implementation: rmw_fastrtps_cpp
• ROS 2 distribution: Checks if the correct ROS 2 version is installed and used.
• Environment variables: Ensures that critical ROS 2 environment variables are set correctly
(e.g., ROS_DOMAIN_ID, RMW_IMPLEMENTATION).
• Network configuration: Verifies if the system's network configuration is appropriate for ROS
2 communication.
• Node duplication: Ensures there are no duplicate nodes running.
• Python and dependencies: Confirms that compatible Python versions and dependencies are
installed.
If ros2doctor detects issues, it will print a summary along with suggestions for resolving
them. Here are some common issues it may report:
source /opt/ros/humble/[Link]
• Problem: Hostname not set properly, or multicast is disabled, which may cause nodes to fail
to communicate.
• Solution: Ensure that the hostname is correctly configured and that multicast is enabled on
your network.
If you encounter issues with communication, you can use ros2doctor to check the RMW
implementation.
export RMW_IMPLEMENTATION=rmw_fastrtps_cpp