ROS Messages#
ltcodecs can encode and decode ROS messages. The ROS message
path uses the same field configuration format described in
Codec Configurations, but it can also infer fields from ROS message
definitions.
ROS functionality is implemented using ARMW, so it works with ROS 1 and ROS 2.
Top-Level and Field Codecs#
Use ltcodecs.ros_message_codec.RosMessageCodec at application
boundaries. It owns the top-level message codec, optional checksum handling,
and metadata returned from encode().
Use ltcodecs.ros_msg_field_codec.RosMsgFieldCodec only when a
field inside another codec is itself a ROS message. In YAML, this is the
msg or ros_msg codec alias.
pose:
codec: msg
ros_type: geometry_msgs/Pose
Automatic Field Inference#
If RosMessageCodec is created without a field dictionary, ltcodecs uses
ARMW to introspect for the ROS message fields and types:
codec = ltcodecs.RosMessageCodec("std_msgs/String")
For simple messages this is convenient. For production acoustic links, prefer an explicit YAML config so field bounds and lossy encodings are deliberate. Explicit configs are also the way to change array limits, string lengths, float resolution, optional fields, and nested message fields.
Explicit Field Configs#
Pass a field dictionary directly or load one from YAML:
codec = ltcodecs.RosMessageCodec.from_codec_file(
"std_msgs/String",
"string_msg_codec.yaml",
)
data:
codec: string
max_length: 10
When encoding, every configured payload field must exist on the ROS message.
When decoding, ltcodecs constructs a new ROS message object from the
decoded field values.
ROS 1 and ROS 2 Type Syntax#
ROS 1 and ROS 2 expose message type names differently. ltcodecs
normalizes the common forms before constructing nested message codecs.
Type string |
Meaning |
|---|---|
|
Message type, ROS 1 style |
|
Message type, ROS 2 introspection style |
|
Variable-length array, ROS 1 style |
|
Fixed-length array, ROS 1 style |
|
Variable-length array, ROS 2 style |
|
Bounded variable-length primitive array |
|
Fixed-length array, ROS 2 style |
The ROS 2 form pkg/msg/Msg is normalized to pkg/Msg before calling
ARMW’s message import helpers.
Arrays#
When arrays are inferred from ROS field definitions, ltcodecs maps them to
the array codecs used by explicit configs:
fixed-size arrays become
fixed_len_arrayvariable-size arrays become
variable_len_arrayprimitive element types use their scalar codec alias
message element types use
element_type: msgandelement_params
For example, a ROS 2 field type like:
sequence<geometry_msgs/msg/Point>
is treated like this explicit configuration:
points:
codec: variable_len_array
max_length: 10
element_type: msg
element_params:
ros_type: geometry_msgs/Point
The default maximum length for inferred variable-length arrays is currently
10. Use an explicit config when that limit should be different.
Nested Message Fields#
Nested ROS message fields can either be inferred or configured explicitly. An explicit config is useful when only a subset of the nested fields should be encoded or when individual nested fields need custom codecs.
point:
codec: msg
ros_type: geometry_msgs/Point
fields:
x:
codec: float32
y:
codec: float32
z:
codec: float32
Without a fields mapping, RosMsgFieldCodec infers the nested message’s
fields from the ROS message definition.
Metadata#
ROS message encoding returns (bits, metadata). The metadata value is
usually None. When a configured field uses a metadata encoder alias, the
field is copied into the returned metadata dictionary instead of being encoded
into the bit stream.
During decoding, received_packet can provide packet metadata for configured
metadata decoder fields:
decoded = codec.decode(bits_to_decode, received_packet=packet)
The available metadata aliases are shared with dictionary codecs and are listed in Codec Aliases.
Checksums#
RosMessageCodec supports the same top-level checksums as
DictCodec:
codec = ltcodecs.RosMessageCodec(
"std_msgs/String",
fields_dict={
"data": {
"codec": "string",
"max_length": 10,
},
},
checksum="crc32",
)
The checksum is appended after the encoded message payload. Decoding raises
ValueError if the received checksum does not match the decoded payload.
Testing Without ROS Middleware#
ARMW’s native backend can load ROS-style .msg definitions without running
ROS 1 or ROS 2 middleware. This is useful for fast unit tests that need
standard message classes but do not need a ROS graph.
Set the middleware and interface search path before importing ARMW:
ARMW_MIDDLEWARE=native
ROS_PACKAGE_PATH=/path/to/common_interfaces
Then tests can import messages with ARMW:
import armw
String = armw.import_message("std_msgs", "String")
Use full ROS 1 and ROS 2 CI jobs for behavior that depends on actual middleware, generated package layouts, or ROS-specific introspection behavior.