Skip to content

rmw_take_request fails: first 8 bytes of static_buffer->buffer are non-CDR on jazzy (serial transport) #327

@kristkis

Description

@kristkis

Summary

On rmw_microxrcedds jazzy, rmw_take_request consistently fails for custom services over a Zephyr-based serial transport. on_request in callbacks.c successfully matches and stores the request (confirmed by instrumentation), but functions->cdr_deserialize at rmw_request.c:124 returns false because the first uint32_t at static_buffer->buffer is not the expected CDR sequence-size — it's 8 bytes of unknown data, with the real CDR payload starting at offset 8.

Advancing the ucdrBuffer iterator 8 bytes before cdr_deserialize makes the service round-trip succeed.

Environment

  • micro-ROS branch: jazzy
  • Client: micro_ros_zephyr_module (jazzy)
  • Agent: micro-ROS-Agent (jazzy, v2.4.3)
  • Target: STM32G491 (Cortex-M4), Zephyr 4.1
  • Transport: custom serial (lpuart1 @ 115200)
  • Service type: rcl_interfaces/srv/SetParameters
  • Executor has 3 best-effort subscriptions + 2 default-QoS (reliable) services. Subscription dispatch works correctly; only service dispatch fails.

Steps to reproduce

  1. Create two services on a Zephyr micro-ROS client:

    rclc_service_init_default(&svc_set, &node,
        ROSIDL_GET_SRV_TYPE_SUPPORT(rcl_interfaces, srv, SetParameters),
        "~/set_parameters");
    rclc_service_init_default(&svc_get, &node,
        ROSIDL_GET_SRV_TYPE_SUPPORT(rcl_interfaces, srv, GetParameters),
        "~/get_parameters");
    rclc_executor_add_service(&exec, &svc_set, &req, &res, on_set_cb);
    rclc_executor_add_service(&exec, &svc_get, &req, &res, on_get_cb);

    Pre-allocate all nested strings and sequences of the request/response via __init + __Sequence__init + __assignn per pablogs9's comment in micro_ros_setup#578.

  2. From host:

    ros2 service call /axon_sensor_node/set_parameters rcl_interfaces/srv/SetParameters \
      '{parameters: [{name: "accel_fs", value: {type: 2, integer_value: 4}}]}'
  3. Client's on_set_cb is never invoked. CLI hangs.

Instrumentation

With JLink-readable counters added to rmw_microxrcedds_c:

Counter Value
on_request hits 1
on_request matched service by service_data_resquest 1
static_buffer->owner after store 0x2000CA28 (= set_params rmw_uxrce_service_t *)
rmw_take_requestcdr_deserialize returned false
temp_buffer.error after deserialize 0
Bytes consumed before failure 4
static_buffer->length 84
First 16 bytes of static_buffer->buffer (hex) 6D 4F 6F 29 0A 5E 6B 3B 01 00 00 00 00 00 00 00

The 01 00 00 00 at offset 8 is the expected parameters.size = 1 (matches the request: one Parameter named accel_fs). The 8 bytes at offset 0–7 are not valid CDR — the sequence-size guard in the generated typesupport rejects them and the request is dropped.

Workaround

Inserting ucdr_advance_buffer(&temp_buffer, 8); in rmw_request.c between ucdr_init_buffer and cdr_deserialize:

ucdrBuffer temp_buffer;
ucdr_init_buffer(&temp_buffer, static_buffer->buffer, static_buffer->length);
ucdr_advance_buffer(&temp_buffer, 8);       // <-- workaround
bool deserialize_rv = functions->cdr_deserialize(&temp_buffer, ros_request);

With this skip: callback fires, request deserializes correctly, firmware processes and sends the reply.

Questions

  1. What are those 8 bytes? SampleIdentity tail, custom CDR encapsulation, or unrelated padding?
  2. Is the right fix to strip them during the ucdr_deserialize_array_uint8_t copy in on_request (so static_buffer->buffer contains only CDR), or in rmw_take_request?
  3. Is this jazzy-specific, or does it also affect rolling/iron?
  4. Does stream reliability (best-effort vs reliable) change which bytes arrive? Our subscriptions use best-effort and dispatch correctly; services use default (reliable) and fail.

Happy to test any proposed fix on our hardware.

Related


Co-authored-by: Claude Opus 4.7 (1M context) noreply@anthropic.com

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions