How to implement deserialization of ros2 messages

312 views Asked by At

After I serialized the ros2 message and extracted the buffer data, When I deserialize as follows,It has the following problem:terminate called after throwing an instance of 'rcpputils::IllegalStateException' what(): Wrongly initialized. Serialized message has a size of zero. [ros2run]: Aborted

void callbackCloudResponseMessage(const planning_interface::msg::Cloud & msg) {

    /* serialize */
    rclcpp::Serialization<planning_interface::msg::Cloud> cloudSerializer;
    rclcpp::SerializedMessage serialized_msg;
    cloudSerializer.serialize_message(&msg, &serialized_msg);

    uint8_t* serialized_data = serialized_msg.get_rcl_serialized_message().buffer;
    size_t serialized_size = serialized_msg.size();
    
    static uint8_t buf_test[FRAME_LENGTH_MAX+1];
    uint8_t *pmsg_test = buf_test + DATA_PAYLOAD;
    memcpy(pmsg_test, serialized_data, serialized_size);

    /* deserialize */
    planning_interface::msg::Cloud test_msg;
    rclcpp::SerializedMessage serialize_test_msg(serialized_size);
    memcpy(new_msg.get_rcl_serialized_message().buffer, pmsg_test, serialized_size);
    cloudSerializer.deserialize_message(&new_msg, &test_msg);

}

I tried the above method and expected to be able to deserialize

1

There are 1 answers

0
YurkoFlisk On

(I assume that serialize_test_msg is just an unfinished rename of new_msg or vice versa which you did after run, otherwise your example wouldn't compile in the first place)

The problem is that new_msg is zero size when you call deserialize_message because rclcpp::SerializedMessage constructor you use takes size_t as capacity, not size, of the created buffer. It allocates memory (to which you then successfully memcpy) and sets buffer, buffer_capacity and allocator fields of the underlying struct, but buffer_length field remains zero and the buffer is initially empty. memcpy only writes data to the buffer (within capacity, so no problems here), but buffer_length remains untouched and so new_msg.get_rcl_serialized_message() is in logically invalid state which can't be properly interpreted by deserialize_message. So, before doing deserializing, you should fix this by manually setting buffer_length (this doesn't require reallocation since it's, trivially, within capacity to which it is equal):

// ...
memcpy(new_msg.get_rcl_serialized_message().buffer, pmsg_test, serialized_size);
new_msg.get_rcl_serialized_message().buffer_length = serialized_size;
cloudSerializer.deserialize_message(&new_msg, &test_msg);