baglab.io¶
baglab.io
¶
I/O module for rosbag loading, field access, and timestamp utilities.
FieldGroup
¶
Intermediate node for chained ROS2-style field access.
Returned by :class:MsgAccessor attribute access. Supports further
chaining until a leaf (single column) is reached, at which point a
:class:~pandas.Series is returned.
Use the :attr:df property to obtain a :class:~pandas.DataFrame
containing all columns under the current prefix, with the prefix
stripped from column names.
df
property
¶
Return matching columns as a DataFrame with prefix stripped.
MsgAccessor
¶
ROS2-style dot access for DataFrame columns.
Registered as df.msg. Supports chained attribute access
mirroring ROS2 message field hierarchy::
df.msg.twist.linear.x # → Series
df.msg.twist.linear # → FieldGroup
df.msg.twist.linear.df # → DataFrame with columns [x, y, z]
Bag
¶
Rosbag handle with lazy per-topic DataFrame loading.
Use :func:baglab.load to create instances instead of calling this
constructor directly — load expands shell paths, preloads topics,
and selects the backend automatically.
Access topic data via subscript::
bag = baglab.load("path/to/rosbag")
df = bag["/cmd_vel"] # all fields, cached
df = bag["/cmd_vel", ["twist.linear.x"]] # field selection, not cached
Parameters¶
path : Path Path to the rosbag directory.
topics
property
¶
Return {topic_name: message_type} mapping.
preload(topic_names)
¶
Batch-preload topics into the in-memory cache.
On the mcap backend this uses a single-pass read through the file, which is much faster than reading topics one-by-one. Other backends fall back to sequential loading.
Preloaded topics are returned instantly by bag[topic].
Parameters¶
topic_names : list[str] Topic names to preload.
__getitem__(key)
¶
Access topic data with optional field selection.
Usage::
bag["/motor/angle"] # all fields, cached
bag["/motor/angle", ["actual"]] # specific fields, not cached
close()
¶
Close the underlying reader.
explode_array(series, names=None)
¶
Expand an array-valued Series into a DataFrame with one column per element.
Useful for sensor_msgs/JointState fields like position,
velocity, and effort where each cell contains a list.
Parameters¶
series : pd.Series
Series whose cells are lists or arrays of equal length.
names : sequence of str, optional
Column names for the resulting DataFrame. If None, columns are
named 0, 1, 2, ....
Returns¶
pd.DataFrame DataFrame with the same index as series.
clear_cache(path)
¶
Remove the disk cache for a rosbag.
Parameters¶
path : str | Path
Path to the rosbag directory. Shell notation (~, $VAR) is expanded.
find_bags(pattern)
¶
Return bag paths matching a glob pattern, sorted by data-file modification time.
Sorts by the modification time of the actual .db3 or .mcap files
inside each bag directory (oldest first), ignoring cache or metadata
timestamps.
Parameters¶
pattern : str
Glob pattern (e.g. "/path/to/log_dir/*").
Returns¶
list[Path]
Matched paths sorted ascending by data-file mtime.
Use [-1] for the latest bag.
has_mcap_backend()
¶
Return True if the baglab-mcap acceleration package is installed.
load(path, topics=None, msg_paths=(), *, use_cache=True, backend='auto')
¶
Load a rosbag.
Parameters¶
path : str | Path
Path to the rosbag directory. Shell notation (~, $VAR) is expanded.
topics : list[str] | dict[str, list[str]] | None
If a list of topic names, eagerly preload all fields for those topics
in a single pass (fast batch read on mcap backend).
If a dict {topic: [fields]}, eagerly load specified fields per topic.
If None, return a lazy :class:Bag handle.
msg_paths : Sequence[str | Path]
Directories to scan for .msg files. Required for db3 bags
that use custom message types not included in the standard ROS2
type definitions. Shell notation is expanded.
use_cache : bool
If True (default), use disk cache for loaded DataFrames.
Set to False to always read from the bag file directly.
backend : str
Backend to use for reading: "auto" (default), "mcap",
or "rosbags".
Returns¶
Bag
A bag handle. When topics is provided, the requested
DataFrames are pre-cached and accessible via bag[topic].
Examples¶
Lazy loading (topics loaded on first access)::
bag = baglab.load("~/rosbags/experiment1")
df = bag["/cmd_vel"]
Eager batch preloading::
bag = baglab.load("~/rosbags/experiment1", topics=["/cmd_vel", "/odom"])
Field-selective loading::
bag = baglab.load("path", topics={"/imu": ["angular_velocity.x"]})
align_origin(*series)
¶
Shift multiple time series so that the global minimum becomes 0.
Parameters¶
*series : pd.Series
Time series in absolute seconds (e.g. from :func:stamp_to_sec or
:func:recv_time_to_sec).
Returns¶
tuple[pd.Series, ...] Each input series shifted by the same shared origin.
Raises¶
ValueError If no series are provided.
find_time(series, condition)
¶
Return the relative time of the first element satisfying condition.
Parameters¶
series : pd.Series
Series with a DatetimeIndex.
condition : Callable[[pd.Series], pd.Series]
A callable that accepts the Series values and returns a boolean Series.
For example lambda x: x >= 0.5.
Returns¶
float
Seconds from series.index[0] to the first matching element.
Raises¶
ValueError If no element satisfies the condition.
recv_time_to_sec(df, relative=False)
¶
Convert the DataFrame DatetimeIndex (rosbag receive time) to float seconds.
Parameters¶
df : pd.DataFrame
DataFrame with a DatetimeIndex produced by :func:load.
relative : bool
If True, return time relative to the first message (starting from 0).
Returns¶
pd.Series Receive timestamp in seconds as float64.
reindex_by_stamp(df)
¶
stamp_to_sec(df, relative=False, stamp='header.stamp')
¶
Combine stamp sec and nanosec columns into float seconds.
Parameters¶
df : pd.DataFrame
DataFrame containing {stamp}.sec and {stamp}.nanosec columns.
relative : bool
If True, return time relative to the first message (starting from 0).
stamp : str
Column prefix for the builtin_interfaces/Time field.
Default "header.stamp".
Returns¶
pd.Series Timestamp in seconds as float64.
time_slice(df, t_start, t_end)
¶
Slice a DatetimeIndex DataFrame by relative time in seconds.
Parameters¶
df : pd.DataFrame
DataFrame with a DatetimeIndex.
t_start : float
Start time in seconds relative to df.index[0].
t_end : float
End time in seconds relative to df.index[0].
Returns¶
pd.DataFrame Subset of df within the requested time window. The original DataFrame is not modified.
register_msg_types(typestore, path)
¶
Scan path for .msg files and register them in typestore.
The directory structure must follow the ROS2 convention::
<pkg_name>/msg/<MsgName>.msg
Types already present in typestore are silently skipped.
Parameters¶
typestore : Typestore
The rosbags typestore to register types into.
path : str | Path
Root directory to search for .msg files.
Returns¶
int Number of newly registered types.