A system identification routine for IsaacLab and Mujoco, to estimate motor parameters, inertia, mass, and center of mass. It provides scripts for data collection on the real robot (the robot should be in the air with the base fixed if a quadruped, or on a table if a manipulator). This repo interfaces directly with Pace and the new sys-id functionality of Mujoco.
The models (usd and xml) identified so far can be found in the folder robot_model.
| Robot | last modified XML | last modified USD | Identified |
|---|---|---|---|
| a2 | 2026-10-10 | 2026-09-30 | ✓ |
| aliengo | 2026-09-30 | 2026-09-30 | ✓ |
| b2 | 2026-09-30 | 2026-09-30 | |
| go2 | 2026-11-02 | 2026-09-30 | ✓ |
| hyqreal2 | 2026-09-30 | 2026-09-30 | X |
| pegasus | 2026-11-02 | 2026-09-30 | |
| piper_l | 2026-09-20 | 2026-09-30 | ✓ |
| z1 | 2026-09-19 | 2026-09-30 | ✓ |
-
install miniforge (x86_64 or arm64 depending on your platform) or pixi - the latter for full reproducibility.
-
create an environment using one of the files in the folder installation:
# for conda
conda env create -f mamba_environment_humble.yaml #for humble
conda env create -f mamba_environment_lyrical.yaml #for lyrical
conda activate sim2real_robot_identification_env
# for pixi
pixi shell --manifest-path installation/pixi.toml -e humble #for humble
pixi shell --manifest-path installation/pixi.toml -e lyrical #for lyrical- install IsaacLab and pace-sim2real (that is a submodule of this repo) if you need it
This repo works best with unitree-ros2-dls for communicating with unitree go2, b2, a2, aliengo and z1 robots, and with piper-ros2-dls2 for the agilex piper arm.
-
Choose the robot and the gains in the config file or add yours in the robot_model folder.
-
In the xml of your robot, add two keyframe (sys_id_1, sys_id_2) to define the start and end point of the chirp trajectory (see here for an example)
-
Runs one of the following files
python3 run_collection_quadruped_ros2.py
python3 run_collection_manipulator_ros2.py- Inside the script
startCollection
trajectory
chirp # or: excitationchirp moves all the joints together back and forth between the two keyframes. excitation (excitation_trajectory.py) stays in the same joint box, but gives every joint its own chirp plus a slow posture sweep, which makes the parameters easier to identify; it asks for a seed (use different seeds for the fit and the validation trajectories) and a speed scale in (0, 1] (default 0.5, the same motion slowed down; increase it once the motion looks safe), prints the joint ranges and peak velocities, and waits for confirmation. It is saved as excitation_N.pt.
- Close the script
ctrl+c- Visualize your runned trajectory
python3 datasets/replay_dataset_quadruped.py
python3 datasets/replay_dataset_manipulator.py
python3 datasets/plot_joint_trajectories.pyAdd a new task for a new robot. Then
python3 sysid_isaaclab/my_fit.py # CMA-ES (default): one best combination
python3 sysid_isaaclab/my_fit.py --optimizer ot # a set of plausible combinationsWith --optimizer ot, a diversity-regularized version of the optimal-transport optimizer of arXiv:2605.02147 (ot_optimizer.py) returns num_particles parameter combinations
where plausible_params.pt in the log folder, and the per-joint range of every parameter over the set is printed at the end (a wide range means that parameter is not identifiable from the data). The defaults are in OTSinkhornOptimizerCfg; to change them for a robot, add a field to its PaceCfg, e.g. ot: OTSinkhornOptimizerCfg = OTSinkhornOptimizerCfg(num_particles=64, loss_tolerance=0.05).
With both optimizers, the joint parameters are searched linearly within their bounds, as in PACE, and:
--identify-link-mass,--identify-center-of-mass(mass + CoM) and--identify-inertia-tensor(mass + CoM + inertia) also identify the inertial parameters of the bodies, with the same options of the MuJoCo fit (--inertial-bodies,--tie-quadruped-inertias, bounds). They are corrections of the nominal USD values: mass scale, CoM offset in the body frame (mirrored between legs when tied) and scales of the principal second moments of the mass distribution, so every value within the bounds is a physically consistent body. The identified values are saved inbody_params.pt(CMA-ES) or underinertialinplausible_params.pt(OT). On Newton, Isaac Lab warns that runtime CoM changes may be unstable: preferphysics=physxwith--identify-center-of-mass.
python3 sysid_mujoco/my_fit.py PRs are very welcome (search for TODO in the issue, or add what you like)!
This repository is maintained by Giulio Turrisi and Lorenzo Amatucci.

