Name | ros2-unbag JSON |
Version |
1.0.4
JSON |
| download |
home_page | None |
Summary | A ROS 2 tool for exporting bags to human readable files. Supports pluggable export routines to handle any message type. |
upload_time | 2025-08-07 18:36:54 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.8 |
license | MIT License
Copyright (c) 2025 Institute for Automotive Engineering (ika), RWTH Aachen University
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. |
keywords |
ros2
rosbag
robotics
perception
ros2-export
|
VCS |
 |
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
<img src="ros2_unbag/ui/assets/badge.svg" height=130 align="right">
# *ros2 unbag* - fast ROS 2 bag export for any format
<p align="center">
<img src="https://img.shields.io/github/license/ika-rwth-aachen/ros2_unbag"/>
<a href="https://github.com/ika-rwth-aachen/ros2_unbag/actions/workflows/build_docker.yml"><img src="https://github.com/ika-rwth-aachen/ros2_unbag/actions/workflows/build_docker.yml/badge.svg"/></a>
<a href="https://pypi.org/project/ros2-unbag/"><img src="https://img.shields.io/pypi/v/ros2-unbag?label=PyPI"/></a>
</p>
*ros2 unbag* is a ROS 2 CLI plugin with optional GUI for extracting selected topics from `.db3` or `.mcap` bag files into formats like CSV, JSON, PCD, images, and more.
It comes with export routines for [all message types](#export-routines) (sensor data, point clouds, images). You need a special file format or message type? Add your [own export plugin](#custom-export-routines) for any ROS 2 message or format, and chain custom processors to filter, transform or enrich messages (e.g. drop fields, compute derived values, remap frames).
Optional resampling synchronizes your data streams around a chosen master topic—aligning each other topic either to its last‑known sample (“last”) or to the temporally closest sample (“nearest”)—so you get a consistent sample count in your exports.
For high‑throughput workflows, *ros2 unbag* can spawn multiple worker processes and lets you tune CPU usage. Your topic selections, processor chains, export parameters and resampling mode (last or nearest) can be saved to and loaded from a JSON configuration, ensuring reproducibility across runs.
Use it as `ros2 unbag <args>` or in the GUI for a flexible, extensible way to turn bag files into the data you need.
## Table of Contents
- [Features](#features)
- [Installation](#installation)
- [Prerequisites](#prerequisites)
- [From PyPI (via pip)](#from-pypi-via-pip)
- [From Source](#from-source)
- [Docker](#docker)
- [Quick Start](#quick-start)
- [GUI Mode](#gui-mode)
- [CLI Mode](#cli-mode)
- [Config File](#config-file)
- [Export Routines](#export-routines)
- [Custom Export Routines](#custom-export-routines)
- [Processors](#processors)
- [Resampling](#resampling)
- [last](#last)
- [nearest](#nearest)
- [CPU Utilization](#cpu-utilization)
- [Acknowledgements](#acknowledgements)
## Features
- **Integrated ROS 2 CLI plugin**: `ros2 unbag <args>`
- **GUI interface** for interactive export
- **Pluggable export routines** enable export of any message to any type
- **Custom processors** to filter, transform or enrich messages
- **Time‐aligned resampling** (`last` | `nearest`)
- **Multi‐process** export with adjustable CPU usage
- **JSON config** saving/loading for repeatable workflows
## Installation
### Prerequisites
Make sure you have a working ROS 2 installation (e.g., Humble, Iron, Jazzy, or newer) and that your environment is sourced:
```bash
source /opt/ros/<distro>/setup.bash
```
Replace `<distro>` with your ROS 2 distribution.
Install the required apt dependencies:
```bash
sudo apt update
sudo apt install libxcb-cursor0 libxcb-shape0 libxcb-icccm4 libxcb-keysyms1 libxkbcommon-x11-0
```
### From PyPI (via pip)
```bash
pip install ros2-unbag
```
### From source
```bash
git clone https://github.com/ika-rwth-aachen/ros2_unbag.git
cd ros2_unbag
pip install .
```
### Docker
You can skip local installs by running our ready‑to‑go Docker image:
```bash
docker pull ghcr.io/ika-rwth-aachen/ros2_unbag:latest
```
This image comes with ROS 2 Jazzy and *ros2 unbag* preinstalled. To launch it:
1. Clone or download the `docker/docker-compose.yml` in this repo.
2. Run:
```bash
docker-compose -f docker/docker-compose.yml up
```
3. If you need the GUI, first enable X11 forwarding on your host (at your own risk!):
```bash
xhost +local:
```
Then start the container as above—the GUI will appear on your desktop.
## Quick Start
You can use the tool either via a graphical user interface (GUI) or a command-line interface (CLI).
### GUI Mode
Launch the interactive interface:
```bash
ros2 unbag
```
Then follow the on‑screen prompts to pick your bag file, select topics, and choose export settings.
### CLI Mode
Run the CLI tool by calling *ros2 unbag* with a path to a rosbag and an export config, consisting of one or more topic:format:[subdirectory] combinations:
```bash
ros2 unbag <path_to_rosbag> --export </topic:format[:subdir]>…
```
Alternatively you can load a config file. In this case you do not need any `--export` flag:
```bash
ros2 unbag <path_to_rosbag> --config <config.json>
```
the structure of config files is described in [here](#config-file).
In addition to these required flags, there are some optional flags. See the table below, for all possible flags:
| Flag | Value/Format | Description | Usage | Default |
| --------------------------- | ---------------------------------------- | --------------------------------------------------------------------------------------------------------- | ---------------------------------- | -------------- |
| **`bag`** | `<path>` | Path to ROS 2 bag file (`.db3` or `.mcap`). | CLI mode (required) | – |
| **`-e, --export`** | `/topic:format[:subdir]` | Topic → format export spec. Repeatable. | CLI mode (required or `--config`) | – |
| **`-o, --output-dir`** | `<directory>` | Base directory for all exports. | Optional | `.` |
| **`--naming`** | `<pattern>` | Filename pattern. Supports `%name`, `%index` and strftime (e.g. `%Y-%m-%d_%H-%M-%S`) - uses ROS timestamp | Optional | `%name_%index` |
| **`--resample`** | `/master:association[,discard_eps]`. | Time‑align to master topic. `association` = `last` or `nearest`; `nearest` needs a numeric `discard_eps`. | Optional | – |
| **`-p, --processing`** | `/topic:processor[:arg1=val1,…]` | Pre‑export processor spec. Repeatable. | Optional | – |
| **`--cpu-percentage`** | `<float>` | % of cores for parallel export (0–100). Use `0` for single‑threaded. | Optional | `80.0` |
| **`--config`** | `<config.json>` | JSON config file path. Overrides all other args (except `bag`). | Optional | – |
| **`--gui`** | (flag) | Launch Qt GUI. If no `bag`/`--export`/`--config`, GUI is auto‑started. | Optional | `false` |
| **`--use-routine`** | `<file.py>` | Load a routine for this run only (no install). | Optional | – |
| **`--use-processor`** | `<file.py>` | Load a processor for this run only (no install). | Optional | – |
| **`--install-routine`** | `<file.py>` | Copy & register custom export routine. | Standalone | – |
| **`--install-processor`** | `<file.py>` | Copy & register custom processor. | Standalone | – |
| **`--uninstall-routine`** | (flag) | Interactive removal of an installed routine. | Standalone | - |
| **`--uninstall-processor`** | (flag) | Interactive removal of an installed processor. | Standalone | - |
| **`--help`** | (flag) | Show usage information and exit. | Standalone | - |
Example:
```bash
ros2 unbag rosbag/rosbag.mcap
--output-dir /docker-ros/ws/example/ --export /lidar/point_cloud:pointcloud/pcd:lidar --export /radar/point_cloud:pointcloud/pcd:radar --resample /lidar/point_cloud:last,0.2
```
⚠️ If you specify the `--config` option (e.g., `--config configs/my_config.json`), the tool will load all export settings from the given JSON configuration file. In this case, all other command-line options except `<path_to_rosbag>` are ignored, and the export process is fully controlled by the config file. The `<path_to_rosbag>` is always required in CLI use.
## Config File
When using ros2 unbag, you can define your export settings in a JSON configuration file. This works in the GUI, as well as in the CLI version. It allows you to easily reuse your export settings without having to specify them on the command line every time.
💡 Tip: Use the GUI to create your export settings and then save them via the "Save Config" button. This will create a JSON file with all your export settings, which you can then use in the CLI version.
```jsonc
{
"/imu/pos": {
"format": "text/json@single_file",
"path": "/docker-ros/data/rosbag2_2025_08_19-12_34_56",
"subfolder": "%name",
"naming": "%name"
},
"/drivers/lidar_fl/nearir_image": {
"format": "image/png",
"path": "/docker-ros/data/rosbag2_2025_08_19-12_34_56",
"subfolder": "%name",
"naming": "%name_%index"
},
"/drivers/lidar_fl/pointcloud": {
"format": "pointcloud/pcd",
"path": "/docker-ros/data/rosbag2_2025_08_19-12_34_56",
"subfolder": "%name",
"naming": "%name_%index",
"processor": "transform_from_yaml",
"processor_args": {
"custom_frame_path": "test.yml"
}
},
"__global__": {
"cpu_percentage": 85.0,
"resample_config": {
"master_topic": "/drivers/lidar_fl/pointcloud",
"association": "nearest",
"discard_eps": 0.5
}
}
}
```
## Export Routines
Export routines define the way how messages are exported from the ros2 bag file to the desired output format. The tool comes with a set of predefined routines for **all** message types and formats, such as:
| Identifier(s) | Topic(s) | Description |
| ------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| **image/png** | `sensor_msgs/msg/Image`<br> `sensor_msgs/msg/CompressedImage` | Exports images via openCV to PNG. |
| **image/jpeg** | `sensor_msgs/msg/Image`<br> `sensor_msgs/msg/CompressedImage` | Exports images via openCV to JPEG. |
| **video/mp4** | `sensor_msgs/msg/Image`<br> `sensor_msgs/msg/CompressedImage` | Exports image sequences via openCV to MP4. |
| **video/avi** | `sensor_msgs/msg/Image`<br> `sensor_msgs/msg/CompressedImage` | Exports image sequences via openCV to AVI. |
| **pointcloud/pkl** | `sensor_msgs/msg/PointCloud2` | Serializes the entire `PointCloud2` message object using Python’s `pickle`, producing a `.pkl` file. |
| **pointcloud/xyz** | `sensor_msgs/msg/PointCloud2` | Unpacks each point’s x, y, z floats from the binary buffer and writes one `x y z` line per point into a plain `.xyz` text file. |
| **pointcloud/pcd** | `sensor_msgs/msg/PointCloud2` | Constructs a PCD v0.7 file and writes binary point data* in PCD format to a `.pcd` file. |
| **pointcloud/pcd_compressed** | `sensor_msgs/msg/PointCloud2` | Constructs a PCD v0.7 file and writes compressed binary point data* in PCD format to a `.pcd` file. |
| **pointcloud/pcd_ascii** | `sensor_msgs/msg/PointCloud2` | Constructs a PCD v0.7 file and writes ASCII point data* in PCD format to a `.pcd` file. |
***Note:** Point data in PCD files is written with all fields, that are present in the `PointCloud2` message. Some programs do not support arbitrary fields in PCD files. If you need to export only specific fields, you can use the `remove_fields` processor to drop unwanted fields before exporting. See the [Processors](#processors) section for more information.*
In addition to these specialized routines, there are also generic routines for exporting any message type to common formats. These are available as `@single_file` and `@multi_file` variants, which determine whether all messages are written to a single file or each message is written to its own file:
| Identifier | Topic(s) | `@single_file` Description | `@multi_file` Description |
| ------------- | -------------------- | ------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| **table/csv** | *any message type* | Flattens fields, writes header + one row per message into a single `.csv` file. | Flattens fields, writes header + one message per file into separate `.csv` files. |
| **text/json** | *any message type* | All messages in one `.json` file as a list of objects. | One `.json` file per message. |
| **text/yaml** | *any message type* | One `.yaml` document containing all messages in a single `.yaml` file. | One `.yaml` document per message. |
You can call these as `table/csv@single_file` or `table/csv@multi_file`.
### Custom Export Routines
Your message type or output format is not supported by default? No problem! You can add your own export routines to handle custom message types or output formats.
Routines are defined like this:
```python
from pathlib import Path # import Path from pathlib for file path handling
from ros2_unbag.core.routines.base import ExportRoutine # import the base class
# you can also import other packages here - e.g., numpy, cv2, etc.
@ExportRoutine("sensor_msgs/msg/PointCloud2", ["pointcloud/xyz"], mode=ExportMode.MULTI_FILE)
def export_pointcloud_xyz(msg, path: Path, fmt: str, metadata: ExportMetadata): # define the export routine function, the name of the function does not matter
"""
Export PointCloud2 message as an XYZ text file by unpacking x, y, z floats from each point and writing lines.
Args:
msg: PointCloud2 message instance.
path: Output file path (without extension).
fmt: Export format string (default "pointcloud/xyz").
metadata: Export metadata including message index and max index.
Returns:
None
"""
with open(path + ".xyz", 'w') as f: # define your custom logic to export the message
for i in range(0, len(msg.data), msg.point_step):
x, y, z = struct.unpack_from("fff", msg.data, offset=i)
f.write(f"{x} {y} {z}\n")
```
A template for this, including single file handling is available in the `templates` directory of the repository. You can copy it and modify it to suit your needs.
The message type, format and mode are defined in the decorator. The `ExportRoutine` decorator registers the function as an export routine for the specified message type and format. It has the following attributes:
- `msg_types`: The message types that this routine can handle. (Can be a single type or a list of types.) Note that the message type must be installed in the system, i.e., it must be available in the ROS 2 environment.
- `formats`: The output formats that this routine supports. (Can be a single format or a list of formats.)
- `mode`: Specifies the export mode — SINGLE_FILE or MULTI_FILE. This determines whether the routine is designed for exporting data into a single file or multiple files. While this setting affects parallelization and naming conventions, you must implement the logic for single file exports yourself if you choose SINGLE_FILE mode (e.g., appending data to the same file during each function call).
You can import your own routines permanently by calling
```bash
ros2 unbag --install-routine <path_to_your_routine_file>
```
or use them only temporarily by specifying the `--use-routine` option when starting the program. This works in both the GUI and CLI versions.
```bash
ros2 unbag --use-routine <path_to_your_routine_file>
```
If you installed a routine and do not want it anymore, you can delete it by calling
```bash
ros2 unbag --uninstall-routine
```
You’ll be prompted to pick which routine to uninstall.
⚠️ Never use or install new routines that you did not write yourself or that you do not trust. The code gets ingested and executed in the context of the *ros2 unbag* process, which means it can access all data and resources available to the process. This includes reading and writing files, accessing network resources, and more. Always review the code of any routine you use or install.
## Processors
Processors are used to modify messages before they are exported. They can be applied to specific topics and allow you to perform operations such as filtering, transforming, or enriching the data.
The following processors are available by default:
| Identifier(s) | Topic(s) | Arguments | Description |
| ---------------------- | ------------------------------------------------------------------- | -------------------------------------------------------------- | ------------------------------------------ |
| **field_mapping** | `sensor_msgs/msg/PointCloud2` | `field_mapping` String in the form `old_field:new_field, ...` | Remaps fields in a PointCloud2 message. |
| **remove_fields** | `sensor_msgs/msg/PointCloud2` | `fields_to_remove` List of field names to remove `field1, ...` | Removes specified fields from PointCloud2. |
| **transform_from_yaml**| `sensor_msgs/msg/PointCloud2` | `custom_frame_path` Path to a YAML file with custom frame data | Transforms PointCloud2 to a custom frame. |
| **apply_color_map** | `sensor_msgs/msg/Image` <br> `sensor_msgs/msg/CompressedImage` | `color_map` Integer specifying cv2 colormap index*. | Applies a color map to an image. |
*Note: The `color_map` argument is an integer that specifies the OpenCV colormap index. You can find a list of available colormaps in the [OpenCV documentation](https://docs.opencv.org/4.x/d3/d50/group__imgproc__colormap.html).*
### Custom Processors
You can define your own processors like this:
```python
# Import the processor decorator
from ros2_unbag.core.processors.base import Processor
# Define the processor class with the appropriate message types and give it a name
@Processor(["std_msgs/msg/String"], ["your_processor_name"])
def your_processor_name(msg, your_parameter: str = "default", your_parameter_2: str = "template"):
"""
Short description of what the processor does.
Args:
msg: The ROS message you want to process.
your_parameter: Describe the parameter. This will be shown in the UI.
your_parameter_2: You can add more parameters as needed.
Returns:
The return always needs to match the incoming message type.
"""
# Validate and convert parameter
try:
your_parameter = str(your_parameter)
your_parameter_2 = str(your_parameter_2)
except ValueError:
raise ValueError(f"One of the parameters is not valid: {your_parameter}, {your_parameter_2}")
# Decode ROS message if necessary
string_msg = msg.data # Assuming msg is a String message
# --- Apply your processing here ---
processed_msg = string_msg.replace(your_parameter, your_parameter_2)
# Re-encode the image
msg.data = processed_msg
return msg
```
A template for this is available in the `templates` directory of the repository. You can copy it and modify it to suit your needs.
The message type and processor name are defined in the decorator. The `Processor` decorator registers the function as a processor for the specified message type and name. It has the following attributes:
- `msg_types`: The message types that this processor can handle. (Can be a single type or a list of types.) Note that the message type must be installed in the system, i.e., it must be available in the ROS 2 environment.
- `name`: The name of the processor, which is used to identify it in the system.
You can import your own processors by calling
```bash
ros2 unbag --install-processor <path_to_your_processor_file>
```
or use them only temporarily by specifying the `--use-processor` option when starting the program. This works in both the GUI and CLI versions.
```bash
ros2 unbag --use-processor <path_to_your_processor_file>
```
If you installed a processor and do not want it anymore, you can delete it by calling
```bash
ros2 unbag --uninstall-processor
```
You’ll be prompted to pick which processor to uninstall.
⚠️ Never use or install new processes that you did not write yourself or that you do not trust. The code gets ingested and executed in the context of the *ros2 unbag* process, which means it can access all data and resources available to the process. This includes reading and writing files, accessing network resources, and more. Always review the code of any routine you use or install.
## Resampling
In many cases, you may want to resample messages in the frequency of a master topic. This allows you to assemble a "frame" of data that is temporally aligned with a specific topic, such as a camera or LIDAR sensor. The resampling process will ensure that the messages from other topics are exported in sync with the master topic's timestamps.
ros2 unbag supports resampling of messages based on a master topic. You can specify the master topic and the resampling type (e.g., `last` or `nearest`) along with an optional discard epsilon value.
### Last
The `last` resampling type will listen for the master topic. As soon as a message of the master topic is received, a frame will be assembled, containing the last message of any other selected topics. With an optional `discard_eps` value, you can specify a maximum time difference between the master topic message and the other topics' messages. If no message is found within the `discard_eps` value, the whole frame is discarded.
### Nearest
The `nearest` resampling type will listen for the master topic and export it along with the (temporally) nearest message of the other topics that were published in the time range of the master topic message. This resampling strategy is only usable with an `discard_eps` value, which defines the maximum time difference between the master topic message and the other topics' messages. If no message is found within the `discard_eps` value, the whole frame is discarded.
## CPU utilization
*ros2 unbag* uses multi-processing to export messages in parallel. By default, full parallelization is applied only when exporting to multiple files. For single-file outputs, it uses one process per file to ensure deterministic ordering, which still utilizes multi-processing but with limited concurrency. You can control the number of processes by setting the --cpu-percentage option. The default value is 80%, meaning the tool will use 80% of available CPU cores for processing. Adjust this value to control CPU utilization during export.
## Acknowledgements
This research is accomplished within the following research projects:
| Project | Funding Source | |
|---------|----------------|:----:|
| <a href="https://www.ika.rwth-aachen.de/de/kompetenzen/projekte/automatisiertes-fahren/4-cad.html"><img src="https://www.ika.rwth-aachen.de/images/projekte/4cad/4cad-logo.svg" alt="4-CAD" height="40"/></a> | Funded by the Deutsche Forschungsgemeinschaft (DFG, German Research Foundation) DFG Proj. Nr. 503852364 | <p align="center"><img src="https://www.ika.rwth-aachen.de/images/foerderer/dfg.svg" height="50"/></p> |
| <a href="https://iexoddus-project.eu/"><img src="https://www.ika.rwth-aachen.de/images/projekte/iexoddus/iEXODDUS%20Logo%20color.svg" alt="iEXXODUS" height="40"/></a> | Funded by the European Union’s Horizon Europe Research and Innovation Programme under Grant Agreement No 101146091 | <p align="center"><img src="https://www.ika.rwth-aachen.de/images/foerderer/eu.svg" height="50"/></p> |
| <a href="https://synergies-ccam.eu/"><img src="https://www.ika.rwth-aachen.de/images/projekte/synergies/SYNERGIES_Logo%201.png" alt="SYNERGIES" height="40"/></a> | Funded by the European Union’s Horizon Europe Research and Innovation Programme under Grant Agreement No 101146542 | <p align="center"><img src="https://www.ika.rwth-aachen.de/images/foerderer/eu.svg" height="50"/></p> |
## Notice
> [!IMPORTANT]
> This repository is open-sourced and maintained by the [**Institute for Automotive Engineering (ika) at RWTH Aachen University**](https://www.ika.rwth-aachen.de/).
> We cover a wide variety of research topics within our [*Vehicle Intelligence & Automated Driving*](https://www.ika.rwth-aachen.de/en/competences/fields-of-research/vehicle-intelligence-automated-driving.html) domain.
> If you would like to learn more about how we can support your automated driving or robotics efforts, feel free to reach out to us!
> :email: ***opensource@ika.rwth-aachen.de***
Raw data
{
"_id": null,
"home_page": null,
"name": "ros2-unbag",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": "Lukas Ostendorf <lukas.ostendorf@ika.rwth-aachen.de>",
"keywords": "ros2, rosbag, robotics, perception, ros2-export",
"author": null,
"author_email": "Lukas Ostendorf <lukas.ostendorf@ika.rwth-aachen.de>",
"download_url": "https://files.pythonhosted.org/packages/07/97/375011164c523fa9828e8bb8180c9a128805d3a389d9c5ffb58fce6af1fc/ros2_unbag-1.0.4.tar.gz",
"platform": null,
"description": "<img src=\"ros2_unbag/ui/assets/badge.svg\" height=130 align=\"right\">\n\n# *ros2 unbag* - fast ROS 2 bag export for any format\n\n<p align=\"center\">\n <img src=\"https://img.shields.io/github/license/ika-rwth-aachen/ros2_unbag\"/>\n <a href=\"https://github.com/ika-rwth-aachen/ros2_unbag/actions/workflows/build_docker.yml\"><img src=\"https://github.com/ika-rwth-aachen/ros2_unbag/actions/workflows/build_docker.yml/badge.svg\"/></a>\n <a href=\"https://pypi.org/project/ros2-unbag/\"><img src=\"https://img.shields.io/pypi/v/ros2-unbag?label=PyPI\"/></a>\n</p>\n\n*ros2 unbag* is a ROS\u202f2 CLI plugin with optional GUI for extracting selected topics from `.db3` or `.mcap` bag files into formats like CSV, JSON, PCD, images, and more.\n\nIt comes with export routines for [all message types](#export-routines) (sensor data, point clouds, images). You need a special file format or message type? Add your [own export plugin](#custom-export-routines) for any ROS\u202f2 message or format, and chain custom processors to filter, transform or enrich messages (e.g. drop fields, compute derived values, remap frames).\n\nOptional resampling synchronizes your data streams around a chosen master topic\u2014aligning each other topic either to its last\u2011known sample (\u201clast\u201d) or to the temporally closest sample (\u201cnearest\u201d)\u2014so you get a consistent sample count in your exports.\n\nFor high\u2011throughput workflows, *ros2 unbag* can spawn multiple worker processes and lets you tune CPU usage. Your topic selections, processor chains, export parameters and resampling mode (last or nearest) can be saved to and loaded from a JSON configuration, ensuring reproducibility across runs.\n\nUse it as `ros2 unbag <args>` or in the GUI for a flexible, extensible way to turn bag files into the data you need.\n\n## Table of Contents\n\n- [Features](#features) \n- [Installation](#installation) \n - [Prerequisites](#prerequisites) \n - [From PyPI (via pip)](#from-pypi-via-pip) \n - [From Source](#from-source) \n - [Docker](#docker) \n- [Quick Start](#quick-start) \n - [GUI Mode](#gui-mode) \n - [CLI Mode](#cli-mode) \n- [Config File](#config-file) \n- [Export Routines](#export-routines)\n - [Custom Export Routines](#custom-export-routines)\n- [Processors](#processors) \n- [Resampling](#resampling) \n - [last](#last) \n - [nearest](#nearest) \n- [CPU Utilization](#cpu-utilization) \n- [Acknowledgements](#acknowledgements)\n\n## Features\n\n- **Integrated ROS 2 CLI plugin**: `ros2 unbag <args>` \n- **GUI interface** for interactive export \n- **Pluggable export routines** enable export of any message to any type \n- **Custom processors** to filter, transform or enrich messages \n- **Time\u2010aligned resampling** (`last`\u00a0|\u00a0`nearest`) \n- **Multi\u2010process** export with adjustable CPU usage \n- **JSON config** saving/loading for repeatable workflows \n\n## Installation \n\n### Prerequisites\n\nMake sure you have a working ROS 2 installation (e.g., Humble, Iron, Jazzy, or newer) and that your environment is sourced:\n\n```bash\nsource /opt/ros/<distro>/setup.bash\n```\n\nReplace `<distro>` with your ROS 2 distribution.\n\nInstall the required apt dependencies:\n\n```bash\nsudo apt update\nsudo apt install libxcb-cursor0 libxcb-shape0 libxcb-icccm4 libxcb-keysyms1 libxkbcommon-x11-0\n```\n\n### From PyPI (via pip)\n\n```bash\npip install ros2-unbag\n```\n\n### From source\n\n```bash\ngit clone https://github.com/ika-rwth-aachen/ros2_unbag.git\ncd ros2_unbag\npip install .\n```\n\n### Docker \n\nYou can skip local installs by running our ready\u2011to\u2011go Docker image:\n\n```bash\ndocker pull ghcr.io/ika-rwth-aachen/ros2_unbag:latest\n```\n\nThis image comes with ROS\u00a02\u00a0Jazzy and *ros2 unbag* preinstalled. To launch it:\n\n1. Clone or download the `docker/docker-compose.yml` in this repo.\n2. Run:\n\n ```bash\n docker-compose -f docker/docker-compose.yml up\n ```\n3. If you need the GUI, first enable X11 forwarding on your host (at your own risk!):\n\n ```bash\n xhost +local:\n ```\n\n Then start the container as above\u2014the GUI will appear on your desktop.\n\n\n## Quick Start\n\nYou can use the tool either via a graphical user interface (GUI) or a command-line interface (CLI).\n\n### GUI Mode\n\nLaunch the interactive interface:\n\n```bash\nros2 unbag\n```\n\nThen follow the on\u2011screen prompts to pick your bag file, select topics, and choose export settings.\n\n\n### CLI Mode\n\nRun the CLI tool by calling *ros2 unbag* with a path to a rosbag and an export config, consisting of one or more topic:format:[subdirectory] combinations:\n\n```bash\nros2 unbag <path_to_rosbag> --export </topic:format[:subdir]>\u2026\n```\n\nAlternatively you can load a config file. In this case you do not need any `--export` flag:\n```bash\nros2 unbag <path_to_rosbag> --config <config.json>\n```\nthe structure of config files is described in [here](#config-file).\n\nIn addition to these required flags, there are some optional flags. See the table below, for all possible flags:\n| Flag | Value/Format | Description | Usage | Default |\n| --------------------------- | ---------------------------------------- | --------------------------------------------------------------------------------------------------------- | ---------------------------------- | -------------- |\n| **`bag`** | `<path>` | Path to ROS\u00a02 bag file (`.db3` or `.mcap`). | CLI mode (required) | \u2013 |\n| **`-e, --export`** | `/topic:format[:subdir]` | Topic \u2192 format export spec. Repeatable. | CLI mode (required or `--config`) | \u2013 |\n| **`-o, --output-dir`** | `<directory>` | Base directory for all exports. | Optional | `.` |\n| **`--naming`** | `<pattern>` | Filename pattern. Supports `%name`, `%index` and strftime (e.g. `%Y-%m-%d_%H-%M-%S`) - uses ROS timestamp | Optional | `%name_%index` |\n| **`--resample`** | `/master:association[,discard_eps]`. | Time\u2011align to master topic. `association` = `last` or `nearest`; `nearest` needs a numeric `discard_eps`. | Optional | \u2013 |\n| **`-p, --processing`** | `/topic:processor[:arg1=val1,\u2026]` | Pre\u2011export processor spec. Repeatable. | Optional | \u2013 |\n| **`--cpu-percentage`** | `<float>` | % of cores for parallel export (0\u2013100). Use `0` for single\u2011threaded. | Optional | `80.0` |\n| **`--config`** | `<config.json>` | JSON config file path. Overrides all other args (except `bag`). | Optional | \u2013 |\n| **`--gui`** | (flag) | Launch Qt GUI. If no `bag`/`--export`/`--config`, GUI is auto\u2011started. | Optional | `false` |\n| **`--use-routine`** | `<file.py>` | Load a routine for this run only (no install). | Optional | \u2013 |\n| **`--use-processor`** | `<file.py>` | Load a processor for this run only (no install). | Optional | \u2013 |\n| **`--install-routine`** | `<file.py>` | Copy & register custom export routine. | Standalone | \u2013 |\n| **`--install-processor`** | `<file.py>` | Copy & register custom processor. | Standalone | \u2013 |\n| **`--uninstall-routine`** | (flag) | Interactive removal of an installed routine. | Standalone | - |\n| **`--uninstall-processor`** | (flag) | Interactive removal of an installed processor. | Standalone | - |\n| **`--help`** | (flag) | Show usage information and exit. | Standalone | - |\n\nExample: \n```bash\nros2 unbag rosbag/rosbag.mcap \n --output-dir /docker-ros/ws/example/ --export /lidar/point_cloud:pointcloud/pcd:lidar --export /radar/point_cloud:pointcloud/pcd:radar --resample /lidar/point_cloud:last,0.2\n```\n\n\u26a0\ufe0f If you specify the `--config` option (e.g., `--config configs/my_config.json`), the tool will load all export settings from the given JSON configuration file. In this case, all other command-line options except `<path_to_rosbag>` are ignored, and the export process is fully controlled by the config file. The `<path_to_rosbag>` is always required in CLI use.\n\n## Config File\nWhen using ros2 unbag, you can define your export settings in a JSON configuration file. This works in the GUI, as well as in the CLI version. It allows you to easily reuse your export settings without having to specify them on the command line every time.\n\n\ud83d\udca1 Tip: Use the GUI to create your export settings and then save them via the \"Save Config\" button. This will create a JSON file with all your export settings, which you can then use in the CLI version.\n\n```jsonc\n{\n \"/imu/pos\": {\n \"format\": \"text/json@single_file\",\n \"path\": \"/docker-ros/data/rosbag2_2025_08_19-12_34_56\",\n \"subfolder\": \"%name\",\n \"naming\": \"%name\"\n },\n \"/drivers/lidar_fl/nearir_image\": {\n \"format\": \"image/png\",\n \"path\": \"/docker-ros/data/rosbag2_2025_08_19-12_34_56\",\n \"subfolder\": \"%name\",\n \"naming\": \"%name_%index\"\n },\n \"/drivers/lidar_fl/pointcloud\": {\n \"format\": \"pointcloud/pcd\",\n \"path\": \"/docker-ros/data/rosbag2_2025_08_19-12_34_56\",\n \"subfolder\": \"%name\",\n \"naming\": \"%name_%index\",\n \"processor\": \"transform_from_yaml\",\n \"processor_args\": {\n \"custom_frame_path\": \"test.yml\"\n }\n },\n \"__global__\": {\n \"cpu_percentage\": 85.0,\n \"resample_config\": {\n \"master_topic\": \"/drivers/lidar_fl/pointcloud\",\n \"association\": \"nearest\",\n \"discard_eps\": 0.5\n }\n }\n}\n```\n\n## Export Routines \n\nExport routines define the way how messages are exported from the ros2 bag file to the desired output format. The tool comes with a set of predefined routines for **all** message types and formats, such as:\n\n| Identifier(s) | Topic(s) | Description |\n| ------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |\n| **image/png** | `sensor_msgs/msg/Image`<br> `sensor_msgs/msg/CompressedImage` | Exports images via openCV to PNG. | \n| **image/jpeg** | `sensor_msgs/msg/Image`<br> `sensor_msgs/msg/CompressedImage` | Exports images via openCV to JPEG. |\n| **video/mp4** | `sensor_msgs/msg/Image`<br> `sensor_msgs/msg/CompressedImage` | Exports image sequences via openCV to MP4. |\n| **video/avi** | `sensor_msgs/msg/Image`<br> `sensor_msgs/msg/CompressedImage` | Exports image sequences via openCV to AVI. |\n| **pointcloud/pkl** | `sensor_msgs/msg/PointCloud2` | Serializes the entire `PointCloud2` message object using Python\u2019s `pickle`, producing a `.pkl` file. |\n| **pointcloud/xyz** | `sensor_msgs/msg/PointCloud2` | Unpacks each point\u2019s\u00a0x,\u00a0y,\u00a0z floats from the binary buffer and writes one `x y z` line per point into a plain `.xyz` text file. |\n| **pointcloud/pcd** | `sensor_msgs/msg/PointCloud2` | Constructs a PCD\u00a0v0.7 file and writes binary point data* in PCD format to a `.pcd` file. |\n| **pointcloud/pcd_compressed** | `sensor_msgs/msg/PointCloud2` | Constructs a PCD\u00a0v0.7 file and writes compressed binary point data* in PCD format to a `.pcd` file. |\n| **pointcloud/pcd_ascii** | `sensor_msgs/msg/PointCloud2` | Constructs a PCD\u00a0v0.7 file and writes ASCII point data* in PCD format to a `.pcd` file. |\n\n***Note:** Point data in PCD files is written with all fields, that are present in the `PointCloud2` message. Some programs do not support arbitrary fields in PCD files. If you need to export only specific fields, you can use the `remove_fields` processor to drop unwanted fields before exporting. See the [Processors](#processors) section for more information.*\n\nIn addition to these specialized routines, there are also generic routines for exporting any message type to common formats. These are available as `@single_file` and `@multi_file` variants, which determine whether all messages are written to a single file or each message is written to its own file:\n\n| Identifier | Topic(s) | `@single_file` Description | `@multi_file` Description |\n| ------------- | -------------------- | ------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |\n| **table/csv** | *any message type* | Flattens fields, writes header + one row per message into a single `.csv` file. | Flattens fields, writes header + one message per file into separate `.csv` files. |\n| **text/json** | *any message type* | All messages in one `.json` file as a list of objects. | One `.json` file per message. |\n| **text/yaml** | *any message type* | One `.yaml` document containing all messages in a single `.yaml` file. | One `.yaml` document per message. |\n\nYou can call these as `table/csv@single_file` or `table/csv@multi_file`.\n\n### Custom Export Routines\nYour message type or output format is not supported by default? No problem! You can add your own export routines to handle custom message types or output formats.\n\nRoutines are defined like this: \n\n```python\nfrom pathlib import Path # import Path from pathlib for file path handling\nfrom ros2_unbag.core.routines.base import ExportRoutine # import the base class\n# you can also import other packages here - e.g., numpy, cv2, etc.\n\n@ExportRoutine(\"sensor_msgs/msg/PointCloud2\", [\"pointcloud/xyz\"], mode=ExportMode.MULTI_FILE)\ndef export_pointcloud_xyz(msg, path: Path, fmt: str, metadata: ExportMetadata): # define the export routine function, the name of the function does not matter\n \"\"\"\n Export PointCloud2 message as an XYZ text file by unpacking x, y, z floats from each point and writing lines.\n\n Args:\n msg: PointCloud2 message instance.\n path: Output file path (without extension).\n fmt: Export format string (default \"pointcloud/xyz\").\n metadata: Export metadata including message index and max index.\n\n Returns:\n None\n \"\"\"\n with open(path + \".xyz\", 'w') as f: # define your custom logic to export the message\n for i in range(0, len(msg.data), msg.point_step):\n x, y, z = struct.unpack_from(\"fff\", msg.data, offset=i)\n f.write(f\"{x} {y} {z}\\n\")\n```\n\nA template for this, including single file handling is available in the `templates` directory of the repository. You can copy it and modify it to suit your needs.\n\nThe message type, format and mode are defined in the decorator. The `ExportRoutine` decorator registers the function as an export routine for the specified message type and format. It has the following attributes:\n\n- `msg_types`: The message types that this routine can handle. (Can be a single type or a list of types.) Note that the message type must be installed in the system, i.e., it must be available in the ROS 2 environment.\n- `formats`: The output formats that this routine supports. (Can be a single format or a list of formats.)\n- `mode`: Specifies the export mode \u2014 SINGLE_FILE or MULTI_FILE. This determines whether the routine is designed for exporting data into a single file or multiple files. While this setting affects parallelization and naming conventions, you must implement the logic for single file exports yourself if you choose SINGLE_FILE mode (e.g., appending data to the same file during each function call).\n\nYou can import your own routines permanently by calling \n```bash \nros2 unbag --install-routine <path_to_your_routine_file>\n```\n\nor use them only temporarily by specifying the `--use-routine` option when starting the program. This works in both the GUI and CLI versions.\n\n```bash\nros2 unbag --use-routine <path_to_your_routine_file>\n```\n\nIf you installed a routine and do not want it anymore, you can delete it by calling\n```bash\nros2 unbag --uninstall-routine\n```\nYou\u2019ll be prompted to pick which routine to uninstall.\n\n\u26a0\ufe0f Never use or install new routines that you did not write yourself or that you do not trust. The code gets ingested and executed in the context of the *ros2 unbag* process, which means it can access all data and resources available to the process. This includes reading and writing files, accessing network resources, and more. Always review the code of any routine you use or install.\n\n## Processors\n\nProcessors are used to modify messages before they are exported. They can be applied to specific topics and allow you to perform operations such as filtering, transforming, or enriching the data.\n\nThe following processors are available by default:\n| Identifier(s) | Topic(s) | Arguments | Description |\n| ---------------------- | ------------------------------------------------------------------- | -------------------------------------------------------------- | ------------------------------------------ |\n| **field_mapping** | `sensor_msgs/msg/PointCloud2` | `field_mapping` String in the form `old_field:new_field, ...` | Remaps fields in a PointCloud2 message. |\n| **remove_fields** | `sensor_msgs/msg/PointCloud2` | `fields_to_remove` List of field names to remove `field1, ...` | Removes specified fields from PointCloud2. |\n| **transform_from_yaml**| `sensor_msgs/msg/PointCloud2` | `custom_frame_path` Path to a YAML file with custom frame data | Transforms PointCloud2 to a custom frame. |\n| **apply_color_map** | `sensor_msgs/msg/Image` <br> `sensor_msgs/msg/CompressedImage` | `color_map` Integer specifying cv2 colormap index*. | Applies a color map to an image. |\n\n*Note: The `color_map` argument is an integer that specifies the OpenCV colormap index. You can find a list of available colormaps in the [OpenCV documentation](https://docs.opencv.org/4.x/d3/d50/group__imgproc__colormap.html).*\n\n### Custom Processors\n\nYou can define your own processors like this:\n\n```python\n# Import the processor decorator\nfrom ros2_unbag.core.processors.base import Processor\n\n# Define the processor class with the appropriate message types and give it a name\n@Processor([\"std_msgs/msg/String\"], [\"your_processor_name\"]) \ndef your_processor_name(msg, your_parameter: str = \"default\", your_parameter_2: str = \"template\"):\n \"\"\"\n Short description of what the processor does.\n\n Args:\n msg: The ROS message you want to process.\n your_parameter: Describe the parameter. This will be shown in the UI.\n your_parameter_2: You can add more parameters as needed.\n\n Returns:\n The return always needs to match the incoming message type.\n \"\"\"\n\n # Validate and convert parameter\n try:\n your_parameter = str(your_parameter)\n your_parameter_2 = str(your_parameter_2)\n except ValueError:\n raise ValueError(f\"One of the parameters is not valid: {your_parameter}, {your_parameter_2}\")\n\n # Decode ROS message if necessary\n string_msg = msg.data # Assuming msg is a String message\n\n # --- Apply your processing here ---\n processed_msg = string_msg.replace(your_parameter, your_parameter_2)\n\n # Re-encode the image\n msg.data = processed_msg\n\n return msg\n```\n\nA template for this is available in the `templates` directory of the repository. You can copy it and modify it to suit your needs.\n\nThe message type and processor name are defined in the decorator. The `Processor` decorator registers the function as a processor for the specified message type and name. It has the following attributes:\n\n- `msg_types`: The message types that this processor can handle. (Can be a single type or a list of types.) Note that the message type must be installed in the system, i.e., it must be available in the ROS 2 environment.\n- `name`: The name of the processor, which is used to identify it in the system.\n\nYou can import your own processors by calling \n```bash\nros2 unbag --install-processor <path_to_your_processor_file>\n```\n\nor use them only temporarily by specifying the `--use-processor` option when starting the program. This works in both the GUI and CLI versions.\n\n```bash\nros2 unbag --use-processor <path_to_your_processor_file>\n```\n\nIf you installed a processor and do not want it anymore, you can delete it by calling\n```bash\nros2 unbag --uninstall-processor\n```\nYou\u2019ll be prompted to pick which processor to uninstall.\n\n\u26a0\ufe0f Never use or install new processes that you did not write yourself or that you do not trust. The code gets ingested and executed in the context of the *ros2 unbag* process, which means it can access all data and resources available to the process. This includes reading and writing files, accessing network resources, and more. Always review the code of any routine you use or install.\n\n## Resampling\nIn many cases, you may want to resample messages in the frequency of a master topic. This allows you to assemble a \"frame\" of data that is temporally aligned with a specific topic, such as a camera or LIDAR sensor. The resampling process will ensure that the messages from other topics are exported in sync with the master topic's timestamps.\n\nros2 unbag supports resampling of messages based on a master topic. You can specify the master topic and the resampling type (e.g., `last` or `nearest`) along with an optional discard epsilon value.\n\n### Last\nThe `last` resampling type will listen for the master topic. As soon as a message of the master topic is received, a frame will be assembled, containing the last message of any other selected topics. With an optional `discard_eps` value, you can specify a maximum time difference between the master topic message and the other topics' messages. If no message is found within the `discard_eps` value, the whole frame is discarded.\n\n### Nearest\nThe `nearest` resampling type will listen for the master topic and export it along with the (temporally) nearest message of the other topics that were published in the time range of the master topic message. This resampling strategy is only usable with an `discard_eps` value, which defines the maximum time difference between the master topic message and the other topics' messages. If no message is found within the `discard_eps` value, the whole frame is discarded.\n\n## CPU utilization\n*ros2 unbag* uses multi-processing to export messages in parallel. By default, full parallelization is applied only when exporting to multiple files. For single-file outputs, it uses one process per file to ensure deterministic ordering, which still utilizes multi-processing but with limited concurrency. You can control the number of processes by setting the --cpu-percentage option. The default value is 80%, meaning the tool will use 80% of available CPU cores for processing. Adjust this value to control CPU utilization during export.\n\n## Acknowledgements\nThis research is accomplished within the following research projects:\n\n| Project | Funding Source | | \n|---------|----------------|:----:|\n| <a href=\"https://www.ika.rwth-aachen.de/de/kompetenzen/projekte/automatisiertes-fahren/4-cad.html\"><img src=\"https://www.ika.rwth-aachen.de/images/projekte/4cad/4cad-logo.svg\" alt=\"4-CAD\" height=\"40\"/></a> | Funded by the Deutsche Forschungsgemeinschaft (DFG, German Research Foundation) DFG Proj. Nr. 503852364 | <p align=\"center\"><img src=\"https://www.ika.rwth-aachen.de/images/foerderer/dfg.svg\" height=\"50\"/></p> |\n| <a href=\"https://iexoddus-project.eu/\"><img src=\"https://www.ika.rwth-aachen.de/images/projekte/iexoddus/iEXODDUS%20Logo%20color.svg\" alt=\"iEXXODUS\" height=\"40\"/></a> | Funded by the European Union\u2019s Horizon Europe Research and Innovation Programme under Grant Agreement No 101146091 | <p align=\"center\"><img src=\"https://www.ika.rwth-aachen.de/images/foerderer/eu.svg\" height=\"50\"/></p> |\n| <a href=\"https://synergies-ccam.eu/\"><img src=\"https://www.ika.rwth-aachen.de/images/projekte/synergies/SYNERGIES_Logo%201.png\" alt=\"SYNERGIES\" height=\"40\"/></a> | Funded by the European Union\u2019s Horizon Europe Research and Innovation Programme under Grant Agreement No 101146542 | <p align=\"center\"><img src=\"https://www.ika.rwth-aachen.de/images/foerderer/eu.svg\" height=\"50\"/></p> |\n\n## Notice \n\n> [!IMPORTANT] \n> This repository is open-sourced and maintained by the [**Institute for Automotive Engineering (ika) at RWTH Aachen University**](https://www.ika.rwth-aachen.de/). \n> We cover a wide variety of research topics within our [*Vehicle Intelligence & Automated Driving*](https://www.ika.rwth-aachen.de/en/competences/fields-of-research/vehicle-intelligence-automated-driving.html) domain. \n> If you would like to learn more about how we can support your automated driving or robotics efforts, feel free to reach out to us! \n> :email: ***opensource@ika.rwth-aachen.de***\n",
"bugtrack_url": null,
"license": "MIT License\n \n Copyright (c) 2025 Institute for Automotive Engineering (ika), RWTH Aachen University\n \n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n \n The above copyright notice and this permission notice shall be included in all\n copies or substantial portions of the Software.\n \n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n SOFTWARE.",
"summary": "A ROS 2 tool for exporting bags to human readable files. Supports pluggable export routines to handle any message type.",
"version": "1.0.4",
"project_urls": {
"homepage": "https://github.com/ika-rwth-aachen/ros2_unbag"
},
"split_keywords": [
"ros2",
" rosbag",
" robotics",
" perception",
" ros2-export"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "ef15b76a3760b2cdcedf56748f53da89becd37ac28ff075c29caaf25ebd8e693",
"md5": "33fee396a5460bb1b17a665a1247629a",
"sha256": "c80e0a0ada11a704c4952dafac262467899fceffabd0c1a81a866c9d7b7747e0"
},
"downloads": -1,
"filename": "ros2_unbag-1.0.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "33fee396a5460bb1b17a665a1247629a",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 595071,
"upload_time": "2025-08-07T18:36:52",
"upload_time_iso_8601": "2025-08-07T18:36:52.840562Z",
"url": "https://files.pythonhosted.org/packages/ef/15/b76a3760b2cdcedf56748f53da89becd37ac28ff075c29caaf25ebd8e693/ros2_unbag-1.0.4-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "0797375011164c523fa9828e8bb8180c9a128805d3a389d9c5ffb58fce6af1fc",
"md5": "5a41e3e96cefc08c6ed2806719d557da",
"sha256": "c6995c08a0155fb647ea09d8c7d13f262794c275f227e79401eca000763ed6b5"
},
"downloads": -1,
"filename": "ros2_unbag-1.0.4.tar.gz",
"has_sig": false,
"md5_digest": "5a41e3e96cefc08c6ed2806719d557da",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 587982,
"upload_time": "2025-08-07T18:36:54",
"upload_time_iso_8601": "2025-08-07T18:36:54.503748Z",
"url": "https://files.pythonhosted.org/packages/07/97/375011164c523fa9828e8bb8180c9a128805d3a389d9c5ffb58fce6af1fc/ros2_unbag-1.0.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-07 18:36:54",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "ika-rwth-aachen",
"github_project": "ros2_unbag",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "ros2-unbag"
}