evo

1.35.2 · active · verified Thu Apr 16

evo is a Python package for the evaluation of odometry and SLAM (Simultaneous Localization and Mapping) algorithms. It provides a robust command-line interface and a modular Python library for handling, evaluating, and comparing trajectory outputs from various formats like TUM, KITTI, EuRoC MAV, and ROS bagfiles. It includes tools for association, alignment, scale adjustment (for monocular SLAM), flexible output, plotting, and visualization. The library is actively maintained, with the current version being 1.35.2, and supports Python 3.10+.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to programmatically load two dummy TUM trajectories, associate them based on timestamps, align the estimated trajectory to the reference using Umeyama's method, calculate the Absolute Pose Error (APE) for the translation part, and print the resulting statistics. Finally, it visualizes the aligned trajectories using Matplotlib. In a real application, replace the dummy file creation with loading your actual trajectory files.

import os
import numpy as np
from evo.core import metrics, sync
from evo.core.trajectory import PoseTrajectory3D
from evo.tools import file_interface, plot
from evo.tools.settings import SETTINGS
import matplotlib.pyplot as plt

# Create dummy trajectory files for demonstration
# In a real scenario, these would be actual ground truth and estimated trajectories
ref_file_content = """
1.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0
2.0 1.0 0.0 0.0 0.0 0.0 0.0 1.0
3.0 2.0 0.0 0.0 0.0 0.0 0.0 1.0
4.0 3.0 0.0 0.0 0.0 0.0 0.0 1.0
"""
est_file_content = """
1.0 0.1 0.0 0.0 0.0 0.0 0.0 1.0
2.0 1.1 0.0 0.0 0.0 0.0 0.0 1.0
3.0 2.1 0.0 0.0 0.0 0.0 0.0 1.0
4.0 3.1 0.0 0.0 0.0 0.0 0.0 1.0
"""

# Save dummy files
dummy_dir = "./evo_quickstart_data"
os.makedirs(dummy_dir, exist_ok=True)
ref_path = os.path.join(dummy_dir, "ref.tum")
est_path = os.path.join(dummy_dir, "est.tum")

with open(ref_path, "w") as f: f.write(ref_file_content)
with open(est_path, "w") as f: f.write(est_file_content)

# 1. Load trajectories (TUM format in this example)
traj_ref = file_interface.read_tum_trajectory_file(ref_path)
traj_est = file_interface.read_tum_trajectory_file(est_path)

# 2. Associate trajectories by timestamps
traj_ref, traj_est = sync.associate_trajectories(traj_ref, traj_est, max_diff=0.1)

# 3. Align trajectories (e.g., SE(3) Umeyama alignment)
traj_est_aligned = traj_est.copy()
traj_est_aligned.align(traj_ref)

# 4. Calculate Absolute Pose Error (APE)
ape_metric = metrics.APE(metrics.PoseRelation.translation_part)
ape_stats = ape_metric.process_trajectory(traj_ref, traj_est_aligned)

print("\n--- APE Statistics (Translation Part) ---")
print(f"RMSE: {ape_stats.rmse:.4f}")
print(f"Mean: {ape_stats.mean:.4f}")
print(f"Max: {ape_stats.max:.4f}")

# 5. Plotting (optional)
SETTINGS.plot_usetex = False # Disable LaTeX for simpler plotting
fig = plt.figure(figsize=(10, 8))
plot.trajectories(fig, {"reference": traj_ref, "estimate_aligned": traj_est_aligned}, plot.PlotMode.xyz)
plt.title("Trajectories (Aligned)")
plt.show()

# Clean up dummy files and directory
os.remove(ref_path)
os.remove(est_path)
os.rmdir(dummy_dir)

view raw JSON →