Skip to content

[feat] Add make_mcap_metadata.py and document it in bag2edex README - #74

Open
slepichev wants to merge 1 commit into
mainfrom
slepichev/make_mcap_metadata
Open

[feat] Add make_mcap_metadata.py and document it in bag2edex README#74
slepichev wants to merge 1 commit into
mainfrom
slepichev/make_mcap_metadata

Conversation

@slepichev

@slepichev slepichev commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Standalone .mcap files copied or downloaded without their companion metadata.yaml cannot be opened by rosbag2, so the bag2edex extraction tools reject them. Add a script that reconstructs metadata.yaml from ros2 bag info output — duration, start time, message counts, and per-topic metadata — writing it next to the .mcap file.

Document when and how to run it in the bag2edex README, including the ros2-on-PATH prerequisite and an end-to-end example feeding the recovered bag into rosbag_extract_edex.

Summary by CodeRabbit

  • New Features

    • Added a command-line tool to generate missing ROS 2 metadata.yaml files for MCAP recordings.
    • Generated metadata includes recording duration, start time, message counts, and topic details.
    • Supports an optional metadata version argument, defaulting to version 9.
  • Documentation

    • Added setup, usage, prerequisites, and workflow examples for regenerating metadata and extracting MCAP data.

Standalone .mcap files copied or downloaded without their companion
metadata.yaml cannot be opened by rosbag2, so the bag2edex extraction
tools reject them. Add a script that reconstructs metadata.yaml from
`ros2 bag info` output — duration, start time, message counts, and
per-topic metadata — writing it next to the .mcap file.

Document when and how to run it in the bag2edex README, including the
ros2-on-PATH prerequisite and an end-to-end example feeding the
recovered bag into rosbag_extract_edex.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a standalone CLI that derives ROS 2 metadata.yaml from MCAP bag information and documents its prerequisites, options, and usage with rosbag_extract_edex.

Changes

MCAP metadata generation

Layer / File(s) Summary
Metadata generation CLI
tools/python_tools/cuvslam_tools/bag2edex/make_mcap_metadata.py
Parses ros2 bag info output, converts timing values to nanoseconds, constructs bag and topic metadata, validates required fields, and writes metadata.yaml beside the MCAP file.
Metadata regeneration documentation
tools/python_tools/cuvslam_tools/bag2edex/README.md
Documents prerequisites, command usage, the optional metadata version, and an example extraction workflow.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: hrabeti-nvidia, vikuznetsov-nvidia

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main changes: adding make_mcap_metadata.py and documenting it in the bag2edex README.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch slepichev/make_mcap_metadata

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tools/python_tools/cuvslam_tools/bag2edex/make_mcap_metadata.py`:
- Around line 40-104: Add regression tests for the CLI metadata-generation flow,
mocking representative ros2 bag info output. Cover timestamp conversion,
filenames requiring safe handling, version values of at least 7, bags with no
topics, and behavior when metadata.yaml already exists; anchor the tests to the
relevant CLI entry point and metadata-writing logic without changing unrelated
behavior.
- Line 104: Update the metadata-writing flow around metadata_path.write_text to
refuse overwriting an existing metadata.yaml by default, allowing replacement
only when an explicit --force option is provided. Write the generated YAML to a
temporary file in the destination directory, then atomically replace
metadata_path after the write succeeds so interruptions cannot leave a partial
metadata file.
- Around line 69-97: Update the YAML generation block around the yaml list and
topics loop to serialize every interpolated scalar safely, including rel_file,
args.version, duration_ns, start_ns, total_messages, and topic fields. Use a
YAML emitter or JSON-style quoting/escaping for dynamic values while preserving
numeric types where required by the metadata schema, and ensure filenames and
parsed ros2 bag info values cannot alter YAML structure or parsed content.
- Around line 73-96: Update metadata generation around the YAML-building flow in
make_mcap_metadata.py to use a Humble-compatible default schema, or
conditionally emit the v9 fields including type_description_hash and updated QoS
serialization when version 9 is selected; preserve the existing topic metadata
values. In tools/python_tools/cuvslam_tools/bag2edex/README.md lines 99-100,
document the supported Humble/Jazzy version split and stop presenting version 9
as universal.

In `@tools/python_tools/cuvslam_tools/bag2edex/README.md`:
- Around line 92-103: Update the Markdown in the Usage and Example sections of
README.md by adding a blank line before each opening fenced code block, ensuring
both fences satisfy markdownlint MD031 without changing their content.
- Around line 86-90: Update the “Generating Missing metadata.yaml for MCAP
Files” prerequisites section to state that the ROS 2 environment must be sourced
and the MCAP storage plugin must be installed and available for `ros2 bag info
--storage mcap`, in addition to `ros2` being on PATH.
- Around line 99-100: Update the --version option documentation in the bag2edex
README to state that the default is ROS-distribution-specific: Humble uses
metadata version 5 and Jazzy uses version 9. Document these supported
distro/version pairs instead of presenting 9 as the universal default.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 6a3a9d42-9510-4c5a-a69b-b2b8d6e8fd27

📥 Commits

Reviewing files that changed from the base of the PR and between 57f42cc and 5ce4918.

📒 Files selected for processing (2)
  • tools/python_tools/cuvslam_tools/bag2edex/README.md
  • tools/python_tools/cuvslam_tools/bag2edex/make_mcap_metadata.py

Comment on lines +40 to +104
result = subprocess.run(
["ros2", "bag", "info", "--storage", "mcap", str(mcap_path)],
check=True,
text=True,
capture_output=True,
)

text = result.stdout

duration = re.search(r"Duration:\s+([0-9.]+)s", text)
start = re.search(r"Start:.*\((\d+)\.(\d+)\)", text)
messages = re.search(r"Messages:\s+(\d+)", text)

if not duration or not start or not messages:
raise RuntimeError("Could not parse ros2 bag info output")

duration_ns = ns_from_seconds(duration.group(1))
start_ns = ns_from_epoch(start.group(1), start.group(2))
total_messages = int(messages.group(1))

topic_re = re.compile(
r"Topic:\s+(.+?)\s+\|\s+Type:\s+(.+?)\s+\|\s+Count:\s+(\d+)\s+\|\s+Serialization Format:\s+(\S+)"
)

topics = topic_re.findall(text)

if not topics:
raise RuntimeError("No topics found in ros2 bag info output")

rel_file = mcap_path.name

yaml = []
yaml.append("rosbag2_bagfile_information:")
yaml.append(f" version: {args.version}")
yaml.append(" storage_identifier: mcap")
yaml.append(" duration:")
yaml.append(f" nanoseconds: {duration_ns}")
yaml.append(" starting_time:")
yaml.append(f" nanoseconds_since_epoch: {start_ns}")
yaml.append(f" message_count: {total_messages}")
yaml.append(" relative_file_paths:")
yaml.append(f" - {rel_file}")
yaml.append(" files:")
yaml.append(f" - path: {rel_file}")
yaml.append(" starting_time:")
yaml.append(f" nanoseconds_since_epoch: {start_ns}")
yaml.append(" duration:")
yaml.append(f" nanoseconds: {duration_ns}")
yaml.append(f" message_count: {total_messages}")
yaml.append(" topics_with_message_count:")

for name, msg_type, count, serialization in topics:
yaml.append(" - topic_metadata:")
yaml.append(f" name: {name}")
yaml.append(f" type: {msg_type}")
yaml.append(f" serialization_format: {serialization}")
yaml.append(' offered_qos_profiles: ""')
yaml.append(f" message_count: {count}")

yaml.append(' compression_format: ""')
yaml.append(' compression_mode: ""')
yaml.append(" custom_data: {}")
yaml.append("")

metadata_path.write_text("\n".join(yaml))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add regression coverage for the CLI contract.

Mock representative ros2 bag info output and cover timestamp conversion, special filenames, version ≥7 metadata, empty-topic bags, and existing metadata.yaml behavior.

🧰 Tools
🪛 ast-grep (0.44.1)

[warning] 63-63: XPath query is request-/variable-derived; use parameterized XPath to prevent injection.
Context: topic_re.findall(text)
Note: [CWE-643] Improper Neutralization of Data within XPath Expressions ('XPath Injection').

(xpath-injection-python)

🪛 Ruff (0.15.21)

[error] 40-40: subprocess call: check for execution of untrusted input

(S603)


[error] 41-41: Starting a process with a partial executable path

(S607)


[warning] 54-54: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 67-67: Avoid specifying long messages outside the exception class

(TRY003)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/python_tools/cuvslam_tools/bag2edex/make_mcap_metadata.py` around lines
40 - 104, Add regression tests for the CLI metadata-generation flow, mocking
representative ros2 bag info output. Cover timestamp conversion, filenames
requiring safe handling, version values of at least 7, bags with no topics, and
behavior when metadata.yaml already exists; anchor the tests to the relevant CLI
entry point and metadata-writing logic without changing unrelated behavior.

Comment on lines +69 to +97
rel_file = mcap_path.name

yaml = []
yaml.append("rosbag2_bagfile_information:")
yaml.append(f" version: {args.version}")
yaml.append(" storage_identifier: mcap")
yaml.append(" duration:")
yaml.append(f" nanoseconds: {duration_ns}")
yaml.append(" starting_time:")
yaml.append(f" nanoseconds_since_epoch: {start_ns}")
yaml.append(f" message_count: {total_messages}")
yaml.append(" relative_file_paths:")
yaml.append(f" - {rel_file}")
yaml.append(" files:")
yaml.append(f" - path: {rel_file}")
yaml.append(" starting_time:")
yaml.append(f" nanoseconds_since_epoch: {start_ns}")
yaml.append(" duration:")
yaml.append(f" nanoseconds: {duration_ns}")
yaml.append(f" message_count: {total_messages}")
yaml.append(" topics_with_message_count:")

for name, msg_type, count, serialization in topics:
yaml.append(" - topic_metadata:")
yaml.append(f" name: {name}")
yaml.append(f" type: {msg_type}")
yaml.append(f" serialization_format: {serialization}")
yaml.append(' offered_qos_profiles: ""')
yaml.append(f" message_count: {count}")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Escape all dynamic YAML scalars.

The MCAP filename and parsed ros2 bag info values are interpolated directly into YAML. Filenames or metadata containing YAML syntax can make the generated file invalid or change the parsed value. Quote/escape every dynamic scalar, preferably with a YAML emitter or JSON-style quoted strings.

Proposed fix
+import json
...
-    yaml.append(f"    - {rel_file}")
+    yaml.append(f"    - {json.dumps(rel_file)}")
...
-    yaml.append(f"    - path: {rel_file}")
+    yaml.append(f"    - path: {json.dumps(rel_file)}")
...
-        yaml.append(f"        name: {name}")
-        yaml.append(f"        type: {msg_type}")
-        yaml.append(f"        serialization_format: {serialization}")
+        yaml.append(f"        name: {json.dumps(name)}")
+        yaml.append(f"        type: {json.dumps(msg_type)}")
+        yaml.append(f"        serialization_format: {json.dumps(serialization)}")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
rel_file = mcap_path.name
yaml = []
yaml.append("rosbag2_bagfile_information:")
yaml.append(f" version: {args.version}")
yaml.append(" storage_identifier: mcap")
yaml.append(" duration:")
yaml.append(f" nanoseconds: {duration_ns}")
yaml.append(" starting_time:")
yaml.append(f" nanoseconds_since_epoch: {start_ns}")
yaml.append(f" message_count: {total_messages}")
yaml.append(" relative_file_paths:")
yaml.append(f" - {rel_file}")
yaml.append(" files:")
yaml.append(f" - path: {rel_file}")
yaml.append(" starting_time:")
yaml.append(f" nanoseconds_since_epoch: {start_ns}")
yaml.append(" duration:")
yaml.append(f" nanoseconds: {duration_ns}")
yaml.append(f" message_count: {total_messages}")
yaml.append(" topics_with_message_count:")
for name, msg_type, count, serialization in topics:
yaml.append(" - topic_metadata:")
yaml.append(f" name: {name}")
yaml.append(f" type: {msg_type}")
yaml.append(f" serialization_format: {serialization}")
yaml.append(' offered_qos_profiles: ""')
yaml.append(f" message_count: {count}")
rel_file = mcap_path.name
yaml = []
yaml.append("rosbag2_bagfile_information:")
yaml.append(f" version: {args.version}")
yaml.append(" storage_identifier: mcap")
yaml.append(" duration:")
yaml.append(f" nanoseconds: {duration_ns}")
yaml.append(" starting_time:")
yaml.append(f" nanoseconds_since_epoch: {start_ns}")
yaml.append(f" message_count: {total_messages}")
yaml.append(" relative_file_paths:")
yaml.append(f" - {json.dumps(rel_file)}")
yaml.append(" files:")
yaml.append(f" - path: {json.dumps(rel_file)}")
yaml.append(" starting_time:")
yaml.append(f" nanoseconds_since_epoch: {start_ns}")
yaml.append(" duration:")
yaml.append(f" nanoseconds: {duration_ns}")
yaml.append(f" message_count: {total_messages}")
yaml.append(" topics_with_message_count:")
for name, msg_type, count, serialization in topics:
yaml.append(" - topic_metadata:")
yaml.append(f" name: {json.dumps(name)}")
yaml.append(f" type: {json.dumps(msg_type)}")
yaml.append(f" serialization_format: {json.dumps(serialization)}")
yaml.append(' offered_qos_profiles: ""')
yaml.append(f" message_count: {count}")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/python_tools/cuvslam_tools/bag2edex/make_mcap_metadata.py` around lines
69 - 97, Update the YAML generation block around the yaml list and topics loop
to serialize every interpolated scalar safely, including rel_file, args.version,
duration_ns, start_ns, total_messages, and topic fields. Use a YAML emitter or
JSON-style quoting/escaping for dynamic values while preserving numeric types
where required by the metadata schema, and ensure filenames and parsed ros2 bag
info values cannot alter YAML structure or parsed content.

Comment on lines +73 to +96
yaml.append(f" version: {args.version}")
yaml.append(" storage_identifier: mcap")
yaml.append(" duration:")
yaml.append(f" nanoseconds: {duration_ns}")
yaml.append(" starting_time:")
yaml.append(f" nanoseconds_since_epoch: {start_ns}")
yaml.append(f" message_count: {total_messages}")
yaml.append(" relative_file_paths:")
yaml.append(f" - {rel_file}")
yaml.append(" files:")
yaml.append(f" - path: {rel_file}")
yaml.append(" starting_time:")
yaml.append(f" nanoseconds_since_epoch: {start_ns}")
yaml.append(" duration:")
yaml.append(f" nanoseconds: {duration_ns}")
yaml.append(f" message_count: {total_messages}")
yaml.append(" topics_with_message_count:")

for name, msg_type, count, serialization in topics:
yaml.append(" - topic_metadata:")
yaml.append(f" name: {name}")
yaml.append(f" type: {msg_type}")
yaml.append(f" serialization_format: {serialization}")
yaml.append(' offered_qos_profiles: ""')

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== File outline ==\n'
ast-grep outline tools/python_tools/cuvslam_tools/bag2edex/make_mcap_metadata.py --view expanded || true

printf '\n== Relevant source excerpts ==\n'
sed -n '1,220p' tools/python_tools/cuvslam_tools/bag2edex/make_mcap_metadata.py | cat -n

printf '\n== README excerpt ==\n'
sed -n '1,180p' tools/python_tools/cuvslam_tools/bag2edex/README.md | cat -n

printf '\n== Search for type_description_hash / version handling ==\n'
rg -n "type_description_hash|rosbag2_bagfile_information.version|version:" tools/python_tools/cuvslam_tools/bag2edex -S

Repository: nvidia-isaac/cuVSLAM

Length of output: 2029


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
p = Path('tools/python_tools/cuvslam_tools/bag2edex/make_mcap_metadata.py')
text = p.read_text()
print('HAS type_description_hash:', 'type_description_hash' in text)
print('HAS version 9 literal:', 'version: 9' in text or 'version = 9' in text)
PY

Repository: nvidia-isaac/cuVSLAM

Length of output: 2029


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the generator and any local documentation for metadata version/schema requirements.
sed -n '1,220p' tools/python_tools/cuvslam_tools/bag2edex/make_mcap_metadata.py | cat -n
printf '\n--- README ---\n'
sed -n '1,180p' tools/python_tools/cuvslam_tools/bag2edex/README.md | cat -n
printf '\n--- Search ---\n'
rg -n "type_description_hash|rosbag2_bagfile_information.version|version 9|version 5|Jazzy|Humble" tools/python_tools/cuvslam_tools/bag2edex -S

Repository: nvidia-isaac/cuVSLAM

Length of output: 2029


🌐 Web query:

rosbag2_bagfile_information metadata version 9 type_description_hash required Humble Jazzy

💡 Result:

The metadata version 9 in rosbag2 introduces schema changes that are incompatible with older ROS 2 distributions such as Humble [1][2]. The type_description_hash is a field added to the TopicMetadata structure in newer ROS 2 versions (like Jazzy) and is serialized in version 9 metadata files [3][4][5]. In ROS 2 Humble, the rosbag2 metadata parser does not recognize this field, nor does it handle the updated serialization format for offered_qos_profiles, leading to parsing errors (e.g., yaml-cpp: error ... bad conversion) when attempting to play bags recorded in newer distributions [2][6][7]. Key differences in version 9 metadata include: - Inclusion of the type_description_hash field for topics [3][5]. - Changes to the serialization of offered_qos_profiles (using string names/enums instead of raw integer values) [4][8][7]. - Inclusion of additional fields such as ros_distro and custom_data [9][2]. Because these changes involve structural updates to how metadata is parsed and validated, version 9 metadata files are generally not backward compatible with Humble [1][2]. Users encountering these issues often need to manually edit the metadata.yaml file to remove incompatible fields (like type_description_hash, ros_distro, and custom_data) and revert offered_qos_profiles to a format compatible with Humble, or use third-party conversion scripts [6].

Citations:


🌐 Web query:

site:docs.ros.org rosbag2 metadata version 9 type_description_hash version 5 Humble

💡 Result:

In ROS 2, rosbag2 metadata files use a versioning system to track changes in the metadata schema [1][2][3]. The specific fields you mentioned are associated with different versions of this schema: The type_description_hash field was introduced to TopicMetadata in metadata version 7 [1][2]. In versions prior to 7, this field is not present or is treated as an empty string [1][2]. Regarding metadata version 9: This version introduced updates to how QoS (Quality of Service) profiles are serialized and handled within the metadata files [2]. Specifically, in versions 9 and later, the offered_qos_profiles field is serialized using YAML::convert rather than being stored as a raw string [2]. For ROS 2 Humble, the metadata version is generally lower than 9 (Humble typically uses version 5 or 6 depending on the specific release patch), meaning it does not support the version 9 metadata schema features such as the updated QoS serialization or the field structures associated with newer ROS 2 distributions [4][1][2]. The type_description_hash field may also be unavailable or handled differently depending on the specific patch version of Humble, as it was added in later development cycles [1][2]. In summary, metadata version 9 is a more recent schema evolution used in newer ROS 2 distributions (such as Rolling or Jazzy), whereas Humble relies on an older version of the schema [4][1][2][5].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find where the metadata file and version flag are used.
rg -n "make_mcap_metadata|--version|metadata.version|topics_with_message_count|type_description_hash" tools/python_tools -S

# Show the script in smaller slices if it is large.
wc -l tools/python_tools/cuvslam_tools/bag2edex/make_mcap_metadata.py
sed -n '1,140p' tools/python_tools/cuvslam_tools/bag2edex/make_mcap_metadata.py | cat -n

Repository: nvidia-isaac/cuVSLAM

Length of output: 2029


🌐 Web query:

"rosbag2_bagfile_information" "type_description_hash" required version 9

💡 Result:

In the context of ROS 2 rosbag2 metadata, version 9 is a storage format version that includes the type_description_hash field within the topic metadata [1][2]. This field is a string, typically prefixed with RIHS01_ (standing for ROS Interface Hash Specification), which provides a unique identifier representing the structure and type of the ROS 2 message [3][4]. The type_description_hash was originally introduced in version 7 of the rosbag2 metadata format [1][2]. Version 9 specifically introduced changes to how Quality of Service (QoS) metadata is serialized and handled, moving away from string-based representations toward deserialized structures in the code [1][2][5]. Because of these changes to the metadata structure and the handling of QoS profiles, older versions of ROS 2 (such as Humble) that only support earlier metadata formats cannot natively parse metadata.yaml files generated by version 9 [6][4]. Summary of Key Aspects: - Format Version: The version: 9 entry in metadata.yaml indicates the bag is using the current, more structured serialization format [3][2]. - Type Description Hash: The type_description_hash (e.g., RIHS01_...) allows tools to verify that the message type used during recording matches the type expected during playback, helping to avoid issues with changed message definitions [3][4]. - Compatibility: Version 9 metadata is not backward-compatible with older ROS 2 distributions (e.g., Humble) [4]. Attempting to open these bags in older environments often results in parsing errors because the YAML structure for QoS and other fields has evolved [6][4].

Citations:


Align the metadata schema with the ROS distribution you’re targeting.

  • tools/python_tools/cuvslam_tools/bag2edex/make_mcap_metadata.py#L73-L96: version: 9 expects newer metadata fields like type_description_hash and updated QoS serialization, so the emitted YAML won’t be compatible with Humble-era rosbag2. Either emit the v9 fields or default to the older schema.
  • tools/python_tools/cuvslam_tools/bag2edex/README.md#L99-L100: document the supported Humble/Jazzy version split instead of presenting 9 as a universal default.
📍 Affects 2 files
  • tools/python_tools/cuvslam_tools/bag2edex/make_mcap_metadata.py#L73-L96 (this comment)
  • tools/python_tools/cuvslam_tools/bag2edex/README.md#L99-L100
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/python_tools/cuvslam_tools/bag2edex/make_mcap_metadata.py` around lines
73 - 96, Update metadata generation around the YAML-building flow in
make_mcap_metadata.py to use a Humble-compatible default schema, or
conditionally emit the v9 fields including type_description_hash and updated QoS
serialization when version 9 is selected; preserve the existing topic metadata
values. In tools/python_tools/cuvslam_tools/bag2edex/README.md lines 99-100,
document the supported Humble/Jazzy version split and stop presenting version 9
as universal.

yaml.append(" custom_data: {}")
yaml.append("")

metadata_path.write_text("\n".join(yaml))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Do not silently overwrite existing metadata.

write_text() truncates an existing metadata.yaml, even though this workflow is documented for missing metadata. Refuse by default or require an explicit --force, and write through a temporary file before replacing the destination to avoid leaving a partial file after interruption.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/python_tools/cuvslam_tools/bag2edex/make_mcap_metadata.py` at line 104,
Update the metadata-writing flow around metadata_path.write_text to refuse
overwriting an existing metadata.yaml by default, allowing replacement only when
an explicit --force option is provided. Write the generated YAML to a temporary
file in the destination directory, then atomically replace metadata_path after
the write succeeds so interruptions cannot leave a partial metadata file.

Comment on lines +86 to +90
## Generating Missing `metadata.yaml` for MCAP Files

`make_mcap_metadata.py` regenerates the `metadata.yaml` file that `rosbag2` requires next to an `.mcap` file. Use it when you have a standalone `.mcap` file without its companion `metadata.yaml` — for example, after downloading only the `.mcap` from a recording system or after the metadata file was accidentally deleted.

**Prerequisites:** `ros2` must be on `PATH` (the script calls `ros2 bag info` internally).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Document the MCAP storage plugin prerequisite. ros2 on PATH is not enough here; the sourced ROS 2 environment also needs the MCAP storage plugin available for ros2 bag info --storage mcap.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/python_tools/cuvslam_tools/bag2edex/README.md` around lines 86 - 90,
Update the “Generating Missing metadata.yaml for MCAP Files” prerequisites
section to state that the ROS 2 environment must be sourced and the MCAP storage
plugin must be installed and available for `ros2 bag info --storage mcap`, in
addition to `ros2` being on PATH.

Comment on lines +92 to +103
**Usage:**
```sh
./make_mcap_metadata.py path/to/rosbag.mcap
```

The script writes `metadata.yaml` into the same directory as the `.mcap` file. Once generated, the directory can be used with the extraction tools above.

**Optional argument:**
- `--version <int>` — sets the `rosbag2_bagfile_information.version` field in the metadata (default: `9`). Only change this if you need to match a specific rosbag2 version.

**Example:**
```sh

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add blank lines around fenced code blocks.

markdownlint reports MD031 for both added fences. Insert a blank line before each opening fence.

Proposed fix
 **Usage:**
+
 ```sh
 ...
 **Example:**
+
 ```sh
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
**Usage:**
```sh
./make_mcap_metadata.py path/to/rosbag.mcap
```
The script writes `metadata.yaml` into the same directory as the `.mcap` file. Once generated, the directory can be used with the extraction tools above.
**Optional argument:**
- `--version <int>` — sets the `rosbag2_bagfile_information.version` field in the metadata (default: `9`). Only change this if you need to match a specific rosbag2 version.
**Example:**
```sh
**Usage:**
🧰 Tools
🪛 markdownlint-cli2 (0.23.0)

[warning] 93-93: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 103-103: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/python_tools/cuvslam_tools/bag2edex/README.md` around lines 92 - 103,
Update the Markdown in the Usage and Example sections of README.md by adding a
blank line before each opening fenced code block, ensuring both fences satisfy
markdownlint MD031 without changing their content.

Source: Linters/SAST tools

Comment on lines +99 to +100
**Optional argument:**
- `--version <int>` — sets the `rosbag2_bagfile_information.version` field in the metadata (default: `9`). Only change this if you need to match a specific rosbag2 version.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show surrounding README context
sed -n '1,180p' tools/python_tools/cuvslam_tools/bag2edex/README.md

# Find other mentions of rosbag2/version in this area
rg -n --hidden --no-messages "version|rosbag2|Humble|Jazzy" tools/python_tools/cuvslam_tools/bag2edex

Repository: nvidia-isaac/cuVSLAM

Length of output: 2029


🌐 Web query:

rosbag2_storage bag_metadata version default Humble Jazzy docs

💡 Result:

In ROS 2, the rosbag2 metadata format is versioned to track changes in the BagMetadata structure [1][2][3]. As of ROS 2 Jazzy, the BagMetadata version is 9 [1][4][3]. Key details regarding metadata versioning and compatibility between Humble and Jazzy include: 1. Version Evolution: The metadata version number is internal to rosbag2_storage and increments whenever the BagMetadata struct or its serialization format changes [1][2][3]. Version 9 introduced updates to QoS metadata serialization and enums [3]. 2. Compatibility Issues: Bag files recorded in newer versions of ROS 2 (like Jazzy, which uses version 9) are often incompatible with older versions (like Humble) [5][6][7]. Attempting to play a Jazzy-recorded bag in Humble typically results in a yaml-cpp parsing error due to differences in the metadata.yaml structure, specifically regarding the handling of offered_qos_profiles, the addition of fields like type_description_hash, custom_data, and ros_distro in newer versions [5][6][7]. 3. Default Behavior: While the rosbag2 tool provides default storage plugins (such as mcap or sqlite3) [8], the metadata.yaml file is generated by the rosbag2_storage library [9][8], which strictly enforces the schema corresponding to the current ROS distribution's BagMetadata version [2][3]. Users experiencing compatibility errors when moving bags from newer distributions to older ones often must convert or manually refactor the metadata.yaml file to match the expected format of the older distribution [7].

Citations:


🌐 Web query:

site:docs.ros.org humble rosbag2_storage bag_metadata version 5

💡 Result:

In ROS 2 Humble, the rosbag2_storage package defines the bag metadata structure with version 5 [1][2]. The BagMetadata structure is primarily used to manage recording information and includes a version field, which is incremented when the structure of the metadata changes to ensure backward compatibility and proper serialization [2]. Specifically, in version 5 of the metadata schema, the structure introduced support for the files field, which contains a vector of FileInformation objects [3][4]. This field allows the system to explicitly track multiple files associated with a single bag, which is critical for storage formats that split recordings across several files [1][4]. The metadata is typically serialized into a metadata.yaml file [5]. When the system reads this file, it uses the version number to decide which fields to parse [3][4]. For instance, the decoding logic in rosbag2_storage specifically checks if the version is 5 or greater to correctly deserialize the files information [3][4]. While version 5 was current for Humble, newer versions of ROS 2 have subsequently introduced higher metadata versions to support additional features, such as custom data maps (version 6) and ROS distribution tracking (version 8) [3][6].

Citations:


🌐 Web query:

site:docs.ros.org/en/humble/p/rosbag2_storage/generated/program_listing_file_include_rosbag2_storage_bag_metadata.hpp.html BagMetadata version

💡 Result:

In the context of the ROS 2 (Robot Operating System) rosbag2_storage library, the BagMetadata structure includes a version field that is used to track changes to the content of the structure [1]. As of the documentation for rosbag2_storage version 0.15.16, the defined version is 5 [1]. The documentation explicitly notes that this number should be upgraded whenever the content of the struct is changed [1].

Citations:


Clarify --version as ROS-distro-specific The default depends on the target rosbag2 release: Humble uses metadata version 5, while Jazzy uses 9. Document the supported distro/version pairs here instead of implying 9 is universal.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/python_tools/cuvslam_tools/bag2edex/README.md` around lines 99 - 100,
Update the --version option documentation in the bag2edex README to state that
the default is ROS-distribution-specific: Humble uses metadata version 5 and
Jazzy uses version 9. Document these supported distro/version pairs instead of
presenting 9 as the universal default.

@github-actions

Copy link
Copy Markdown

Test Results

Status Platform Language Total Passed Failed Errors Skipped
Orin C++ 16 16 0 0 0
Orin Python 71 70 0 0 1
Thor C++ 16 16 0 0 0
Thor Python 71 70 0 0 1
x86_64 C++ 16 16 0 0 0
x86_64 Python 71 70 0 0 1

cuVSLAM Evaluation KPIs

Config Dataset ATE,% ARE,º/m Kabsch, Losts, diff ATE,% diff ARE,º/m diff Kabsch, diff Losts, FPS,Hz
x86_64-cuda12.6.3-ubuntu24.04 KITTI-STEREO_ODOM 0.8375 0.0023 2.6999 0 NA NA NA NA 301.1
x86_64-cuda12.6.3-ubuntu24.04 KITTI-STEREO_SLAM 0.7574 0.002 1.9246 0 NA NA NA NA 177.8

Artifacts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant