Metadata-Version: 2.4
Name: clockdoctor
Version: 0.1.0
Summary: Diagnose sensor/recorder clock sync issues (offset, drift, jitter, gaps) in ROS2 mcap recordings, with an interactive HTML dashboard.
License-Expression: Apache-2.0
Project-URL: Homepage, https://github.com/Benjamin-Tan/clockdoctor
Project-URL: Repository, https://github.com/Benjamin-Tan/clockdoctor
Project-URL: Issues, https://github.com/Benjamin-Tan/clockdoctor/issues
Keywords: ros2,mcap,rosbag,timestamp,clock-sync,diagnostics,robotics
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Software Development :: Debuggers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Operating System :: OS Independent
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: mcap-ros2-support
Requires-Dist: numpy
Requires-Dist: pandas
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Provides-Extra: lint
Requires-Dist: ruff; extra == "lint"
Dynamic: license-file

# clockdoctor

Diagnose sensor/recorder clock sync issues in ROS2 `.mcap` recordings — offset,
drift, jitter, gaps, coverage — and get an interactive, self-contained HTML
dashboard out the other end. No GUI app to install; the dashboard is one HTML
file you can open locally or send to someone else.

## Install

```bash
pip install clockdoctor
```

## Use

```bash
clockdoctor path/to/recording.mcap
```

That's it — it decodes every topic, runs the analysis, and writes (next to
the input file):

- `<name>_dashboard.html` — open this in a browser
- `<name>_timestamps.csv` — one row per message
- `<name>_timeline_data.json` — the data backing the dashboard

Point it at an already-extracted `*_messages.jsonl` instead of a `.mcap` and
it skips straight to analysis.

## What it checks, per topic

- **Clock offset vs. drift vs. jitter** — a linear regression over
  recorder-time-minus-source-time, so a fixed epoch bug (offset) is never
  confused with the source clock genuinely running at a different rate
  (drift); jitter is what's left after removing both.
- **Cadence regularity** on both the recorder clock and the sensor's own
  clock — distinguishes recorder-side buffering from real sensor irregularity.
- **Gaps, duplicates, out-of-order timestamps, coverage** (does a topic start
  late or end early relative to the rest of the recording?).
- Works whether a topic's clock lives in a ROS `header.stamp` or is embedded
  as JSON inside a `std_msgs/String` payload (`--embedded-timestamp-key`).

## Options

```bash
clockdoctor recording.mcap --topic /some/topic   # extraction: restrict to one topic
clockdoctor recording.mcap --out-dir ./out        # write outputs elsewhere
clockdoctor recording.mcap --embedded-timestamp-key ts
```

Explicit subcommands are also available if you want to run extraction and
analysis as separate steps: `clockdoctor extract recording.mcap` /
`clockdoctor analyze recording_messages.jsonl`.

## Scope

Only ROS2/CDR-encoded `.mcap` channels are decoded (via `mcap-ros2-support`).
ROS1 bags and protobuf/flatbuffer-encoded mcap channels are out of scope.

Extraction only pulls out `header` (stamp + frame_id) and, for `std_msgs/String`
topics, the raw string — never point clouds, images, scan arrays, poses, or any
other bulk sensor payload, since none of that is needed for sync analysis. For
a LaserScan/Odometry/Imu-heavy recording that keeps the intermediate JSONL a
fraction of the size a full decode would produce.

## License

Apache License 2.0 — see [LICENSE](LICENSE).

The analyzer itself only ever reads a documented JSONL row schema (see the
top of `src/clockdoctor/analyze.py`), so any other producer — a different
logger, a reshaped CSV/DB export — can feed it directly without going through
mcap at all.
