This repository contains a set of scripts and utilities to process and analyze ROS bag files. It converts ROS bags into CSV format, organizes data per topic, generates plots for velocities and trajectories, and computes errors for analysis.
- Overview
- Dependencies
- Folder Structure Created by Script
- User Manual
- Errors and Plots
- Bag File Naming Warning
- Execution Flow Example
- Available Functions
- Notes and Warnings
bagpypandasmatplotlibpyyamlnumpyscikit-learnreglobgeopy
Install dependencies with:
pip install bagpy pandas matplotlib pyyaml numpy scikit-learn glob2 geopy
Upon running the script, the following structure is created within your specified bag_folder:
-
csv_files/
- per_run/
- run_0/ (individual run CSV files)
- run_1/
- ... and so on.
- per_topic/
- topic_name_1/
- topic_name_2/
- ... and so on.
- per_run/
-
plots/
- Velocity and trajectory plots generated from CSV files.
-
errors/
- CSV files containing computed position and velocity errors for each run.
- Place your ROS bag files inside a folder (
bag_folder). - Prepare your configuration file (
config.yaml) according to your ROS topics. - Include in the same folder as your ROS bags, the .yaml containing the GNSS waypoints of the experiment.
Example config.yaml structure:
topics:
estimated_position:
name: "/odometry/global"
trajectory_plan:
name: "/move_base/TEBPlannerROS/global_plan"
gps_plan:
name: "/gnss_left/fix"
waypoints_coords:
name: "demo_baylands.yaml"
You can use this repository either as a Python library, calling individual functions within your own code, or run it as a standalone script that automatically processes the bag files—handling conversion, plotting, and error calculations in one go.
From the root of the repository, run:
cd scripts/packaged/Then run the code:
python fullAnalysis.py --bag_folder <path-to-ros-bags> --config_path config.yamlTo use it as a library, there are some obligatory commands, the script must be executed in the following order in main():
- load_config
- get_sorted_bag_mapping
- convert_bags_to_csv
- organize_csv_per_topic
- calculate errors
- plot functions
This library generates visualizations and numerical evaluations of your robot's performance by comparing ground-truth data with planned or estimated trajectories and velocities.
Errors are calculated along three axes — X, Y, and Z — using the following metrics:
-
RMSE (Root Mean Square Error)
Measures the standard deviation of the differences between predicted and actual values. A lower RMSE indicates better performance. -
Mean Absolute Error (MAE)
The average magnitude of errors in each axis, giving a direct sense of how far off the values are on average. -
Max Absolute Error
The single largest deviation observed for each axis, useful for identifying worst-case behavior.
The following types of errors are computed:
-
Position Error:
Compares estimated robot positions against ground-truth (e.g., from localization vs. odometry). -
Yaw Error (Orientation):
Specifically compares the X component of quaternion orientation to assess heading error.
All errors are saved as CSV files in the errors/ directory and aggregated for all specified runs.
ROS Bag File Format Requirement
This tool requires your ROS bag files to follow the default ROS naming convention, which looks like this:
YYYY-MM-DD-HH-MM-SS.bagExample:
2025-04-11-13-55-04.bagFiles that do not match this exact format will be ignored during processing.
This naming convention is used to determine the temporal order of the bags (oldest to newest) before assigning them internally asrun_0,run_1, etc.Valid:
2024-12-01-08-00-00.bag
Invalid:test_run1.bag,04112025_13_55_04.bag,run0.bag
Plots are automatically generated from CSV data and saved in the plots/ folder. These help visually assess the system's behavior and compare it to expectations.
-
Trajectory Plots:
- 2D trajectory comparision (Ground Truth GPS vs. estimated odometry) of executed paths.
- Optional offset to origin for alignment and easier visual comparison.
-
Distance to waypoints:
- Distance (in meters) until reach each of the fisrt three waypoints.
Each plot is saved as a PNG image and named accordingly (e.g., distance_to_waypoints_run_0.png, trajectory_comparison_run_1.png, etc.).
The following steps illustrate a typical usage of the library by walking through the main() function. Each function call processes ROS bag data and generates structured outputs, plots, and evaluation metrics.
Load your topic definitions (names, types, and CSV output filenames) from a YAML config file.
topics = load_config("config.yaml")Loads topic metadata required for all downstream steps.
Sort your bag files in chronological order.
get_sorted_bag_mapping(bag_folder)Convert .bag files into individual CSV files, one folder per run.
convert_bags_to_csv(bag_folder, num_bags, topics)Creates csv_files/per_run/run_X/ folders, each with CSVs for all topics.
Reorganize per-run CSVs into per-topic folders.
organize_csv_per_topic(bag_folder, num_bags, topics)Creates csv_files/per_topic/topic_name/ folders for analysis.
Iterate through each run to calculate position errors (GPS vs. Odometry) and length drift, saving the results to CSV files within the errors directory.
for run_id in run_ids:
# Position Errors
pos_errors = calculate_position_error_gps_vs_odometry(bag_folder, run_id, topics)
save_errors_to_csv(pos_errors, bag_folder, run_id)
# Drift Errors
drift_errors = calculate_length_drift_error(bag_folder, run_id, topics)
save_errors_to_csv(drift_errors, bag_folder, run_id, label="length_drift")Generates error reports in errors/run_X_...csv for quantitative analysis.
Calculate total path lengths and trajectory efficiency to evaluate the robot's performance consistency.
calculate_and_save_path_lengths(bag_folder, run_id, topics)
calculate_trajectory_efficiency_error(bag_folder, run_id, topics)Computes and saves metrics regarding the distance traveled and path efficiency.
Create visualizations for distance to specific waypoints and compare the estimated odometry trajectory against the GPS ground truth.
# Plot distance to waypoints
plot_distance_to_waypoints(bag_folder, run_id, topics, waypoint_indices=[0, 1, 2, 3])
# Plot trajectory comparison
plot_single_trajectory_or_comparison(
bag_folder, run_id, topics,
plot_estimated_trajectory=True,
plot_gps_trajectory=True,
offset_est=False,
offset_gps=False
)Saves visual plots in the plots/ directory to facilitate manual inspection of the robot's behavior.
Below is a summary of the core functions provided by this library. These functions are designed to streamline the process of working with ROS bag files, organizing data, plotting results, and evaluating performance metrics.
-
load_config(config_path)
Loads the YAML configuration file with topic names and types.
Usage:topics = load_config("path/to/config.yaml")
-
get_sorted_bag_mapping(bag_folder
Scans for.bagfiles in the folder and returns a dictionary mappingrun_Xfile path, sorted by modification time.Usage:
python bag_mapping = get_sorted_bag_mapping("path/to/bag_folder")
-
convert_bags_to_csv(bag_folder, num_bags, topics)
Converts.bagfiles into CSV format. Createscsv_files/per_runwith separated CSVs per run.
Usage:convert_bags_to_csv("path/to/bag_folder", 2, topics)
-
organize_csv_per_topic(bag_folder, num_bags, topics)
Organizes CSVs into folders per topic for downstream processing.
Usage:organize_csv_per_topic("path/to/bag_folder", 2, topics)
-
extract_poses_from_csv(input_csv, output_csv)
Parses pose data from complex CSVs (e.g., trajectory plans) and rewrites them into structured format. -
parse_pose_block(pose_block)
Helper to extract position and orientation from raw YAML-style blocks.
-
plot_single_trajectory_or_comparison(bag_folder, run_id, topics, ...)Generates a 2D plot comparing the Estimated Trajectory (Odometry) against the GPS Trajectory (Ground Truth). It can also plot the waypoints. It supports offsetting trajectories to the origin (0,0) for easier visual comparison of shapes.
Usage:plot_single_trajectory_or_comparison( bag_folder, run_id=0, topics=topics, plot_estimated_trajectory=True, plot_gps_trajectory=True, offset_est=False, offset_gps=False )
-
plot_distance_to_waypoints(bag_folder, run_id, topics, waypoint_indices)Plots the Euclidean distance from the robot to specific waypoints over time. It visually marks the exact timestamp when the robot arrived (distance < threshold) at a specific waypoint.
Usage:# Plot distance to the first 4 waypoints plot_distance_to_waypoints(bag_folder, 0, topics, waypoint_indices=[0, 1, 2, 3])
-
calculate_position_error_gps_vs_odometry(bag_folder, run_id, topics)Computes the Root Mean Square Error (RMSE) and Mean Absolute Error (MAE) between the Estimated Odometry and the GPS Ground Truth.
Note: This function automatically synchronizes the two time-series (via interpolation) and converts GPS Lat/Lon to local X/Y coordinates before comparison. Usage:errors = calculate_position_error_gps_vs_odometry(bag_folder, 0, topics) # Returns: {'rmse': {'x': ..., 'y': ...}, 'mae': {...}} # Saves to: errors/errors_position_run_0.csv
-
calculate_length_drift_error(bag_folder, run_id, topics)Calculates the difference in total path length measured by Odometry versus GPS. This is useful for identifying odometry scaling issues (e.g., wheel radius calibration).
Usage:calculate_length_drift_error(bag_folder, 0, topics) # Saves to: errors/length_drift_error_run_0.csv
-
calculate_trajectory_efficiency_error(bag_folder, run_id, topics)Evaluates how efficient the robot's path was by comparing the GPS path length (actual distance traveled) against the Minimal Waypoint path length (ideal straight lines between waypoints).
Usage:calculate_trajectory_efficiency_error(bag_folder, 0, topics) # Saves to: errors/trajectory_efficiency_error_run_0.csv
-
calculate_and_save_path_lengths(bag_folder, run_id, topics)A helper function that computes Odometry length, GPS length, and Minimal length simultaneously and saves them to a consolidated CSV for general comparison.
Usage:calculate_and_save_path_lengths(bag_folder, 0, topics) # Saves to: path_lengths/path_lengths_run_0.csv
- CSV file naming and topic definitions in your configuration file must match exactly, so please do not move or rename any folder or file.
- Some functions issue warnings if expected data or CSV files are missing or incorrectly formatted.