rosserial is a protocol for wrapping standard ROS serialized messages and multiplexing multiple topics and services over a character device such as a serial port or network socket.

In addition to a protocol definition, there are three types of packages found in this suite:

Client Libraries

Client libraries allow users to easily get ROS nodes up and running on various systems. These clients are ports of the general ANSI C++ rosserial_client library. Currently, these packages include:


support for Arduino compatible boards including UNO, Leonardo, MEGA, DUE, Teensy 3.x and LC, Spark, STM32F1, STM32Duino, ESP8266 and ESP32


support for Embedded Linux (eg, routers)


support for communicating with Windows applications


support for mbed platforms


support for TI's Launchpad boards, TM4C123GXL and TM4C1294XL


support for VEX V5 Robot Brain


support for VEX Cortex board


support for STM32 MCUs, based on STM32CubeMX HAL


support for teensy platforms

Refer to Adding Support for New Hardware for details on how to add a new hardware platform.

ROS-side Interfaces

Devices running rosserial code require a node on the host machine to bridge the connection from the serial protocol to the more general ROS network:


A Python-based implementation (recommended for PC usage).


A C++ implementation based on the ShapeShifter message, some limitations compared to rosserial_python but recommended for high-performance applications.

Examples and Use Cases

We have created a number of extensions and examples:

  • rosserial_arduino Tutorials - contains a number of examples of using various sensors and actuators with Arduino. This is the most well documented tutorial, and many of the feature depicted there can be extended into other platforms.

  • rosserial_xbee - tools for creating sensor networks using XBEE devices and Arduino.

  • rosserial_embeddedlinux Tutorials contains a number of examples of various sensors and actuators with an embedded linux system which cannot run full-blown ROS.

  • rosserial_mbed Tutorials - contains a number of examples of using various sensors and actuators with and Mbed platform.

  • rosserial_tivac Tutorials - Various examples for programming TI's TivaC Launchpad with Energia IDE or catkinized projects.


Maximum Size of a Message, Maximum Number of Publishers/Subscribers

The number of Publishers and Subscribers are limited at 25, and the size of serialization and deserialization buffers are limited at 512 bytes by default for rosserial_client.

However, those numbers and sizes are too big for microcontroller with limited SRAM. The buffer sizes, and numbers of Publisher/Subscriber for rosserial_arduino now vary depending on the chip used:

AVR Model

Input/Output buffer sizes



150/150 bytes



280/280 bytes


All others

512/512 bytes


You can change these numbers and sizes, refer to tutorial NodeHandle and ArduinoHardware for more informaiton.


You should, however, be careful not to consume too much of the limited SRAM found in the Arduino. If the Arduino ran out of SRAM, it will simply hang with no debug information.

Messages larger than the buffer size is not transmitted. A ROS error message will be relayed telling whether the message was coming from, or going to, the device.


The Arduino does not support 64-bit float datatypes. The serialization/deserialization code generated by make_library will automatically convert 64-bit floats into 32-bit datatypes, however, it should be noted that a loss of precision may occur!


To conserve precious AVR memory, strings are not stored inside a message instance, instead an unsigned char * is stored. This has two impacts:

When publishing, you must assign store the string data elsewhere and set the pointer:

   1 std_msgs::String str_msg;
   2 unsigned char hello[13] = "hello world!";
   4 str_msg.data = hello;

When subscribing to a message containing a string datatype, the string itself will not be copied from the deserialization buffer. Therefore, while it will be valid during the callback function, it will disappear when any other message is deserialized. If you need to keep the value of the string outside the callback, you must manually copy the string elsewhere.


Arrays have similar limitations to strings, however, since there is no easy way to find the termination of an array (analogous to the \0 found at the end of a string), we need to specify the size of the array. An extra variable is added to the class definition to accomplish this. For instance, the geometry_msgs/PoseArray is declared as:

Header header
geometry_msgs/Pose[] poses

On the Arduino, this will translate to a class:

   1 class PoseArray
   2 {
   3   Header header;
   4   int poses_length;
   5   Pose * poses;
   6 }

Therefore, to send an array message, we have to set the length and pointer. When deserializing, we cannot deserialize in-place like the string (since the bytes of the message are actually packed, unlike a string which is passed in plain form). Therefore, the deserialization function will automatically allocate enough storage using realloc(), attempting to reuse the memory location whenever possible and only expanding it when the new message received is larger than the largest previous message.

Some array types containing other array types will not deserialize correctly, as all elements of the child type will point to the same memory. This limitation may be addressed in the future.


The rosserial protocol is aimed at point-to-point ROS communications over a serial transmission line. We use the same serialization/de-serialization as standard ROS messages, simply adding a packet header and tail which allows multiple topics to share a common serial link. This page describes the low-level details of the packet header and tail, and several special topics used for synchronization.

Packet Format

  1st Byte - Sync Flag (Value: 0xff)
  2nd Byte - Sync Flag / Protocol version
  3rd Byte - Message Length (N) - Low Byte
  4th Byte - Message Length (N) - High Byte
  5th Byte - Checksum over message length
  6th Byte - Topic ID - Low Byte
  7th Byte - Topic ID - High Byte
  x Bytes  - Serialized Message Data
  Byte x+1 - Checksum over Topic ID and Message Data

The Protocol version byte was 0xff on ROS Groovy, 0xfe on ROS Hydro, Indigo, and Jade.

Topics ID 0-100 are reserved for system functions, as defined in the rosserial_msgs/TopicInfo message.

The checksums on the length and data are used to make sure that a particular packet has not been corrupted.

The checksum over the message length is computed as follows:

Message Length Checksum = 255 - ((Message Length High Byte + 
                                   Message Length Low Byte) % 256 )

The checksum over the Topic ID and data is computed as follows:

Message Data Checksum = 255 - ((Topic ID Low Byte +
                                Topic ID High Byte + 
                                Data byte values) % 256)

Topic Negotiation

Before data transfer can begin, the PC/Tablet side must query the Arduino or other embedded device for the names and types of topics which will be published or subscribed to.

Topic negotiation consists of a query for topics, a response with the number of topics, and packets to define each topic. The request for topics uses a topic ID of 0.

The query for topics will look like:

  0xff 0xfe 0x00 0x00 0xff 0x00 0x00 0xff

A series of response packets (message type rosserial_msgs/TopicInfo, each containing information about a particular topic, with the following data in place of the serialized message:

  uint16 topic_id
  string topic_name
  string message_type
  string md5sum
  int32 buffer_size

Here, the topic name is the name of the topic, for instance "cmd_vel", and message type is the type of the message, for instance "geometry_msgs/Twist".

If a response packet is not received correctly, another query may be sent.

MD5 checksums are transmitted to verify that both the sender and receiver are using the same message.


Time synchronization is handled by sending a std_msgs::Time in each direction. The embedded device can request the current time from the PC/Tablet by sending an empty Time message. The returned time is used to find clock offset.

Report a Bug

Report bugs, ask questions in the issues list on github/rosserial

Wiki: rosserial (last edited 2018-10-01 21:17:03 by RomainReignier)