A large, high-quality dynamics dataset of the Mini Wheelbot. The dataset contains 1 kHz data of all onboard sensor readings, the estimated state, ground-truth pose measurements from a motion capture system, and a third-person view video of the experiment. We perform a variety of experiments using pseudo-random binary excitation signals (PRBS) as setpoints of a linear controller, an MPC for driving, and an RL policy that races along a track. Experiments are performed across multiple hardware instances and on different surfaces. With this dataset, we hope to encourage researchers to use the Mini Wheelbot to benchmark their learning-based control methods, even without access to the real hardware. We include two example implementations of how to use the dataset, i.e., for dynamics learning and state estimation. A detailed description of this dataset is available in the brief on arxiv.
If you find this dataset helpful, please cite the Mini Wheelbot paper and/or dataset directly:
@inproceedings{hose2025mini,
title={The {Mini Wheelbot}: A Testbed for Learning-based Balancing, Flips, and Articulated Driving},
booktitle={2025 IEEE International Conference on Robotics and Automation (ICRA)},
publisher={IEEE},
author={Hose, Henrik and Weisgerber, Jan and Trimpe, Sebastian},
year={2025},
}
@article{hose2026dataset,
title={The {Mini Wheelbot} Dataset: High-Fidelity Data for Robot Learning},
author={Hose, Henrik and Brunzema, Paul, and Subhasish, Devdutt and Trimpe, Sebastian},
year={2026},
}The Wheelbot Dataset contains trajectory data from a self-balancing wheeled robot across various experimental conditions including:
- Pitch experiments: Random pitch angle tracking
- Roll experiments: Random roll angle tracking
- Velocity experiments: Forward/backward velocity tracking
- Combined experiments: Velocity + roll, velocity + pitch
- Yaw experiments: Random yaw control, circular trajectories, figure-eight patterns
All data is recorded at 1000 Hz and includes:
- IMU data (4x gyroscopes, 4x accelerometers)
- Robot state (yaw, roll, pitch angles and velocities)
- Wheel positions, velocities, and accelerations
- Motor commands
- Setpoints
- Vicon motion capture data (ground truth)
- Battery voltage
pip install wheelbot-datasetgit clone https://github.com/wheelbot/dataset.git
cd dataset
pip install -e .# For development and examples
pip install wheelbot-dataset[dev]
# For all features (neural network training, etc.)
pip install wheelbot-dataset[all]The dataset is automatically downloadable from Zenodo:
# Download dataset to ./data directory
python -m wheelbot_dataset download download
# Or download to a custom location
python -m wheelbot_dataset download download --output_dir=my_dataset
# Check if dataset exists
python -m wheelbot_dataset download checkFrom Python:
from wheelbot_dataset import download_dataset, check_dataset
# Download the dataset
download_dataset(output_dir="data")
# Check dataset status
check_dataset("data")from wheelbot_dataset import Dataset
# Load the dataset
ds = Dataset("data")
# Load a specific experiment group
pitch_group = ds.load_group("pitch")
# Access individual experiments
exp = pitch_group[0]
# View the data
print(exp.data.head()) # Pandas DataFrame
print(exp.meta) # Metadata dictionary# Cut off standup and laydown phases
exp_cut = exp.cut_by_condition(
start_condition=lambda df: df['/tau_DR_command/reaction_wheel'].abs() > 0,
end_condition=lambda df: df['/tau_DR_command/reaction_wheel'].abs() == 0
).cut_time(start=2.0, end=2.0)
# Apply filtering
import scipy.signal as signal
def lowpass_filter(df):
b, a = signal.butter(4, 2*50/1000, btype="low")
df_filtered = df.copy()
for col in df.columns:
df_filtered[col] = signal.filtfilt(b, a, df[col])
return df_filtered
exp_filtered = exp_cut.apply_filter(lowpass_filter).resample(dt=0.01)# Filter entire groups or datasets
group_filtered = pitch_group.map(
lambda exp: exp
.filter_by_metadata(experiment_status="success")
.cut_time(start=2.0, end=2.0)
.apply_filter(lowpass_filter)
.resample(dt=0.01)
)
# Filter by metadata
successful_exps = ds.map(
lambda exp: exp.filter_by_metadata(experiment_status="success")
)from wheelbot_dataset import plot_timeseries
plot_fields = {
"Angles": ["/q_yrp/yaw", "/q_yrp/roll", "/q_yrp/pitch"],
"Angular Velocities": ["/dq_yrp/yaw_vel", "/dq_yrp/roll_vel", "/dq_yrp/pitch_vel"],
"Motor Commands": ["/tau_DR_command/drive_wheel", "/tau_DR_command/reaction_wheel"],
}
plot_timeseries(
experiments=exp_filtered,
groups=plot_fields,
pdf_path="output.pdf"
)from wheelbot_dataset import plot_histograms
plot_histograms(exp_filtered, "histograms.pdf")
plot_histograms(pitch_group, "group_histograms.pdf")
plot_histograms(ds, "dataset_histograms.pdf")# Single experiment
columns = ["time"] + list(exp.data.columns)
exp_numpy = exp.to_numpy(columns)
# Entire group
group_numpy = group.map(lambda exp: exp.to_numpy(columns))from wheelbot_dataset import to_prediction_dataset
fields_states = [
"/q_yrp/roll", "/q_yrp/pitch",
"/dq_yrp/yaw_vel", "/dq_yrp/roll_vel", "/dq_yrp/pitch_vel",
"/dq_DR/drive_wheel", "/dq_DR/reaction_wheel",
]
fields_actions = [
"/tau_DR_command/drive_wheel",
"/tau_DR_command/reaction_wheel",
]
# One-step prediction dataset
states, actions, nextstates, _ = to_prediction_dataset(
ds_filtered,
fields_states=fields_states,
fields_actions=fields_actions,
N_future=1
)
# Multi-step prediction dataset
states, actions, nextstates, _ = to_prediction_dataset(
ds_filtered,
fields_states=fields_states,
fields_actions=fields_actions,
N_future=100
)
print(f"States shape: {states.shape}")
print(f"Actions shape: {actions.shape}")
print(f"Next states shape: {nextstates.shape}")Get comprehensive statistics about your dataset:
python -m wheelbot_dataset consolidate statistics --dataset_path=dataThis generates a LaTeX table with:
- Number of trajectories per experiment type
- Total duration (with configurable cutoff)
- Number of crashes/failed experiments
Check the actual update rates of different sensor signals:
python -m wheelbot_dataset consolidate updaterates \
--dataset_path=data \
--group_name=pitch \
--index=4data/
βββ pitch/ # Pitch angle tracking experiments
β βββ 0.csv
β βββ 0.meta
β βββ 0.mp4
β βββ ...
βββ roll/ # Roll angle tracking experiments
βββ roll_max/ # Maximum roll angle experiments
βββ velocity/ # Forward/backward velocity
βββ velocity_pitch/ # Combined velocity and pitch
βββ velocity_roll/ # Combined velocity and roll
βββ yaw/ # Random yaw control
βββ yaw_circle/ # Circular trajectories
βββ yaw_figure_eight/ # Figure-eight trajectories
Each experiment includes:
.csv- Time series data at 1000 Hz.meta- JSON metadata (robot ID, surface, experiment status).mp4- Video recording.log- Raw log file.pkl- Setpoint data.preview.pdf- Quick visualization.setpoints.pdf- Setpoint visualization
Comprehensive examples are available in the examples/ directory:
- Complementary filter for orientation estimation
- Comparison with onboard estimates and Vicon ground truth
- Run with:
python examples/estimator/complementary_filter.py
- Neural network-based dynamics learning with JAX/Equinox
- One-step and multi-step prediction models with curriculum learning
- Dataset export and model training scripts
- Model evaluation and comparison plots
- Transformer-based classification for surface detection
- Robot identification from IMU data
- Control mode classification (autonomous vs. human)
A comprehensive example demonstrating the main features of the package:
# Run the basic usage example
python examples/basic_usage.pyThe example script shows:
- Loading datasets and experiment groups
- Cutting and filtering data
- Applying custom filters (e.g., lowpass)
- Resampling data
- Batch processing with map operations
- Plotting time series and histograms
- Exporting to NumPy arrays
- Creating training datasets for machine learning
/gyro{0-3}/{x,y,z}- Angular velocities from 4 gyroscopes/accel{0-3}/{x,y,z}- Linear accelerations from 4 accelerometers
/q_yrp/{yaw,roll,pitch}- Euler angles (rad)/dq_yrp/{yaw_vel,roll_vel,pitch_vel}- Angular velocities (rad/s)/q_DR/{drive_wheel,reaction_wheel}- Wheel positions (rad)/dq_DR/{drive_wheel,reaction_wheel}- Wheel velocities (rad/s)/ddq_DR/{drive_wheel,reaction_wheel}- Wheel accelerations (rad/sΒ²)
/tau_DR_command/{drive_wheel,reaction_wheel}- Motor torque commands (Nβ m)
/setpoint/{yaw,roll,pitch}- Target Euler angles/setpoint/{yaw_rate,roll_rate,pitch_rate}- Target angular velocities/setpoint/driving_wheel_angle- Target wheel angle/setpoint/driving_wheel_angular_velocity- Target wheel velocity
/vicon_position/{x,y,z}- Position from Vicon (m)/vicon_orientation_wxyz/{w,x,y,z}- Quaternion orientation
battery/voltage- Battery voltage (V)
For information on recording new trajectories, see README_RECORDING.md.