@@ -15,25 +15,13 @@ uv add pybag-sdk
1515uv tool install pybag-sdk
1616```
1717
18- ## Quick Start
18+ ## Reading Files
1919
20- ### CLI
21-
22- ``` bash
23- # Get file information
24- pybag info data.mcap
25-
26- # Filter messages
27- pybag filter data.mcap -o output.mcap --include-topic /camera
28-
29- # Merge multiple files
30- pybag merge input1.mcap input2.mcap -o output.mcap
31- ```
20+ There are a number of ways to read data with pybag.
3221
3322### Unified Reader
3423
3524The ` Reader ` class provides a common interface for reading both MCAP and ROS 1 bag files.
36-
3725The file format is automatically detected from the file extension.
3826
3927``` python
@@ -56,30 +44,60 @@ with Reader.from_file("data.bag") as reader:
5644from pybag.mcap_reader import McapFileReader
5745
5846with McapFileReader.from_file(" data.mcap" ) as reader:
47+ # Get available topics
48+ topics = reader.get_topics()
49+
50+ # Stream messages with filtering
51+ for msg in reader.messages(
52+ topic = [" /camera/*" , " /sensor/imu" ],
53+ start_time = 1_000_000_000 , # nanoseconds
54+ end_time = 2_000_000_000 ,
55+ in_log_time_order = True
56+ ):
57+ print (msg.log_time, msg.data)
58+
59+ # Get attachments and metadata
60+ attachments = reader.get_attachments()
61+ metadata = reader.get_metadata()
62+ ```
63+
64+ ### Reading ROS 1 Bag Files
65+
66+ ``` python
67+ from pybag.bag_reader import BagFileReader
68+
69+ with BagFileReader.from_file(" data.bag" ) as reader:
5970 for msg in reader.messages(" /camera" ):
6071 print (msg.log_time, msg.data)
6172```
6273
74+ ## Writing Files
75+
76+ There are a number of ways to write data with pybag.
77+
6378### Writing MCAP Files
6479
6580``` python
6681from pybag.mcap_writer import McapFileWriter
6782from pybag.ros2.humble import std_msgs
6883
69- with McapFileWriter.open(" output.mcap" ) as writer:
70- log_time_ns = 1000
84+ with McapFileWriter.open(
85+ " output.mcap" ,
86+ profile = " ros2" ,
87+ chunk_compression = " lz4"
88+ ) as writer:
7189 msg = std_msgs.String(data = " hello" )
72- writer.write_message(" /status" , log_time_ns, msg)
73- ```
90+ writer.write_message(" /status" , 1_000_000_000 , msg)
7491
75- ### Reading ROS 1 Bag Files
76-
77- ``` python
78- from pybag.bag_reader import BagFileReader
92+ # Add attachments
93+ writer.write_attachment(
94+ name = " calibration.yaml" ,
95+ data = b " camera: ..." ,
96+ media_type = " application/yaml"
97+ )
7998
80- with BagFileReader.from_file(" data.bag" ) as reader:
81- for msg in reader.messages(" /camera" ):
82- print (msg.log_time, msg.data)
99+ # Add metadata
100+ writer.write_metadata(" recording_info" , {" robot" : " husky_1" })
83101```
84102
85103### Writing ROS 1 Bag Files
@@ -88,24 +106,173 @@ with BagFileReader.from_file("data.bag") as reader:
88106from pybag.bag_writer import BagFileWriter
89107from pybag.ros1.noetic import std_msgs
90108
91- with BagFileWriter.open(" output.bag" ) as writer:
92- log_time_ns = 1000
109+ with BagFileWriter.open(" output.bag" , compression = " bz2" ) as writer:
93110 msg = std_msgs.String(data = " hello" )
94- writer.write_message(" /status" , log_time_ns, msg)
111+ writer.write_message(" /status" , 1_000_000_000 , msg)
112+ ```
113+
114+ ## Append Mode
115+
116+ Both MCAP and bag writers support append mode to add messages to existing files.
117+
118+ ### Appending to MCAP Files
119+
120+ ``` python
121+ from pybag.mcap_writer import McapFileWriter
122+
123+ # Create a new file
124+ with McapFileWriter.open(" recording.mcap" ) as writer:
125+ writer.write_message(" /topic" , 1_000_000_000 , msg1)
126+
127+ # Append to existing file
128+ with McapFileWriter.open(" recording.mcap" , mode = " a" ) as writer:
129+ writer.write_message(" /topic" , 2_000_000_000 , msg2)
130+ writer.write_message(" /new_topic" , 3_000_000_000 , msg3)
131+ ```
132+
133+ ### Appending to ROS 1 Bag Files
134+
135+ ``` python
136+ from pybag.bag_writer import BagFileWriter
137+
138+ # Create a new file
139+ with BagFileWriter.open(" recording.bag" ) as writer:
140+ writer.write_message(" /topic" , 1_000_000_000 , msg1)
141+
142+ # Append to existing file
143+ with BagFileWriter.open(" recording.bag" , mode = " a" ) as writer:
144+ writer.write_message(" /topic" , 2_000_000_000 , msg2)
145+ writer.write_message(" /new_topic" , 3_000_000_000 , msg3)
146+ ```
147+
148+ ## TypeStore
149+
150+ The ` TypeStore ` provides unified access to ROS message schemas from built-in definitions
151+ and custom ` .msg ` files.
152+
153+ ``` python
154+ from pybag.typestore import TypeStore
155+
156+ # Create a type store for ROS 2 Humble
157+ type_store = TypeStore(encoding = " ros2msg" , distro = " humble" )
158+
159+ # Add custom message paths
160+ type_store.add_path(" /path/to/custom_msgs" )
161+
162+ # Find a message schema
163+ schema = type_store.find(" std_msgs/msg/String" )
164+
165+ # List user-provided messages
166+ messages = type_store.list_messages()
95167```
96168
97- ### Custom Messages
169+ ### Supported Distributions
170+
171+ ** ROS 1** : noetic (and legacy: melodic, kinetic, indigo, etc.)
172+
173+ ** ROS 2** : foxy, galactic, humble, iron, jazzy, kilted, rolling
174+
175+ ## Custom Messages
176+
177+ Define custom message types using dataclasses:
98178
99179``` python
100180from dataclasses import dataclass
101181import pybag.types as t
182+ from pybag.mcap_writer import McapFileWriter
102183
103184@dataclass
104185class SensorData :
105- __msg_name__ = ' custom/msg/SensorData'
186+ __msg_name__ = " custom/msg/SensorData"
106187 temperature: t.float32
107188 humidity: t.float32
108189
109190with McapFileWriter.open(" sensors.mcap" ) as writer:
110- writer.write_message(" /sensor" , 1000 , SensorData(25.5 , 60.0 ))
191+ writer.write_message(" /sensor" , 1_000_000_000 , SensorData(25.5 , 60.0 ))
192+ ```
193+
194+ Or provide schema text directly:
195+
196+ ``` python
197+ from pybag.types import SchemaText
198+
199+ schema = SchemaText(
200+ name = " custom/msg/SensorData" ,
201+ text = " float32 temperature\n float32 humidity"
202+ )
203+
204+ with McapFileWriter.open(" sensors.mcap" ) as writer:
205+ writer.add_channel(" /sensor" , schema = schema)
206+ writer.write_message(" /sensor" , 1_000_000_000 , {" temperature" : 25.5 , " humidity" : 60.0 })
207+ ```
208+
209+ ## CLI Reference
210+
211+ ### info
212+
213+ Display file statistics and metadata:
214+
215+ ``` bash
216+ pybag info recording.mcap
217+ pybag info recording.bag
218+ ```
219+
220+ ### filter
221+
222+ Extract data based on topic patterns and time ranges:
223+
224+ ``` bash
225+ pybag filter input.mcap -o output.mcap \
226+ --include-topic " /sensor/*" \
227+ --exclude-topic " /sensor/debug" \
228+ --start-time 10.5 \
229+ --end-time 20.3
230+ ```
231+
232+ ### merge
233+
234+ Combine multiple files into one:
235+
236+ ``` bash
237+ pybag merge file1.mcap file2.mcap -o merged.mcap
238+ pybag merge bag1.bag bag2.bag -o merged.bag
239+ ```
240+
241+ ### convert
242+
243+ Convert between bag and MCAP formats:
244+
245+ ``` bash
246+ # Bag to MCAP
247+ pybag convert input.bag -o output.mcap --profile ros2 --mcap-compression lz4
248+
249+ # MCAP to Bag
250+ pybag convert input.mcap -o output.bag --bag-compression bz2
251+ ```
252+
253+ ### sort
254+
255+ Sort messages by time and/or topic:
256+
257+ ``` bash
258+ pybag sort input.mcap -o sorted.mcap --log-time --by-topic
259+ ```
260+
261+ ### recover
262+
263+ Recover data from corrupted files:
264+
265+ ``` bash
266+ pybag recover corrupted.mcap -o recovered.mcap --verbose
267+ ```
268+
269+ ### inspect
270+
271+ Examine specific record types:
272+
273+ ``` bash
274+ pybag inspect schemas recording.mcap
275+ pybag inspect channels recording.mcap --topic " /camera/*"
276+ pybag inspect metadata recording.mcap --name " calibration"
277+ pybag inspect attachments recording.mcap --name " calib.yaml" --data
111278```
0 commit comments