Small ROS 2 (Humble+) command-line tools that inspect a rosbag2 (.mcap
or .db3) for its TF2 contents:
tf_bag_analysis: produces a statistics report about all TF topics.tf_relative_pose_plot: plots the relative pose (XYZ + roll/pitch/yaw) between two frames over time.
As any ROS 2 package, drop it into your workspace src/ and build:
source /opt/ros/humble/setup.bash
colcon build --packages-select tf_bag_analysis
source install/setup.bashInspects a rosbag2 and produces a statistics report about its TF2
contents. It answers questions like:
- How many TF topics are in this bag? How many are at the root
(
/tf,/tf_static) vs. inside a robot/sub-system namespace (<ns>/tf,<ns>/tf_static)? - What coordinate frames appear on each TF topic? What is their union, and how do they split by namespace?
- For each parent→child edge: how many times was it broadcast, over what time span, and at what effective rate?
- When does TF publication start and end, and what is the overall duration?
Output goes to the terminal as a plain-text summary, and (optionally) to a Markdown file that also embeds a per-namespace Mermaid TF graph.
ros2 run tf_bag_analysis tf_bag_analysis <bag_path> [--md <report.md>]<bag_path> can be:
- a rosbag2 directory (containing
metadata.yaml), or - a single
.mcap/.db3file.
Examples:
# Plain text report to stdout
ros2 run tf_bag_analysis tf_bag_analysis my_bag/
# Text summary + Markdown report with Mermaid diagrams
ros2 run tf_bag_analysis tf_bag_analysis my_bag.mcap --md tf_report.md- Topic summary: total number of TF topics, split into root vs.
namespaced, and
tfvs.tf_static. Distinct namespaces are listed. - Bag time range: first/last message time and duration (seconds).
- Per-topic statistics: message count, total transforms, duration, effective message rate (Hz), number of distinct edges.
- Per-topic frames and edges: the set of frame IDs on each topic and,
for every
(parent, child)pair, its count, rate and time span. - All frames: union of frame IDs, and a per-namespace breakdown.
- TF graph (Markdown only): a Mermaid
graph LRdiagram per namespace, drawn from the union of all edges seen on that namespace's TF topics.
Replays all /tf and /tf_static topics (root and namespaced) from a
rosbag2 into a tf2 buffer sized to cover the whole bag, then samples the
relative pose of <target_frame_id> as seen from <reference_frame_id> at
a fixed rate over the bag's TF time span. The result (X, Y, Z in meters and
roll/pitch/yaw in degrees, ZYX convention) is plotted with
gnuplot and/or written as CSV.
tf_relative_pose_plot <bag_path> <reference_frame_id> <target_frame_id> \
[--rate HZ] [--csv <output.csv>] [--no-plot]The binary is installed under lib/tf_bag_analysis/ (it can also be run
with ros2 run tf_bag_analysis tf_relative_pose_plot ...).
--rate HZ: sampling rate for the output time series (default:20).--csv <file>: also write the time series as CSV (time_s,x,y,z,roll_deg,pitch_deg,yaw_deg).--no-plot: skip opening the gnuplot window (useful with--csvor when gnuplot/X11 isn't available).
Examples:
# Open an interactive plot window
tf_relative_pose_plot my_bag/ odom base_link
# Sample at 50 Hz and also export a CSV, no plot window
tf_relative_pose_plot my_bag.mcap map base_link --rate 50 --csv rel_pose.csv --no-plotRequires the gnuplot binary (with qt terminal support) to be installed
for plotting, e.g. sudo apt install gnuplot-qt.
rclcpprosbag2_cpp,rosbag2_storage(+ default storage plugins)tf2_msgs,geometry_msgs,tf2,tf2_rosgnuplot(runtime, fortf_relative_pose_plotplotting)
BSD-3-Clause. See LICENSE.