pymcap-cli 0.9.0__tar.gz → 0.10.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/PKG-INFO +221 -4
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/README.md +211 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/pyproject.toml +16 -14
- pymcap_cli-0.10.0/src/pymcap_cli/cli.py +284 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/_run_processor_multi.py +6 -14
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/bag2mcap_cmd.py +13 -33
- pymcap_cli-0.10.0/src/pymcap_cli/cmd/bridge/__init__.py +25 -0
- pymcap_cli-0.10.0/src/pymcap_cli/cmd/bridge/_shared.py +199 -0
- pymcap_cli-0.10.0/src/pymcap_cli/cmd/bridge/cat.py +429 -0
- pymcap_cli-0.10.0/src/pymcap_cli/cmd/bridge/inspect.py +382 -0
- pymcap_cli-0.10.0/src/pymcap_cli/cmd/bridge/record.py +503 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/cat_cmd.py +91 -118
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/compress_cmd.py +2 -3
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/convert_cmd.py +10 -75
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/diag_cmd.py +3 -2
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/diff_cmd.py +18 -50
- pymcap_cli-0.10.0/src/pymcap_cli/cmd/doctor_cmd.py +156 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/duplicates_cmd.py +20 -53
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/export_csv_cmd.py +1 -6
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/export_geo_cmd.py +1 -6
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/export_images_cmd.py +4 -10
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/export_json_cmd.py +1 -6
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/export_parquet_cmd.py +1 -6
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/export_pcd_cmd.py +1 -6
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/filter_cmd.py +67 -3
- pymcap_cli-0.10.0/src/pymcap_cli/cmd/get_cmd.py +150 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/info_cmd.py +12 -13
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/list_cmd.py +5 -4
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/merge_cmd.py +25 -3
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/plot_cmd.py +11 -7
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/process_cmd.py +2 -11
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/rechunk_cmd.py +17 -14
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/recover_cmd.py +2 -3
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/recover_inplace_cmd.py +8 -5
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/roscompress_cmd.py +7 -17
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/rosdecompress_cmd.py +6 -13
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/split_cmd.py +187 -48
- pymcap_cli-0.10.0/src/pymcap_cli/cmd/tf_export_cmd.py +243 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/tftree_cmd.py +19 -112
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/video_cmd.py +0 -2
- pymcap_cli-0.10.0/src/pymcap_cli/constants.py +14 -0
- pymcap_cli-0.10.0/src/pymcap_cli/core/input_options.py +113 -0
- pymcap_cli-0.10.0/src/pymcap_cli/core/input_processor_chain.py +75 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/core/mcap_compare.py +0 -15
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/core/mcap_processor.py +618 -290
- pymcap_cli-0.10.0/src/pymcap_cli/core/processors/always_decode.py +20 -0
- pymcap_cli-0.10.0/src/pymcap_cli/core/processors/attachment_filter.py +28 -0
- pymcap_cli-0.10.0/src/pymcap_cli/core/processors/base.py +263 -0
- pymcap_cli-0.10.0/src/pymcap_cli/core/processors/boundary_split.py +70 -0
- pymcap_cli-0.10.0/src/pymcap_cli/core/processors/channel_merge.py +79 -0
- pymcap_cli-0.10.0/src/pymcap_cli/core/processors/dedup.py +143 -0
- pymcap_cli-0.10.0/src/pymcap_cli/core/processors/duration_split.py +66 -0
- pymcap_cli-0.10.0/src/pymcap_cli/core/processors/expression_split.py +273 -0
- pymcap_cli-0.10.0/src/pymcap_cli/core/processors/latching.py +168 -0
- pymcap_cli-0.10.0/src/pymcap_cli/core/processors/metadata_filter.py +28 -0
- pymcap_cli-0.10.0/src/pymcap_cli/core/processors/nth_message.py +74 -0
- pymcap_cli-0.10.0/src/pymcap_cli/core/processors/size_split.py +65 -0
- pymcap_cli-0.10.0/src/pymcap_cli/core/processors/time_filter.py +141 -0
- pymcap_cli-0.10.0/src/pymcap_cli/core/processors/time_offset.py +68 -0
- pymcap_cli-0.10.0/src/pymcap_cli/core/processors/timestamp_split.py +40 -0
- pymcap_cli-0.10.0/src/pymcap_cli/core/processors/topic_alias.py +132 -0
- pymcap_cli-0.10.0/src/pymcap_cli/core/processors/topic_filter.py +60 -0
- pymcap_cli-0.10.0/src/pymcap_cli/core/processors/topic_rewrite.py +67 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/core/processors/utils.py +5 -5
- pymcap_cli-0.10.0/src/pymcap_cli/core/tf_tree.py +154 -0
- pymcap_cli-0.10.0/src/pymcap_cli/display/cat_helpers.py +65 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/display/display_utils.py +3 -2
- pymcap_cli-0.10.0/src/pymcap_cli/display/message_render.py +523 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/display/sparkline.py +0 -3
- pymcap_cli-0.10.0/src/pymcap_cli/display/time_ranges.py +60 -0
- pymcap_cli-0.10.0/src/pymcap_cli/doctor.py +3024 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/exporters/_common.py +12 -4
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/exporters/csv_exporter.py +2 -2
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/exporters/driver.py +1 -1
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/exporters/geo_common.py +76 -4
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/exporters/geojson_exporter.py +6 -35
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/exporters/gpx_exporter.py +7 -58
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/exporters/image_exporter.py +87 -59
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/exporters/json_exporter.py +2 -1
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/exporters/kml_exporter.py +15 -63
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/exporters/parquet_exporter.py +2 -16
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/exporters/pcd_exporter.py +2 -16
- pymcap_cli-0.10.0/src/pymcap_cli/exporters/sdf_exporter.py +70 -0
- pymcap_cli-0.10.0/src/pymcap_cli/exporters/urdf_exporter.py +65 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/exporters/video_exporter.py +4 -2
- pymcap_cli-0.10.0/src/pymcap_cli/exporters/video_file_writer.py +560 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/rihs01.py +2 -2
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/rosbag_reader/_reader.py +2 -3
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/rosbag_reader/_types.py +1 -1
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/types/duration.py +7 -5
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/types/info_data.py +27 -28
- pymcap_cli-0.10.0/src/pymcap_cli/types/size.py +52 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/types/to_plain.py +5 -3
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/types/types_manual.py +4 -16
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/utils.py +199 -50
- pymcap_cli-0.9.0/src/pymcap_cli/cli.py +0 -247
- pymcap_cli-0.9.0/src/pymcap_cli/core/processors/always_decode.py +0 -16
- pymcap_cli-0.9.0/src/pymcap_cli/core/processors/attachment_filter.py +0 -19
- pymcap_cli-0.9.0/src/pymcap_cli/core/processors/base.py +0 -80
- pymcap_cli-0.9.0/src/pymcap_cli/core/processors/duration_split.py +0 -73
- pymcap_cli-0.9.0/src/pymcap_cli/core/processors/expression_split.py +0 -153
- pymcap_cli-0.9.0/src/pymcap_cli/core/processors/metadata_filter.py +0 -19
- pymcap_cli-0.9.0/src/pymcap_cli/core/processors/time_filter.py +0 -48
- pymcap_cli-0.9.0/src/pymcap_cli/core/processors/timestamp_split.py +0 -70
- pymcap_cli-0.9.0/src/pymcap_cli/core/processors/topic_filter.py +0 -36
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/__init__.py +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/__init__.py +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/_run_processor.py +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/du_cmd.py +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/info_json_cmd.py +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/records_cmd.py +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/cmd/topic_chunks_cmd.py +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/core/__init__.py +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/core/input_handler.py +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/core/mcap_transform.py +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/core/msg_resolver.py +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/core/processors/__init__.py +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/debug_wrapper.py +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/display/__init__.py +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/display/osc_utils.py +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/encoding/__init__.py +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/encoding/arrow_schema.py +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/exporters/__init__.py +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/exporters/base.py +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/exporters/plot_exporter.py +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/http_utils.py +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/log_setup.py +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/py.typed +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/rosbag_reader/__init__.py +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/rosbag_reader/py.typed +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/types/__init__.py +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/types/info_link.py +0 -0
- {pymcap_cli-0.9.0 → pymcap_cli-0.10.0}/src/pymcap_cli/types/info_types.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: pymcap-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.10.0
|
|
4
4
|
Summary: High-performance Python CLI for MCAP file processing with advanced recovery, filtering, and optimization capabilities
|
|
5
5
|
Keywords: mcap,cli,robotics,ros,ros2,recovery,filtering,compression
|
|
6
6
|
Author: Marko Bausch
|
|
@@ -16,39 +16,45 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.12
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
20
|
Classifier: Topic :: Scientific/Engineering
|
|
20
21
|
Classifier: Topic :: System :: Archiving
|
|
21
22
|
Classifier: Topic :: Utilities
|
|
22
23
|
Classifier: Typing :: Typed
|
|
23
24
|
Requires-Dist: rich>=14.1.0
|
|
24
25
|
Requires-Dist: small-mcap[compression]
|
|
25
|
-
Requires-Dist: mcap-codec-support[ros2]
|
|
26
26
|
Requires-Dist: mcap-ros2-support-fast
|
|
27
27
|
Requires-Dist: cyclopts>=4
|
|
28
28
|
Requires-Dist: ros-parser
|
|
29
29
|
Requires-Dist: platformdirs>=4.0.0
|
|
30
30
|
Requires-Dist: pyyaml>=6.0
|
|
31
31
|
Requires-Dist: typing-extensions>=4.15.0
|
|
32
|
-
Requires-Dist: pymcap-cli[video,pointcloud,plot,parquet,image,draco] ; extra == 'all'
|
|
32
|
+
Requires-Dist: pymcap-cli[video,pointcloud,plot,parquet,image,draco,bridge,xxhash] ; extra == 'all'
|
|
33
|
+
Requires-Dist: robo-ws-bridge ; extra == 'bridge'
|
|
33
34
|
Requires-Dist: mcap-codec-support[draco] ; extra == 'draco'
|
|
34
|
-
Requires-Dist:
|
|
35
|
+
Requires-Dist: pillow>=10.0 ; extra == 'image'
|
|
36
|
+
Requires-Dist: pymcap-cli[image,draco,bridge,xxhash] ; extra == 'lite'
|
|
35
37
|
Requires-Dist: pyarrow>=15.0.0 ; extra == 'parquet'
|
|
36
38
|
Requires-Dist: numpy>=1.24.0 ; extra == 'parquet'
|
|
37
39
|
Requires-Dist: mcap-codec-support[pointcloud] ; extra == 'parquet'
|
|
38
40
|
Requires-Dist: plotly>=6.0.0 ; extra == 'plot'
|
|
39
41
|
Requires-Dist: mcap-codec-support[pointcloud] ; extra == 'pointcloud'
|
|
40
42
|
Requires-Dist: mcap-codec-support[video] ; extra == 'video'
|
|
43
|
+
Requires-Dist: xxhash>=3.0.0 ; extra == 'xxhash'
|
|
41
44
|
Requires-Python: >=3.10
|
|
42
45
|
Project-URL: Homepage, https://github.com/mrkbac/robotic-tools
|
|
43
46
|
Project-URL: Issues, https://github.com/mrkbac/robotic-tools/issues
|
|
44
47
|
Project-URL: Repository, https://github.com/mrkbac/robotic-tools
|
|
45
48
|
Provides-Extra: all
|
|
49
|
+
Provides-Extra: bridge
|
|
46
50
|
Provides-Extra: draco
|
|
47
51
|
Provides-Extra: image
|
|
52
|
+
Provides-Extra: lite
|
|
48
53
|
Provides-Extra: parquet
|
|
49
54
|
Provides-Extra: plot
|
|
50
55
|
Provides-Extra: pointcloud
|
|
51
56
|
Provides-Extra: video
|
|
57
|
+
Provides-Extra: xxhash
|
|
52
58
|
Description-Content-Type: text/markdown
|
|
53
59
|
|
|
54
60
|
# pymcap-cli
|
|
@@ -80,6 +86,7 @@ uv add pymcap-cli[video]
|
|
|
80
86
|
- **Smart Chunk Copying** — fast chunk copying without decompression when possible, up to 10x faster for filtering operations
|
|
81
87
|
- **Unified Processing** — single `process` command combines recovery + filtering + compression in one optimized pass
|
|
82
88
|
- **Precise Filtering** — regex topic filtering, time range filtering, and content type filtering with deferred schema/channel writing
|
|
89
|
+
- **Broad Format Coverage** — converts ROS 1 `.bag` and ROS 2 `.db3` to MCAP, exports to NDJSON, CSV, Parquet, PCD, GeoJSON/KML/GPX, and image/video files
|
|
83
90
|
- **Rich Terminal Output** — colored topics, Unicode distribution histograms, tree views, and responsive layouts
|
|
84
91
|
- **Robust Error Handling** — graceful degradation with detailed error reporting and recovery statistics
|
|
85
92
|
|
|
@@ -169,6 +176,27 @@ pymcap-cli tftree data.mcap
|
|
|
169
176
|
pymcap-cli tftree data.mcap --static-only
|
|
170
177
|
```
|
|
171
178
|
|
|
179
|
+
### `tf-export` — TF Tree to URDF / SDF / JSON
|
|
180
|
+
|
|
181
|
+
Reconstruct robot description files from `/tf_static` (and optionally `/tf` at a
|
|
182
|
+
snapshot timestamp). Useful when the original `.urdf` is missing — Foxglove
|
|
183
|
+
Studio and rviz can render the static skeleton from the exported file.
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
# Write a URDF for the static tree
|
|
187
|
+
pymcap-cli tf-export data.mcap -o robot.urdf
|
|
188
|
+
|
|
189
|
+
# SDF or JSON instead
|
|
190
|
+
pymcap-cli tf-export data.mcap --format sdf -o robot.sdf
|
|
191
|
+
pymcap-cli tf-export data.mcap --format json
|
|
192
|
+
|
|
193
|
+
# Capture a dynamic snapshot from /tf at a given time
|
|
194
|
+
pymcap-cli tf-export data.mcap --include-dynamic-at 2024-01-01T10:00:00Z -o snapshot.urdf
|
|
195
|
+
|
|
196
|
+
# Pick a subtree when the recording has multiple disconnected roots
|
|
197
|
+
pymcap-cli tf-export data.mcap --root base_link -o robot.urdf
|
|
198
|
+
```
|
|
199
|
+
|
|
172
200
|
### `diag` — ROS2 Diagnostics
|
|
173
201
|
|
|
174
202
|
Inspect ROS2 diagnostics with per-component health overview, sparkline timelines, frequency stats, and time-in-state tracking.
|
|
@@ -269,6 +297,9 @@ pymcap-cli merge *.mcap -o all_recordings.mcap --compression lz4
|
|
|
269
297
|
|
|
270
298
|
# Exclude metadata/attachments
|
|
271
299
|
pymcap-cli merge file1.mcap file2.mcap -o merged.mcap --metadata exclude
|
|
300
|
+
|
|
301
|
+
# Drop duplicate messages (same channel, log_time, payload) from overlapping inputs
|
|
302
|
+
pymcap-cli merge a.mcap b.mcap -o merged.mcap --dedup-identical
|
|
272
303
|
```
|
|
273
304
|
|
|
274
305
|
### `convert` — Convert DB3 to MCAP
|
|
@@ -286,6 +317,43 @@ pymcap-cli convert input.db3 -o output.mcap --distro jazzy
|
|
|
286
317
|
pymcap-cli convert input.db3 -o output.mcap --extra-path /path/to/msgs
|
|
287
318
|
```
|
|
288
319
|
|
|
320
|
+
### `bag2mcap` — Convert ROS 1 Bag to MCAP
|
|
321
|
+
|
|
322
|
+
Convert ROS 1 `.bag` files to MCAP using the `ros1` profile. Message bytes are
|
|
323
|
+
preserved as raw ROS 1 serialization and schemas use `ros1msg` encoding with
|
|
324
|
+
the full message definition from the bag.
|
|
325
|
+
|
|
326
|
+
```bash
|
|
327
|
+
# Basic conversion
|
|
328
|
+
pymcap-cli bag2mcap recording.bag -o recording.mcap
|
|
329
|
+
|
|
330
|
+
# Pick a different compression / chunk size
|
|
331
|
+
pymcap-cli bag2mcap recording.bag -o recording.mcap --compression lz4 --chunk-size 8388608
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### `split` — Split into Segments
|
|
335
|
+
|
|
336
|
+
Split an MCAP file into multiple output segments by duration, explicit
|
|
337
|
+
timestamps, value-change of a message-path expression, or a byte budget per
|
|
338
|
+
segment.
|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
# Split every 60 seconds
|
|
342
|
+
pymcap-cli split data.mcap --duration 60s -t "out_{index:03d}.mcap"
|
|
343
|
+
|
|
344
|
+
# Split at specific RFC3339 timestamps
|
|
345
|
+
pymcap-cli split data.mcap --split-at "2024-01-01T10:00:00Z" --split-at "2024-01-01T10:30:00Z"
|
|
346
|
+
|
|
347
|
+
# Start a new segment when /gps/fix.status.status changes value
|
|
348
|
+
pymcap-cli split data.mcap -E "/gps/fix.status.status"
|
|
349
|
+
|
|
350
|
+
# Predicate trigger — split on match/no-match transitions
|
|
351
|
+
pymcap-cli split data.mcap -E "/detections.objects[:]{confidence>0.8}"
|
|
352
|
+
|
|
353
|
+
# Split when each output reaches roughly 1 GB
|
|
354
|
+
pymcap-cli split data.mcap --max-size 1G -t "shard_{index:03d}.mcap"
|
|
355
|
+
```
|
|
356
|
+
|
|
289
357
|
### `rechunk` — Topic-Based Rechunking
|
|
290
358
|
|
|
291
359
|
Reorganize MCAP messages into separate chunk groups based on topic patterns for optimized playback.
|
|
@@ -343,6 +411,73 @@ pymcap-cli list attachments data.mcap
|
|
|
343
411
|
pymcap-cli list metadata data.mcap
|
|
344
412
|
```
|
|
345
413
|
|
|
414
|
+
### `get` — Extract Attachments and Metadata
|
|
415
|
+
|
|
416
|
+
Extract a single attachment's bytes or a metadata record's key/value map.
|
|
417
|
+
|
|
418
|
+
```bash
|
|
419
|
+
# Write attachment bytes to a file (or pipe stdout)
|
|
420
|
+
pymcap-cli get attachment --name calib.bin --output calib.bin data.mcap
|
|
421
|
+
pymcap-cli get attachment -n calib.bin data.mcap > calib.bin
|
|
422
|
+
|
|
423
|
+
# Disambiguate when multiple attachments share a name
|
|
424
|
+
pymcap-cli get attachment --name notes.txt --offset 1234 -o notes.txt data.mcap
|
|
425
|
+
|
|
426
|
+
# Print a metadata record as JSON (records sharing a name are merged)
|
|
427
|
+
pymcap-cli get metadata --name session data.mcap
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### `diff` — Compare Files
|
|
431
|
+
|
|
432
|
+
Compare MCAP files using summary and message-index timestamps. Reads through the
|
|
433
|
+
footer/summary first and falls back to rebuilding metadata from the data section
|
|
434
|
+
when the summary is missing.
|
|
435
|
+
|
|
436
|
+
```bash
|
|
437
|
+
# Compare two recordings
|
|
438
|
+
pymcap-cli diff a.mcap b.mcap
|
|
439
|
+
|
|
440
|
+
# Hide channels with identical timestamps
|
|
441
|
+
pymcap-cli diff a.mcap b.mcap --skip-identical
|
|
442
|
+
|
|
443
|
+
# Show more timestamp ranges per channel
|
|
444
|
+
pymcap-cli diff a.mcap b.mcap --max-ranges 10
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
### `duplicates` — Find Duplicate Recordings
|
|
448
|
+
|
|
449
|
+
Scan files and directories for likely duplicate MCAP recordings using summary
|
|
450
|
+
and message-index fingerprints.
|
|
451
|
+
|
|
452
|
+
```bash
|
|
453
|
+
# Scan a directory tree
|
|
454
|
+
pymcap-cli duplicates /data/recordings
|
|
455
|
+
|
|
456
|
+
# Include singleton groups
|
|
457
|
+
pymcap-cli duplicates /data/recordings --all
|
|
458
|
+
|
|
459
|
+
# Rebuild summaries for files missing them
|
|
460
|
+
pymcap-cli duplicates /data/recordings --rebuild-missing
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
### `records` — Raw Record Dump
|
|
464
|
+
|
|
465
|
+
Print every MCAP record in file order using its `repr`. Useful for inspecting
|
|
466
|
+
raw file structure when debugging readers/writers.
|
|
467
|
+
|
|
468
|
+
```bash
|
|
469
|
+
pymcap-cli records data.mcap
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### `topic-chunks` — Topic/Chunk Layout
|
|
473
|
+
|
|
474
|
+
Show which topics appear in which chunks, sorted by chunk count and percentage
|
|
475
|
+
of total chunks. Helps identify topics that would benefit from `rechunk`.
|
|
476
|
+
|
|
477
|
+
```bash
|
|
478
|
+
pymcap-cli topic-chunks data.mcap
|
|
479
|
+
```
|
|
480
|
+
|
|
346
481
|
### `video` — Video Generation
|
|
347
482
|
|
|
348
483
|
Generate MP4 videos from image topics using hardware-accelerated encoding. Requires the `video` extra.
|
|
@@ -388,6 +523,88 @@ pymcap-cli rosdecompress input.mcap output.mcap --video-format raw
|
|
|
388
523
|
pymcap-cli rosdecompress input.mcap output.mcap --no-pointcloud
|
|
389
524
|
```
|
|
390
525
|
|
|
526
|
+
### `export-images` — Image Files
|
|
527
|
+
|
|
528
|
+
Export image topics to per-topic folders of image files. `CompressedImage`
|
|
529
|
+
payloads keep their original encoding by default (`--format native`); set
|
|
530
|
+
`--format` to a Pillow format (e.g. `jpeg`, `png`, `webp`) to re-encode. Raw
|
|
531
|
+
`Image` messages always use `--raw-format` (default `png`). Requires the
|
|
532
|
+
`image` extra.
|
|
533
|
+
|
|
534
|
+
```bash
|
|
535
|
+
# Native passthrough for CompressedImage; PNG for raw Image
|
|
536
|
+
pymcap-cli export-images data.mcap -o ./images -t /camera/front
|
|
537
|
+
|
|
538
|
+
# Force re-encoding to JPEG for everything
|
|
539
|
+
pymcap-cli export-images data.mcap -o ./images --format jpeg
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
### `export-csv` — CSV Files
|
|
543
|
+
|
|
544
|
+
Export an MCAP file to a directory of CSV files (one per topic). Nested fields
|
|
545
|
+
are flattened with dot notation (`pose.position.x`); arrays remain JSON
|
|
546
|
+
strings to preserve row counts. Schemas with raw media payloads (`Image`,
|
|
547
|
+
`CompressedImage`, …) are skipped unless `--include-blobs` is set.
|
|
548
|
+
|
|
549
|
+
```bash
|
|
550
|
+
pymcap-cli export-csv data.mcap -o ./csv
|
|
551
|
+
pymcap-cli export-csv data.mcap -o ./csv -t /odom -t /imu
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
### `export-json` — NDJSON / Per-Message JSON
|
|
555
|
+
|
|
556
|
+
Export an MCAP file to NDJSON (one line per message) or per-message JSON
|
|
557
|
+
files. Default writes one `<topic>.ndjson` per topic; with `--per-message`
|
|
558
|
+
each topic gets a directory of `<log_time_ns>.json` files — handy for
|
|
559
|
+
downstream tools that expect one record per file.
|
|
560
|
+
|
|
561
|
+
```bash
|
|
562
|
+
# One NDJSON per topic
|
|
563
|
+
pymcap-cli export-json data.mcap -o ./ndjson
|
|
564
|
+
|
|
565
|
+
# One JSON file per message
|
|
566
|
+
pymcap-cli export-json data.mcap -o ./json --per-message
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
### `export-parquet` — Parquet Files
|
|
570
|
+
|
|
571
|
+
Export an MCAP file to a directory of Parquet files (one per topic). Requires
|
|
572
|
+
the `parquet` extra.
|
|
573
|
+
|
|
574
|
+
```bash
|
|
575
|
+
pymcap-cli export-parquet data.mcap -o ./parquet
|
|
576
|
+
pymcap-cli export-parquet data.mcap -o ./parquet --compression snappy
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
### `export-pcd` — Point Cloud Files
|
|
580
|
+
|
|
581
|
+
Export `sensor_msgs/PointCloud2` topics to ASCII PCD v0.7 files
|
|
582
|
+
(`<output>/<safe_topic>/<log_time_ns>.pcd`) — readable by `pcl_viewer`,
|
|
583
|
+
Open3D, and CloudCompare. Requires the `pointcloud` extra.
|
|
584
|
+
|
|
585
|
+
```bash
|
|
586
|
+
pymcap-cli export-pcd data.mcap -o ./pcd
|
|
587
|
+
pymcap-cli export-pcd data.mcap -o ./pcd -t /lidar/points
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
### `export-geo` — Map Formats
|
|
591
|
+
|
|
592
|
+
Export geographic topics (`NavSatFix`, `geographic_msgs/*`) to GeoJSON, KML,
|
|
593
|
+
or GPX. GeoJSON writes one `<topic>.geojson` per topic; KML and GPX produce
|
|
594
|
+
a single `export.{kml,gpx}` covering all topics. Local-frame poses
|
|
595
|
+
(`Odometry`, `geometry_msgs/Pose*`) are out of scope — they need a datum.
|
|
596
|
+
|
|
597
|
+
```bash
|
|
598
|
+
# Default GeoJSON, track + points per topic
|
|
599
|
+
pymcap-cli export-geo data.mcap -o ./geo
|
|
600
|
+
|
|
601
|
+
# GPX track every 5th sample
|
|
602
|
+
pymcap-cli export-geo data.mcap -o ./geo --format gpx --mode track --stride 5
|
|
603
|
+
|
|
604
|
+
# Keep NO_FIX samples too
|
|
605
|
+
pymcap-cli export-geo data.mcap -o ./geo --include-no-fix
|
|
606
|
+
```
|
|
607
|
+
|
|
391
608
|
### Shell Autocompletion
|
|
392
609
|
|
|
393
610
|
```bash
|
|
@@ -27,6 +27,7 @@ uv add pymcap-cli[video]
|
|
|
27
27
|
- **Smart Chunk Copying** — fast chunk copying without decompression when possible, up to 10x faster for filtering operations
|
|
28
28
|
- **Unified Processing** — single `process` command combines recovery + filtering + compression in one optimized pass
|
|
29
29
|
- **Precise Filtering** — regex topic filtering, time range filtering, and content type filtering with deferred schema/channel writing
|
|
30
|
+
- **Broad Format Coverage** — converts ROS 1 `.bag` and ROS 2 `.db3` to MCAP, exports to NDJSON, CSV, Parquet, PCD, GeoJSON/KML/GPX, and image/video files
|
|
30
31
|
- **Rich Terminal Output** — colored topics, Unicode distribution histograms, tree views, and responsive layouts
|
|
31
32
|
- **Robust Error Handling** — graceful degradation with detailed error reporting and recovery statistics
|
|
32
33
|
|
|
@@ -116,6 +117,27 @@ pymcap-cli tftree data.mcap
|
|
|
116
117
|
pymcap-cli tftree data.mcap --static-only
|
|
117
118
|
```
|
|
118
119
|
|
|
120
|
+
### `tf-export` — TF Tree to URDF / SDF / JSON
|
|
121
|
+
|
|
122
|
+
Reconstruct robot description files from `/tf_static` (and optionally `/tf` at a
|
|
123
|
+
snapshot timestamp). Useful when the original `.urdf` is missing — Foxglove
|
|
124
|
+
Studio and rviz can render the static skeleton from the exported file.
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# Write a URDF for the static tree
|
|
128
|
+
pymcap-cli tf-export data.mcap -o robot.urdf
|
|
129
|
+
|
|
130
|
+
# SDF or JSON instead
|
|
131
|
+
pymcap-cli tf-export data.mcap --format sdf -o robot.sdf
|
|
132
|
+
pymcap-cli tf-export data.mcap --format json
|
|
133
|
+
|
|
134
|
+
# Capture a dynamic snapshot from /tf at a given time
|
|
135
|
+
pymcap-cli tf-export data.mcap --include-dynamic-at 2024-01-01T10:00:00Z -o snapshot.urdf
|
|
136
|
+
|
|
137
|
+
# Pick a subtree when the recording has multiple disconnected roots
|
|
138
|
+
pymcap-cli tf-export data.mcap --root base_link -o robot.urdf
|
|
139
|
+
```
|
|
140
|
+
|
|
119
141
|
### `diag` — ROS2 Diagnostics
|
|
120
142
|
|
|
121
143
|
Inspect ROS2 diagnostics with per-component health overview, sparkline timelines, frequency stats, and time-in-state tracking.
|
|
@@ -216,6 +238,9 @@ pymcap-cli merge *.mcap -o all_recordings.mcap --compression lz4
|
|
|
216
238
|
|
|
217
239
|
# Exclude metadata/attachments
|
|
218
240
|
pymcap-cli merge file1.mcap file2.mcap -o merged.mcap --metadata exclude
|
|
241
|
+
|
|
242
|
+
# Drop duplicate messages (same channel, log_time, payload) from overlapping inputs
|
|
243
|
+
pymcap-cli merge a.mcap b.mcap -o merged.mcap --dedup-identical
|
|
219
244
|
```
|
|
220
245
|
|
|
221
246
|
### `convert` — Convert DB3 to MCAP
|
|
@@ -233,6 +258,43 @@ pymcap-cli convert input.db3 -o output.mcap --distro jazzy
|
|
|
233
258
|
pymcap-cli convert input.db3 -o output.mcap --extra-path /path/to/msgs
|
|
234
259
|
```
|
|
235
260
|
|
|
261
|
+
### `bag2mcap` — Convert ROS 1 Bag to MCAP
|
|
262
|
+
|
|
263
|
+
Convert ROS 1 `.bag` files to MCAP using the `ros1` profile. Message bytes are
|
|
264
|
+
preserved as raw ROS 1 serialization and schemas use `ros1msg` encoding with
|
|
265
|
+
the full message definition from the bag.
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
# Basic conversion
|
|
269
|
+
pymcap-cli bag2mcap recording.bag -o recording.mcap
|
|
270
|
+
|
|
271
|
+
# Pick a different compression / chunk size
|
|
272
|
+
pymcap-cli bag2mcap recording.bag -o recording.mcap --compression lz4 --chunk-size 8388608
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### `split` — Split into Segments
|
|
276
|
+
|
|
277
|
+
Split an MCAP file into multiple output segments by duration, explicit
|
|
278
|
+
timestamps, value-change of a message-path expression, or a byte budget per
|
|
279
|
+
segment.
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
# Split every 60 seconds
|
|
283
|
+
pymcap-cli split data.mcap --duration 60s -t "out_{index:03d}.mcap"
|
|
284
|
+
|
|
285
|
+
# Split at specific RFC3339 timestamps
|
|
286
|
+
pymcap-cli split data.mcap --split-at "2024-01-01T10:00:00Z" --split-at "2024-01-01T10:30:00Z"
|
|
287
|
+
|
|
288
|
+
# Start a new segment when /gps/fix.status.status changes value
|
|
289
|
+
pymcap-cli split data.mcap -E "/gps/fix.status.status"
|
|
290
|
+
|
|
291
|
+
# Predicate trigger — split on match/no-match transitions
|
|
292
|
+
pymcap-cli split data.mcap -E "/detections.objects[:]{confidence>0.8}"
|
|
293
|
+
|
|
294
|
+
# Split when each output reaches roughly 1 GB
|
|
295
|
+
pymcap-cli split data.mcap --max-size 1G -t "shard_{index:03d}.mcap"
|
|
296
|
+
```
|
|
297
|
+
|
|
236
298
|
### `rechunk` — Topic-Based Rechunking
|
|
237
299
|
|
|
238
300
|
Reorganize MCAP messages into separate chunk groups based on topic patterns for optimized playback.
|
|
@@ -290,6 +352,73 @@ pymcap-cli list attachments data.mcap
|
|
|
290
352
|
pymcap-cli list metadata data.mcap
|
|
291
353
|
```
|
|
292
354
|
|
|
355
|
+
### `get` — Extract Attachments and Metadata
|
|
356
|
+
|
|
357
|
+
Extract a single attachment's bytes or a metadata record's key/value map.
|
|
358
|
+
|
|
359
|
+
```bash
|
|
360
|
+
# Write attachment bytes to a file (or pipe stdout)
|
|
361
|
+
pymcap-cli get attachment --name calib.bin --output calib.bin data.mcap
|
|
362
|
+
pymcap-cli get attachment -n calib.bin data.mcap > calib.bin
|
|
363
|
+
|
|
364
|
+
# Disambiguate when multiple attachments share a name
|
|
365
|
+
pymcap-cli get attachment --name notes.txt --offset 1234 -o notes.txt data.mcap
|
|
366
|
+
|
|
367
|
+
# Print a metadata record as JSON (records sharing a name are merged)
|
|
368
|
+
pymcap-cli get metadata --name session data.mcap
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### `diff` — Compare Files
|
|
372
|
+
|
|
373
|
+
Compare MCAP files using summary and message-index timestamps. Reads through the
|
|
374
|
+
footer/summary first and falls back to rebuilding metadata from the data section
|
|
375
|
+
when the summary is missing.
|
|
376
|
+
|
|
377
|
+
```bash
|
|
378
|
+
# Compare two recordings
|
|
379
|
+
pymcap-cli diff a.mcap b.mcap
|
|
380
|
+
|
|
381
|
+
# Hide channels with identical timestamps
|
|
382
|
+
pymcap-cli diff a.mcap b.mcap --skip-identical
|
|
383
|
+
|
|
384
|
+
# Show more timestamp ranges per channel
|
|
385
|
+
pymcap-cli diff a.mcap b.mcap --max-ranges 10
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
### `duplicates` — Find Duplicate Recordings
|
|
389
|
+
|
|
390
|
+
Scan files and directories for likely duplicate MCAP recordings using summary
|
|
391
|
+
and message-index fingerprints.
|
|
392
|
+
|
|
393
|
+
```bash
|
|
394
|
+
# Scan a directory tree
|
|
395
|
+
pymcap-cli duplicates /data/recordings
|
|
396
|
+
|
|
397
|
+
# Include singleton groups
|
|
398
|
+
pymcap-cli duplicates /data/recordings --all
|
|
399
|
+
|
|
400
|
+
# Rebuild summaries for files missing them
|
|
401
|
+
pymcap-cli duplicates /data/recordings --rebuild-missing
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### `records` — Raw Record Dump
|
|
405
|
+
|
|
406
|
+
Print every MCAP record in file order using its `repr`. Useful for inspecting
|
|
407
|
+
raw file structure when debugging readers/writers.
|
|
408
|
+
|
|
409
|
+
```bash
|
|
410
|
+
pymcap-cli records data.mcap
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
### `topic-chunks` — Topic/Chunk Layout
|
|
414
|
+
|
|
415
|
+
Show which topics appear in which chunks, sorted by chunk count and percentage
|
|
416
|
+
of total chunks. Helps identify topics that would benefit from `rechunk`.
|
|
417
|
+
|
|
418
|
+
```bash
|
|
419
|
+
pymcap-cli topic-chunks data.mcap
|
|
420
|
+
```
|
|
421
|
+
|
|
293
422
|
### `video` — Video Generation
|
|
294
423
|
|
|
295
424
|
Generate MP4 videos from image topics using hardware-accelerated encoding. Requires the `video` extra.
|
|
@@ -335,6 +464,88 @@ pymcap-cli rosdecompress input.mcap output.mcap --video-format raw
|
|
|
335
464
|
pymcap-cli rosdecompress input.mcap output.mcap --no-pointcloud
|
|
336
465
|
```
|
|
337
466
|
|
|
467
|
+
### `export-images` — Image Files
|
|
468
|
+
|
|
469
|
+
Export image topics to per-topic folders of image files. `CompressedImage`
|
|
470
|
+
payloads keep their original encoding by default (`--format native`); set
|
|
471
|
+
`--format` to a Pillow format (e.g. `jpeg`, `png`, `webp`) to re-encode. Raw
|
|
472
|
+
`Image` messages always use `--raw-format` (default `png`). Requires the
|
|
473
|
+
`image` extra.
|
|
474
|
+
|
|
475
|
+
```bash
|
|
476
|
+
# Native passthrough for CompressedImage; PNG for raw Image
|
|
477
|
+
pymcap-cli export-images data.mcap -o ./images -t /camera/front
|
|
478
|
+
|
|
479
|
+
# Force re-encoding to JPEG for everything
|
|
480
|
+
pymcap-cli export-images data.mcap -o ./images --format jpeg
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
### `export-csv` — CSV Files
|
|
484
|
+
|
|
485
|
+
Export an MCAP file to a directory of CSV files (one per topic). Nested fields
|
|
486
|
+
are flattened with dot notation (`pose.position.x`); arrays remain JSON
|
|
487
|
+
strings to preserve row counts. Schemas with raw media payloads (`Image`,
|
|
488
|
+
`CompressedImage`, …) are skipped unless `--include-blobs` is set.
|
|
489
|
+
|
|
490
|
+
```bash
|
|
491
|
+
pymcap-cli export-csv data.mcap -o ./csv
|
|
492
|
+
pymcap-cli export-csv data.mcap -o ./csv -t /odom -t /imu
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
### `export-json` — NDJSON / Per-Message JSON
|
|
496
|
+
|
|
497
|
+
Export an MCAP file to NDJSON (one line per message) or per-message JSON
|
|
498
|
+
files. Default writes one `<topic>.ndjson` per topic; with `--per-message`
|
|
499
|
+
each topic gets a directory of `<log_time_ns>.json` files — handy for
|
|
500
|
+
downstream tools that expect one record per file.
|
|
501
|
+
|
|
502
|
+
```bash
|
|
503
|
+
# One NDJSON per topic
|
|
504
|
+
pymcap-cli export-json data.mcap -o ./ndjson
|
|
505
|
+
|
|
506
|
+
# One JSON file per message
|
|
507
|
+
pymcap-cli export-json data.mcap -o ./json --per-message
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
### `export-parquet` — Parquet Files
|
|
511
|
+
|
|
512
|
+
Export an MCAP file to a directory of Parquet files (one per topic). Requires
|
|
513
|
+
the `parquet` extra.
|
|
514
|
+
|
|
515
|
+
```bash
|
|
516
|
+
pymcap-cli export-parquet data.mcap -o ./parquet
|
|
517
|
+
pymcap-cli export-parquet data.mcap -o ./parquet --compression snappy
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
### `export-pcd` — Point Cloud Files
|
|
521
|
+
|
|
522
|
+
Export `sensor_msgs/PointCloud2` topics to ASCII PCD v0.7 files
|
|
523
|
+
(`<output>/<safe_topic>/<log_time_ns>.pcd`) — readable by `pcl_viewer`,
|
|
524
|
+
Open3D, and CloudCompare. Requires the `pointcloud` extra.
|
|
525
|
+
|
|
526
|
+
```bash
|
|
527
|
+
pymcap-cli export-pcd data.mcap -o ./pcd
|
|
528
|
+
pymcap-cli export-pcd data.mcap -o ./pcd -t /lidar/points
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
### `export-geo` — Map Formats
|
|
532
|
+
|
|
533
|
+
Export geographic topics (`NavSatFix`, `geographic_msgs/*`) to GeoJSON, KML,
|
|
534
|
+
or GPX. GeoJSON writes one `<topic>.geojson` per topic; KML and GPX produce
|
|
535
|
+
a single `export.{kml,gpx}` covering all topics. Local-frame poses
|
|
536
|
+
(`Odometry`, `geometry_msgs/Pose*`) are out of scope — they need a datum.
|
|
537
|
+
|
|
538
|
+
```bash
|
|
539
|
+
# Default GeoJSON, track + points per topic
|
|
540
|
+
pymcap-cli export-geo data.mcap -o ./geo
|
|
541
|
+
|
|
542
|
+
# GPX track every 5th sample
|
|
543
|
+
pymcap-cli export-geo data.mcap -o ./geo --format gpx --mode track --stride 5
|
|
544
|
+
|
|
545
|
+
# Keep NO_FIX samples too
|
|
546
|
+
pymcap-cli export-geo data.mcap -o ./geo --include-no-fix
|
|
547
|
+
```
|
|
548
|
+
|
|
338
549
|
### Shell Autocompletion
|
|
339
550
|
|
|
340
551
|
```bash
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "pymcap-cli"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.10.0"
|
|
4
4
|
description = "High-performance Python CLI for MCAP file processing with advanced recovery, filtering, and optimization capabilities"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
@@ -28,6 +28,7 @@ classifiers = [
|
|
|
28
28
|
"Programming Language :: Python :: 3.11",
|
|
29
29
|
"Programming Language :: Python :: 3.12",
|
|
30
30
|
"Programming Language :: Python :: 3.13",
|
|
31
|
+
"Programming Language :: Python :: 3.14",
|
|
31
32
|
"Topic :: Scientific/Engineering",
|
|
32
33
|
"Topic :: System :: Archiving",
|
|
33
34
|
"Topic :: Utilities",
|
|
@@ -36,7 +37,6 @@ classifiers = [
|
|
|
36
37
|
dependencies = [
|
|
37
38
|
"rich>=14.1.0",
|
|
38
39
|
"small-mcap[compression]",
|
|
39
|
-
"mcap-codec-support[ros2]",
|
|
40
40
|
"mcap-ros2-support-fast",
|
|
41
41
|
"cyclopts>=4",
|
|
42
42
|
"ros-parser",
|
|
@@ -45,22 +45,23 @@ dependencies = [
|
|
|
45
45
|
"typing-extensions>=4.15.0",
|
|
46
46
|
]
|
|
47
47
|
|
|
48
|
+
[project.optional-dependencies]
|
|
49
|
+
all = ["pymcap-cli[video,pointcloud,plot,parquet,image,draco,bridge,xxhash]"]
|
|
50
|
+
lite = ["pymcap-cli[image,draco,bridge,xxhash]"]
|
|
51
|
+
bridge = ["robo-ws-bridge"]
|
|
52
|
+
draco = ["mcap-codec-support[draco]"]
|
|
53
|
+
image = ["pillow>=10.0"]
|
|
54
|
+
parquet = ["pyarrow>=15.0.0", "numpy>=1.24.0", "mcap-codec-support[pointcloud]"]
|
|
55
|
+
plot = ["plotly>=6.0.0"]
|
|
56
|
+
pointcloud = ["mcap-codec-support[pointcloud]"]
|
|
57
|
+
video = ["mcap-codec-support[video]"]
|
|
58
|
+
xxhash = ["xxhash>=3.0.0"]
|
|
59
|
+
|
|
60
|
+
|
|
48
61
|
[project.urls]
|
|
49
62
|
Homepage = "https://github.com/mrkbac/robotic-tools"
|
|
50
63
|
Repository = "https://github.com/mrkbac/robotic-tools"
|
|
51
64
|
Issues = "https://github.com/mrkbac/robotic-tools/issues"
|
|
52
|
-
|
|
53
|
-
[project.optional-dependencies]
|
|
54
|
-
video = ["mcap-codec-support[video]"]
|
|
55
|
-
pointcloud = ["mcap-codec-support[pointcloud]"]
|
|
56
|
-
plot = ["plotly>=6.0.0"]
|
|
57
|
-
parquet = ["pyarrow>=15.0.0", "numpy>=1.24.0", "mcap-codec-support[pointcloud]"]
|
|
58
|
-
image = ["mcap-codec-support[image]"]
|
|
59
|
-
all = ["pymcap-cli[video,pointcloud,plot,parquet,image,draco]"]
|
|
60
|
-
draco = [
|
|
61
|
-
"mcap-codec-support[draco]",
|
|
62
|
-
]
|
|
63
|
-
|
|
64
65
|
[build-system]
|
|
65
66
|
requires = ["uv_build>=0.8.9,<0.9.0"]
|
|
66
67
|
build-backend = "uv_build"
|
|
@@ -76,3 +77,4 @@ ros-parser = { workspace = true }
|
|
|
76
77
|
pureini = { workspace = true }
|
|
77
78
|
pointcloud2 = { workspace = true }
|
|
78
79
|
mcap-codec-support = { workspace = true }
|
|
80
|
+
robo-ws-bridge = { workspace = true }
|