-
Notifications
You must be signed in to change notification settings - Fork 0
fix: ROS1 string decoding and builtin type variant handling #60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…ling
This commit fixes several issues with ROS1 bag decoding and schema handling:
1. **ROS1 string decoding**: CDR decoder now correctly handles ROS1 strings
where length is the exact byte count (no null terminator), unlike ROS2
CDR strings where length includes null terminator.
2. **MCAP writer schema encoding**: Fixed add_channel_with_schema to use
correct schema encoding names ("ros2msg", "jsonschema", "protobuf")
instead of message encoding, and pass message encoding to add_channel.
3. **Builtin type variant conflict**: populate_builtin_types now skips
adding "/msg/" variant when the non-prefixed variant was already parsed
from message_definition (e.g., std_msgs/Header from ROS1 with seq field).
4. **Test coverage**: Added test_decode_dynamic_tf_topic to verify /tf
(tf2_msgs/TFMessage) decoding with nested Header and ROS1 strings.
Fixes decoding of /tf messages from ROS1 bags containing std_msgs/Header
with the seq field (ROS1 variant).
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Greptile OverviewGreptile SummaryThis PR fixes ROS1 decoding edge cases by teaching the CDR decoder to treat ROS1 strings as length-prefixed without a null terminator, adds a regression test for decoding It also adjusts the MCAP writer’s channel/schema metadata: schema names now use
|
| Filename | Overview |
|---|---|
| src/encoding/cdr/decoder.rs | Adds ROS1 string handling in read_string; but ROS2 branch still ignores errors when skipping null terminator (cursor.read_u8() result dropped), which can hide truncation. |
| src/io/formats/mcap/writer.rs | Changes MCAP schema/channel encoding wiring; however schema encoding is now guessed with a heuristic that can mislabel ROS1 vs ROS2 message schemas (e.g., slash-delimited types become ros2msg). |
| src/lib.rs | Exposes io::metadata::FileFormat under a #[cfg(test)] module for tests; no functional impact on non-test builds. |
| src/schema/parser/unified.rs | Adjusts builtin type population to avoid adding /msg/ variants when a parsed variant already exists (prevents ambiguous resolution); change appears safe and localized. |
| tests/ros1_decode_dynamic_tests.rs | Adds a targeted /tf decode_dynamic regression test using an existing ROS1 bag fixture; test logic is consistent with existing integration tests. |
Sequence Diagram
sequenceDiagram
participant W as ParallelMcapWriter
participant MCAP as MCAP file
participant F as CodecFactory
participant SM as SchemaMetadata
participant P as Schema parser
participant C as CdrCodec/CdrDecoder
W->>MCAP: "add_schema(name=message_type, encoding=schema_encoding, data=schema)"
W->>MCAP: "add_channel(topic, message_encoding=encoding, schema_id)"
F->>MCAP: "read ChannelInfo (encoding, schema_encoding, schema)"
F->>F: "detect_encoding(channel.encoding, channel.schema_encoding)"
F->>SM: "SchemaMetadata::cdr_with_encoding(type, schema, schema_encoding)"
SM->>P: "parse_schema_with_encoding(type, schema, schema_encoding)"
P-->>SM: "MessageSchema"
F->>C: "get_codec(Cdr)"
C->>C: "decode_dynamic(data, SchemaMetadata)"
alt schema_encoding indicates ROS1
C->>C: "read_string() reads len bytes"
else ROS2/CDR
C->>C: "read_string() reads len-1 bytes and skips terminator"
end
C-->>F: "DecodedMessage"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
5 files reviewed, 2 comments
Additional Comments (2)
Prompt To Fix With AIThis is a comment left during a code review.
Path: src/encoding/cdr/decoder.rs
Line: 618:626
Comment:
**Ignored terminator read**
In the ROS2/CDR branch, the null terminator is skipped with `let _ = cursor.read_u8();`, which drops any read error. For truncated/malformed inputs where `len` claims a terminator byte but the buffer ends right after the string bytes, this will incorrectly return `Ok` and hide the truncation. This should propagate the error (and ideally validate the terminator is `0`).
How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix With AIThis is a comment left during a code review.
Path: src/io/formats/mcap/writer.rs
Line: 1084:1101
Comment:
**Schema encoding misclassified**
`schema_encoding` is inferred via `encoding == "cdr" && (message_type.contains('/') || message_type.contains("msg"))`, which will label any slash-delimited ROS type (including ROS1 `pkg/Type`) as `"ros2msg"`. This will cause downstream `detect_encoding` / schema parsing to treat ROS1 schemas as ROS2 (and vice versa), breaking decoding for ROS1-written MCAPs. The schema encoding needs to be sourced from the actual schema/version context (e.g., `ros1msg` vs `ros2msg`) rather than this heuristic.
How can I resolve this? If you propose a fix, please make it concise. |
This commit fixes issues with ROS1 bag string decoding and schema handling:
Changes
ROS1 string decoding (
src/encoding/cdr/decoder.rs):is_ros1()check inread_string()methodBuiltin type variant conflict (
src/schema/parser/unified.rs):populate_builtin_typesnow skips adding "/msg/" variant when the non-prefixed variant was already parsed from message_definitionget_type_variantsstd_msgs/msg/Headerwhenstd_msgs/Headerwas parsed from ROS1 message_definition (which includes theseqfield)Test coverage (
tests/ros1_decode_dynamic_tests.rs):test_decode_dynamic_tf_topicto verify/tf(tf2_msgs/TFMessage) decodingrobocodec_test_24_leju_claw.bagImpact
Fixes decoding of
/tfmessages from ROS1 bags containingstd_msgs/Headerwith theseqfield (ROS1 variant).