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:
-
A C++ state stores a
geometry_msgs::msg::Pose on the blackboard.
-
RosSerializeCppState converts it to
std::vector<uint8_t> and writes it to
output.
-
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.