Skip to main content

baglint

Validates the contents of MCAP recordings against a declarative specification. Checks for missing topics, recording gaps and rate violations, and returns a non-zero exit status when a recording does not satisfy the specification.

Validation of the MCAP container itself, such as chunk CRCs and index integrity, is out of scope. Use mcap doctor for that.

Requirements

  • Python 3.10 or later

Installation

$ python3 -m venv .venv
$ .venv/bin/pip install -e .

When ROS 2 is sourced, /opt/ros/$ROS_DISTRO/lib/python3.*/site-packages is on PYTHONPATH and is inherited by the virtual environment, which causes ROS pytest plugins to load during test runs. Clear it when invoking the tool:

$ env -u PYTHONPATH .venv/bin/baglint --help

Usage

$ baglint BAG [-s SPEC] [-f {text,json}] [--strict]
$ baglint BAG --init [--margin FRACTION]
Option Description
-s, --spec Specification file to validate against
-f, --format Output format, text (default) or json
--strict Exit non-zero on WARN findings as well as FAIL
--init Print a specification generated from the recording instead of validating it
--margin With --init, the fraction below the observed rate at which to set min_rate. Default 0.1
--version Print version and exit

Without -s, no checks run and nothing is validated.

Generating a specification

--init writes a specification describing a recording, which is the practical way to produce a first one:

$ baglint good_run.mcap --init > spec.yaml
$ baglint experiment_042.mcap --spec spec.yaml

min_rate is set below each topic's observed mean rate by --margin, and max_gap_ms to twice the worst interval observed. Topics with fewer than ten messages are generated as presence-only, since a mean rate over so few samples describes the recording length rather than the publisher.

The bounds describe the recording they came from, defects included. Generate from a run that is known to be good, and treat the result as a starting point.

Specification

Topic keys accept glob patterns. The first matching entry applies, so list specific topics before wildcards.

topics:
  /joint_states:
    min_rate: 490
    max_gap_ms: 10

  /camera/*:
    min_rate: 25

  /diagnostics:
    required: false
Key Type Description
min_rate float Minimum mean publication rate in Hz, measured over the topic's own span
max_gap_ms float Maximum permitted interval between consecutive messages
required bool Whether a topic named literally must be present. Default true
check_stamps bool Validate header.stamp ordering. Default false, as it deserializes payloads

A transforms.required list of [parent, child] frame pairs is parsed and validated, but no check consumes it yet.

Output

$ baglint experiment_042.mcap --spec examples/demo_spec.yaml
experiment_042.mcap
  3 topics · 680,884 messages · 18m32s

FAIL /camera/image
  rate 12.4 Hz below minimum 25 Hz  [log_time]

FAIL /joint_states
  3 missing interval(s) >10 ms (worst 122.0 ms at 904.00 s)  [log_time]

FAIL /tf
  required by spec but no messages in bag

3 findings: 3 FAIL

To regenerate the recording used above:

$ python examples/make_demo_bag.py experiment_042.mcap

--format json emits the same findings for machine consumption. Each carries a stable code, intended for filtering and baselining in CI:

Code Level Meaning
gap FAIL Consecutive messages exceeded max_gap_ms
rate_below_min FAIL Mean rate fell below min_rate
rate_unmeasurable FAIL Fewer than two messages, so no rate can be computed
missing_topic FAIL A required topic carried no messages
stamp_backwards FAIL A header.stamp preceded the stamp before it
stamp_duplicate WARN A message repeated the previous header.stamp
stamp_unset WARN A message carried a zero header.stamp
stamp_unavailable WARN check_stamps was set on a message type without a header

Message timestamps

Each message carries two timestamps, and findings state which one was used:

Timestamp Set by A defect indicates
log_time the recorder, on write the recorder stalled: disk I/O, CPU starvation, a terminated node
header.stamp the publisher, at sample time the sensor or its driver misbehaved

Gap and rate checks read log_time. Stamp checks read header.stamp and are enabled per topic with check_stamps, which is off by default because it requires deserializing every message on that topic:

topics:
  /imu:
    check_stamps: true

A stamp that moves backwards is reported as a failure. Downstream consumers such as tf2, message_filters and the SLAM backends assume a non-decreasing stamp sequence per topic, and do not report the violation themselves. Duplicate and zero stamps are reported as warnings.

A zero stamp is treated as never populated rather than as a timestamp, so it does not become the baseline for the messages that follow it.

Exit codes

Code Condition
0 No FAIL findings. With --strict, no WARN findings either
1 At least one finding at or above the failing level
2 Invalid arguments, unreadable recording, or malformed specification

Development

$ make install
$ make test

Tests construct MCAP recordings with injected defects at known offsets. See tests/fixtures.py.

Metadata

Release files for baglint 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for baglint 0.1.0
File Size Uploaded
baglint-0.1.0.tar.gz 19.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for baglint 0.1.0
File Interpreter ABI Platform
baglint-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 38.9 kB

Release files / baglint-0.1.0.tar.gz

Download URL baglint-0.1.0.tar.gz
Size 19.7 kB
Tags Source
SHA-256 checksum
How to use checksums
d0328a3ebb3c35fe29cb36e915cf3867a34f767baf988c4e89fb7a65ec7a41a1
BLAKE2b-256 checksum
How to use checksums
b213ea47e48649bdab0003ee47055399156274475e947bf427345a11e6fbe798
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / baglint-0.1.0-py3-none-any.whl

Download URL baglint-0.1.0-py3-none-any.whl
Size 19.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5be69ef905a39074daffacdc9b0c1ac2d3fbaca5611008c10a37b5cda549cd8d
BLAKE2b-256 checksum
How to use checksums
8d4cf920c1e1094cf93fc2f161e3427e72b6f27ba383c6c3c2eeef2f2387a486
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release history Release notifications | RSS feed

0.2.1

2 release files

0.2.0

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page