ROS Serialization States

The ROS Serialization States are part of the yasmin_ros package and enable converting ROS 2 interface instances (messages, service requests/responses, action goals/results/feedback) to and from raw byte arrays. They are especially useful when Python and C++ states need to share complex ROS objects through the YASMIN blackboard, since only primitive types and bytes / std::vector<uint8_t> are safely exchanged across the language boundary.

Overview

There are four serialization states, split by language and direction:

State Language Direction Plugin name
RosSerializeCppState C++ ROS interface → bytes yasmin_ros/RosSerializeCppState
RosDeserializeCppState C++ bytes → ROS interface yasmin_ros/RosDeserializeCppState
RosSerializePyState Python ROS interface → bytes —
RosDeserializePyState Python bytes → ROS interface —

The C++ states are registered as pluginlib plugins so they can be loaded from XML state machine files via the YASMIN Factory. The Python states are imported from yasmin_ros.

Supported Interface Types (C++)

The C++ states operate through a compile-time handler map defined in yasmin_ros/supported_interface_serialization.hpp. The following interface types are built in:

Interface type string C++ type
geometry_msgs/msg/Pose geometry_msgs::msg::Pose
std_msgs/msg/String std_msgs::msg::String
std_srvs/srv/Trigger_Request std_srvs::srv::Trigger::Request
std_srvs/srv/Trigger_Response std_srvs::srv::Trigger::Response
example_interfaces/action/Fibonacci_Goal example_interfaces::action::Fibonacci::Goal
example_interfaces/action/Fibonacci_Result example_interfaces::action::Fibonacci::Result
example_interfaces/action/Fibonacci_Feedback example_interfaces::action::Fibonacci::Feedback

The Python states resolve the interface class dynamically at runtime using rclpy so any installed ROS 2 interface type is supported.

RosSerializeCppState

Reads a C++ ROS interface instance from the blackboard key input, serializes it to a std::vector<uint8_t>, and writes the result to the blackboard key output.

Outcomes

Outcome Description
succeed Serialization finished successfully.
type_error The value stored in input does not match the configured interface type.
error Serialization failed because the input could not be processed.

Blackboard Keys

Direction Key Type Description
Input input configured interface type ROS interface instance to serialize.
Output output std::vector<uint8_t> Serialized byte array.

Parameters

Parameter Type Default Description
interface_type string geometry_msgs/msg/Pose ROS interface type string, e.g. geometry_msgs/msg/Pose or std_srvs/srv/Trigger_Request. Must be one of the supported types listed above.

RosDeserializeCppState

Reads a std::vector<uint8_t> byte array from the blackboard key input, deserializes it into the configured C++ ROS interface type, and writes the result to the blackboard key output.

Outcomes

Outcome Description
succeed Deserialization finished successfully.
type_error The value stored in input does not match the expected byte-array type or the target type does not match.
error Deserialization failed because the data could not be decoded.

Blackboard Keys

Direction Key Type Description
Input input std::vector<uint8_t> Serialized byte array to deserialize.
Output output configured interface type Deserialized ROS interface instance.

Parameters

Parameter Type Default Description
interface_type string geometry_msgs/msg/Pose ROS interface type string. Must be one of the supported types listed above.

RosSerializePyState

Python counterpart of RosSerializeCppState. Reads a Python ROS interface instance from the blackboard key input, serializes it using rclpy.serialization.serialize_message, and writes the resulting bytes object to the blackboard key output.

Outcomes

Outcome Description
succeed Serialization finished successfully.
type_error The value stored in input does not match the configured interface type.
error Serialization failed because the input could not be processed.

Blackboard Keys

Direction Key Type Description
Input input configured interface type ROS interface instance to serialize.
Output output bytes Serialized byte array.

Parameters

Parameter Type Default Description
interface_type string geometry_msgs/msg/Pose ROS interface type string such as geometry_msgs/msg/Pose or std_srvs/srv/Trigger_Request. Any installed ROS 2 interface is accepted.

RosDeserializePyState

Python counterpart of RosDeserializeCppState. Reads a bytes (or bytearray) value from the blackboard key input, deserializes it using rclpy.serialization.deserialize_message, and writes the resulting Python ROS interface instance to the blackboard key output.

Outcomes

Outcome Description
succeed Deserialization finished successfully.
type_error The value stored in input is not a byte array or the target type does not match.
error Deserialization failed because the serialized data could not be decoded.

Blackboard Keys

Direction Key Type Description
Input input bytes / bytearray Serialized byte array to deserialize.
Output output configured interface type Deserialized Python ROS interface instance.

Parameters

Parameter Type Default Description
interface_type string geometry_msgs/msg/Pose ROS interface type string such as geometry_msgs/msg/Pose or example_interfaces/action/Fibonacci_Result. Any installed ROS 2 interface is accepted.

Usage Examples

Python — Serialize and Deserialize a Pose

The following snippet shows how to wire the Python serialization states in a state machine so that a geometry_msgs/msg/Pose instance written by one state is serialized to bytes, passed across the blackboard, and then deserialized back.


import rclpy
from geometry_msgs.msg import Pose

from yasmin import Blackboard, State, StateMachine
from yasmin_ros import RosSerializePyState, RosDeserializePyState, set_ros_loggers
from yasmin_ros.basic_outcomes import SUCCEED, ABORT


class WritePoseState(State):
    """Puts a Pose into the blackboard under key 'input'."""

    def __init__(self):
        super().__init__([SUCCEED])

    def execute(self, blackboard: Blackboard) -> str:
        pose = Pose()
        pose.position.x = 1.0
        pose.position.y = 2.0
        pose.position.z = 3.0
        blackboard["input"] = pose
        return SUCCEED


class ReadPoseState(State):
    """Reads the deserialized Pose from blackboard key 'output'."""

    def __init__(self):
        super().__init__([SUCCEED])

    def execute(self, blackboard: Blackboard) -> str:
        pose: Pose = blackboard["output"]
        print(f"position: x={pose.position.x} y={pose.position.y} z={pose.position.z}")
        return SUCCEED


def main():
    rclpy.init()
    set_ros_loggers()

    serialize_state = RosSerializePyState()
    serialize_state.set_parameter("interface_type", "geometry_msgs/msg/Pose")
    serialize_state.configure()

    deserialize_state = RosDeserializePyState()
    deserialize_state.set_parameter("interface_type", "geometry_msgs/msg/Pose")
    deserialize_state.configure()

    sm = StateMachine(outcomes=["done"])
    sm.add_state("WRITE_POSE", WritePoseState(), {"succeed": "SERIALIZE"})
    sm.add_state("SERIALIZE", serialize_state, {"succeed": "DESERIALIZE",
                                                "type_error": "done",
                                                "error": "done"})
    sm.add_state("DESERIALIZE", deserialize_state, {"succeed": "READ_POSE",
                                                    "type_error": "done",
                                                    "error": "done"})
    sm.add_state("READ_POSE", ReadPoseState(), {"succeed": "done"})

    sm()
    rclpy.shutdown()


if __name__ == "__main__":
    main()

C++ — Serialize via XML (Factory)

The C++ serialization states are registered as plugins so they can be used directly from an XML state machine file loaded by the YASMIN Factory. See the yasmin_demos package for a complete working example (ros_serialization_demo).


<StateMachine outcomes="done">
  <State name="Serialize"
         type="cpp"
         class="yasmin_ros/RosSerializeCppState">
    <Param name="interface_type" value="geometry_msgs/msg/Pose"/>
    <Transition from="succeed" to="Deserialize"/>
    <Transition from="type_error" to="done"/>
    <Transition from="error" to="done"/>
  </State>
  <State name="Deserialize"
         type="cpp"
         class="yasmin_ros/RosDeserializeCppState">
    <Param name="interface_type" value="geometry_msgs/msg/Pose"/>
    <Transition from="succeed" to="done"/>
    <Transition from="type_error" to="done"/>
    <Transition from="error" to="done"/>
  </State>
</StateMachine>

Cross-Language Pattern

When a C++ state writes a serialized byte array and a Python state needs to consume the original message (or vice versa), combine the C++ and Python serialize/deserialize states in the same state machine:

  1. A C++ state stores a geometry_msgs::msg::Pose on the blackboard.
  2. RosSerializeCppState converts it to std::vector<uint8_t> and writes it to output.
  3. A Python state reads output as bytes and uses RosDeserializePyState to recover the geometry_msgs.msg.Pose Python object.

See Cross-Language ROS Interface Communication for background and the primitive types that are safely exchanged without serialization.