ROS Serial Examples: Mastering Communication Between Robots and Hardware

Robot Operating System (ROS) has become an indispensable tool for building and programming advanced robots. As you dive into the world of robotics, understanding the communication between components is critical. ROS offers this capability via a variety of communication protocols, with serial communication being a practical method for interfacing with hardware. This tutorial will provide you with examples of using ROS to facilitate serial communication, which is essential when you need to talk to microcontrollers, sensors, and other serial devices.

Getting started with ROS for serial communication can initially seem daunting. However, with detailed examples, you’ll learn how to set up ROS nodes that can send and receive serialized data efficiently. Through hands-on tutorials, you will gain insights into the intricacies of serialization and deserialization processes. Moreover, examining examples will shed light on common patterns and practices, such as establishing connections, handling message serialization, and ensuring thread safety while interacting with serial devices.

Getting Started with ROS and Serial Communication

Serial communication is essential in robotics for interfacing different hardware elements. The ROS ecosystem facilitates this through the rosserial package, creating a bridge between ROS and microcontrollers like Arduino.

Understanding ROS Serial

ROS, or the Robot Operating System, is a flexible framework for writing robot software. For serial communication, rosserial provides a protocol for wrapping standard ROS serialized messages and multiplexing multiple topics over a serial device. To communicate with an Arduino, rosserial_arduino allows your ROS-enabled computer to interact seamlessly with the Arduino via a serial interface.

When working with rosserial on Arduino, you can publish and subscribe to ROS topics, allowing sensor data to flow from the Arduino into the ROS ecosystem and commands from ROS to reach the actuators controlled by the Arduino.

Prerequisites and Installation

Before installing rosserial, ensure that you have a working ROS installation on a Linux or Windows machine. ROS Noetic, for example, should be fully installed, and your environment properly set up with the source command.

To install rosserial, navigate to your ROS workspace’s src directory:

cd your_ros_workspace/src

Use git to clone the rosserial repository from GitHub:

git clone

Then, build the package with catkin_make or catkin build from the root of your ROS workspace:

cd your_ros_workspace

Alternatively, on some ROS distributions, you may install rosserial using apt:

sudo apt-get install ros-noetic-rosserial-arduino
sudo apt-get install ros-noetic-rosserial

Remember to source your ROS environment after the installation:

source devel/setup.bash

To communicate with an Arduino, it must be programmed with a compatible rosserial client library. Install it using the Arduino IDE, which can be found in the rosserial_arduino package’s lib directory. After installation, your Arduino will be ready to establish a serial connection, ensuring roscore is running on your machine to manage ROS communications.

Setting Up ROS Serial with Arduino

Integrating an Arduino with ROS (Robot Operating System) is achievable by using the ROS Serial communication protocol. This allows your Arduino to publish and subscribe to ROS messages, making it an active node in a ROS network.

Configuring Arduino IDE

Before incorporating the Arduino into your ROS environment, you need to set up the Arduino IDE. First, ensure you have the Arduino IDE installed on your computer. Connect your Arduino to the computer via a USB cable and select the correct board and port from the Tools menu. It’s crucial that your board’s drivers are installed properly to ensure smooth communication.

ROS Serial Arduino Library

Next, you’ll install the rosserial_arduino library, which allows your Arduino to communicate with ROS. You can install this library using the Arduino IDE‘s Library Manager. Search for rosserial_arduino and install it.

Once installed, include the ros.h library at the beginning of your Arduino sketch to access ROS functions. Initialize a NodeHandle with ros::NodeHandle nh; which will act as the main access point to communications with the ROS system.

Configure publishers and subscribers according to your needs, using the nh.advertise and nh.subscribe methods, respectively. When defining a publisher or subscriber, specify the topic name and message type (e.g., std_msgs). For example, to create a publisher:

ros::Publisher pub("topic_name", &msg_type);

Replace pub, topic_name, and msg_type with your specific publisher name, ROS topic name, and ROS message type.

To compile and upload your sketch to the Arduino, use the Upload button. Now your Arduino is ready to send and receive messages using ROS Serial.

In the terminal, navigate to your catkin workspace and compile the rosserial package using the commands cd into your workspace and then make. Launch the rosserial node with the appropriate parameters to establish a serial connection to your Arduino.

With your Arduino programmed and the ROS environment configured, your Arduino can now read and write messages to ROS, effectively becoming a node capable of publishing to and subscribing from topics in your ROS network. Remember, successful communication depends on the correct serial port and baud rate settings, which should match between your sketch and ROS configuration.

ROS Serial Communication Protocols and Handling

In this section, you’ll learn the specifics of establishing a serial connection with ROS, managing data flow through subscribing and publishing, and the intricacies of ROS serial messages and topics. This ensures smooth and reliable communication between your robotic components.

Establishing a Serial Connection

To initiate a serial connection in ROS, you need to specify crucial parameters such as baudrate, timeout, and port. Typically, you’d set the baudrate to a standard value like 57600 or 115200, depending on your hardware’s capability. Using the rosserial library, particularly, you execute a command such as:

rosrun rosserial_python _port:=/dev/ttyUSB0 _baud:=57600

Ensure your user has permissions to access the serial port (/dev/ttyUSB0), which may require being part of the dialout group. Confirm the connection is established with isopen, and if necessary, use flush to clear the input and output buffers.

Subscribing and Publishing

Once a serial connection is made, subscribing to topics and publishing from your node involves creating a NodeHandle and defining subscribers and publishers. For instance:

ros::NodeHandle nh;
nh.subscribe("topic_name", 1000, topicCallback);

This enables your robot to receive (subscribe) and send (publish) data packets, formatted as specified by the message protocol. Use the associated topic_id for referencing specific topics in your embedded code.

ROS Serial Messages and Topics

Messages in ROS are data structures comprised of fields that can be standard types such as int, float, string, or arrays. When working with serial communication, you frequently deal with strings and bytes read. The CTS (Clear To Send) and RTS (Request To Send) can be used to manage the flow control if the protocol, such as RS-232, supports it.

ROS topics are named buses over which nodes exchange messages. They adhere to a publish-subscribe model where nodes publish messages to topics and other nodes subscribe to those topics. An important aspect is to keep track of the baudrate for synchronized communication. It’s also crucial to manage read and timeout settings to ensure data integrity during transmission.

Advanced ROS Serial Topics

In this section, you’ll gain insights into handling complex data structures and managing hardware-level interrupts when working with ROS serial communication. This knowledge is vital for developing sophisticated robotics applications that require efficient and robust interactions between ROS and microcontroller units.

Custom Message Types

When you’re working with ROS, sometimes the predefined message types can’t cover all your use case needs. As a developer, you have the option to define custom message types for specialized data. Creating custom messages in rosserial_client libraries allows your microcontrollers, like Arduino or STM32, to exchange unique data structures with ROS systems. Remember to include the custom message headers in your sketch and to follow the ROS package directory structure. To integrate custom messages with Arduino, you typically include #include <ros.h> and #include <your_custom_msg/YourMessageType.h> in your code.

For instance, when working with an Arduino board for servo control, you might design a custom message to handle specific attributes like angle, speed, and direction. Here’s an example for an Arduino publisher that could send such custom messages:

#include <ros.h>
#include <your_custom_msg/ServoControl.h>

ros::NodeHandle nh;
your_custom_msg::ServoControl servo_msg;
ros::Publisher servo_pub("servo_topic", &servo_msg);

void setup() {

void loop() {
  // Populate your custom message
  servo_msg.angle = 90; // Set desired angle
  servo_msg.speed = 1.0; // Set speed

Interrupt Handling in ROS Serial

When using rosserial_arduino with platforms like Teensy or mbed, handling hardware interrupts can be critical, especially if you’re aiming for real-time responsiveness. The rosserial_arduino library allows Arduino boards and other compatible microcontrollers like Teensy 3.x or STM32 platforms using STM32duino to handle interrupts effectively.

For instance, if you’re using an Arduino or Teensy to control a servo via ROSSerial, you might set up an interrupt to react to an external event, thereby triggering a subscriber callback. When setting up the use_stm32_hw_serial, be aware that hardware serial ports ensure more reliable communication than software serial and can better handle the timing critical nature of interrupt signals.

Here’s a skeleton code example for an interrupt service routine (ISR) in your ROS project with a rosserial_client setup:

#include <ros.h>
#include <std_msgs/Empty.h>

ros::NodeHandle nh;
void messageCb(const std_msgs::Empty& toggle_msg);
ros::Subscriber<std_msgs::Empty> sub("toggle_topic", &messageCb);

void messageCb(const std_msgs/Empty& toggle_msg) {
  // Handle the interrupt event here
  // For example, toggle an LED or send a signal to a servo

void setup() {
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, CHANGE);

void loop() {
  // Other non-blocking code

void handleInterrupt() {
  // A minimal ISR
  // Be cautious about the content of the ISR, keep it short and responsive

Note: Be conscious that interrupts have to be used judiciously as they can disrupt the serial communication between your microcontroller and ROS. Always ensure that your ISRs are as short and efficient as possible to avoid timing issues.

Troubleshooting and Best Practices

When integrating rosserial with platforms like Arduino, mbed, or Teensy for your ROS projects, you’ll likely face a variety of common issues. Applying best practices from the start and knowing how to troubleshoot effectively can save you time and frustration.

Common Issues and Solutions

You may encounter problems like mismatched ROS message types or service definitions between the rosserial_client and the main ROS system. This typically arises from inconsistencies in the ROSSERIAL setup. To mitigate this:

  • Ensure Dependencies: Verify all necessary dependencies are installed and up to date. Use rosdep to check and install any missing packages.
  • ros.h Issue: If you hit errors related to ros.h, ensure the rosserial_arduino package is properly installed.
  • Serial Connection: Issues with the serial connection are common; always check your baud rate and use the setSerial method to match the rates on both the Arduino sketch and ROS configuration.
  • Syncronization: If synchronization issues arise, adjust the settimeout parameter on the serial connection.

ROS Serial Optimization Tips

To optimize the performance of rosserial_python or rosserial_arduino, follow these tips:

  • Use Optimal Rates: Avoid too high or too low publishing rates; find a balance that maintains ROS system performance without buffer overflows.
  • Minimize Message Size: Use tf efficiently by transmitting only necessary transformations and using appropriate data types.
  • Code Structure: Structure your C++ code to handle callbacks efficiently and prevent blocking operations that can hamper communication.
  • Building from Source: If using boards like STM32, build rosserial_client libraries from source for custom message support.

Remember, always start with the documentation available for rosserial and the specific hardware libraries you’re using, as they often contain the most up-to-date and relevant information for troubleshooting and optimization.


Related Posts

Don't Miss Out!

Get the latest news, tutorials, reviews and more direct to your inbox when you subscribe!