pub trait Message:
Clone
+ Debug
+ Default
+ 'static
+ Send
+ Sync {
type RmwMsg: RmwMessage;
// Required methods
fn into_rmw_message(msg_cow: Cow<'_, Self>) -> Cow<'_, Self::RmwMsg>;
fn from_rmw_message(msg: Self::RmwMsg) -> Self;
}
Expand description
Trait for types that can be used in a rclrs::Subscription
and a rclrs::Publisher
.
rosidl_generator_rs
generates two types of messages that implement this trait:
- An “idiomatic” message type, in the
${package_name}::msg
module - An “RMW-native” message type, in the
${package_name}::msg::rmw
module
§Idiomatic message type
The idiomatic message type aims to be familiar to Rust developers and ROS 2 developers coming
from rclcpp
.
To this end, it translates the original ROS 2 message into a version that uses idiomatic Rust
structs: std::vec::Vec
for sequences and std::string::String
for strings. All other
fields are the same as in an RMW-native message.
This conversion incurs some overhead when reading and publishing messages.
It’s possible to use the idiomatic type for a publisher and the RMW-native type for a corresponding subscription, and vice versa.
§RMW-native message type
The RMW-native message type aims to achieve higher performance by avoiding the conversion step to an idiomatic message.
It uses the following type mapping:
Message field type | Rust type |
---|---|
string | String |
wstring | WString |
string<=N , for example string<=10 | BoundedString |
wstring<=N , for example wstring<=10 | BoundedWString |
T[] , for example int32[] | Sequence |
T[<=N] , for example int32[<=32] | BoundedSequence |
T[N] , for example float32[8] | standard Rust arrays |
primitive type, for example float64 | corresponding Rust primitive type |
The linked Rust types provided by this package are equivalents of types defined in C that are used by the RMW layer.
The API for these types, and the message as a whole, is still memory-safe and as convenient as
possible.
For instance, the Sequence
struct that is used for sequences supports
iteration and all of the functionality of slices. However, it doesn’t have an equivalent of
Vec::push()
, among others.
§What does “RMW-native” mean in detail?
The message can be directly passed to and from the RMW layer because (1) its layout is
identical to the layout of the type generated by rosidl_generator_c
and (2) the dynamic
memory inside the message is owned by the C allocator.
The above type mapping, together with a #[repr(C)]
annotation on the message, guarantees
these two properties.
This means the user of a message does not need to care about memory ownership, because that is managed by the relevant functions and trait impls.
§I need even more detail, please
rosidl_runtime_c
and the code generated by rosidl_generator_c
manages
memory by means of four functions for each message: init()
, fini()
, create()
, and
destroy()
.
init()
does the following:
- for a message, it calls
init()
on all its members that are of non-primitive type, and applies default values - for a primitive sequence, it allocates the space requested
- for a string, it constructs a string containing a single null terminator byte
- for a non-primitive sequence, it zero-allocates the space requested and calls
init()
on all its elements
fini()
does the following (which means after a call to fini()
, everything inside the message has been deallocated):
- for a message, it calls
fini()
on all its members that are of non-primitive type - for a primitive sequence, it deallocates
- for a string, it deallocates
- for a non-primitive sequence, it calls
fini()
on all its elements, and then deallocates
create()
simply allocates space for the message itself, and calls init()
.
destroy()
simply deallocates the message itself, and calls fini()
.
Memory ownership by C is achieved by calling init()
when any string or sequence is created,
as well as in the Default
impl for messages.
User code can still create messages explicitly, which will not call init()
, but this is not a
problem, since nothing is allocated this way.
The Drop
impl for any sequence or string will call fini()
.
Required Associated Types§
Sourcetype RmwMsg: RmwMessage
type RmwMsg: RmwMessage
The corresponding RMW-native message type.
Required Methods§
Sourcefn into_rmw_message(msg_cow: Cow<'_, Self>) -> Cow<'_, Self::RmwMsg>
fn into_rmw_message(msg_cow: Cow<'_, Self>) -> Cow<'_, Self::RmwMsg>
Converts the idiomatic message into an RMW-native message.
If the idiomatic message is owned, a slightly more efficient conversion is possible.
This is why the function takes a Cow
.
If this function receives a borrowed message that is already RMW-native, it should
directly return that borrowed message.
This is why the return type is also Cow
.
Sourcefn from_rmw_message(msg: Self::RmwMsg) -> Self
fn from_rmw_message(msg: Self::RmwMsg) -> Self
Converts the RMW-native message into an idiomatic message.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.