Skip to content

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)

Replace index with header.stamp as DatetimeIndex.

Parameters

df : pd.DataFrame DataFrame containing header.stamp.sec and header.stamp.nanosec columns.

Returns

pd.DataFrame New DataFrame with publish-time index. Original is not modified.

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.