Skip to main content

robot-keyframe-kit

A generalizable MuJoCo keyframe editor for creating and editing robot motion sequences. Works with any MuJoCo-compatible robot model.

🎬 Video Tutorial

Watch the Tutorial

▶️ Click to watch the full tutorial on YouTube

Installation

pip install robot-keyframe-kit

Development Setup (Conda)

For contributors, use an editable install so local code changes are reflected immediately.

git clone https://github.com/Stanford-TML/robot_keyframe_kit.git
cd robot_keyframe_kit

conda create -n robot_keyframe_kit python=3.10 -y
conda activate robot_keyframe_kit

python -m pip install -e ".[dev]"

# Optional: download MuJoCo Menagerie assets for local testing/examples
bash scripts/setup_assets.sh

Verify the editable install and CLI entrypoint:

python -c "import robot_keyframe_kit; print(robot_keyframe_kit.__file__)"
keyframe-editor --help

Optional example (after running bash scripts/setup_assets.sh):

keyframe-editor assets/mujoco_menagerie/toddlerbot_2xc/scene.xml --name toddlerbot_2xc

Quick Start

For best results, use a scene.xml file that includes your robot model along with proper floor setup.

keyframe-editor /path/to/scene.xml --name my_robot

Most robot models from mujoco_menagerie include a scene.xml file. For example:

keyframe-editor /path/to/mujoco_menagerie/unitree_g1/scene.xml --name g1

Using Robot-Only XML

If you only have a robot XML file (without scene setup), the editor will automatically:

  1. Detect that no floor plane exists
  2. Check for a scene.xml in the same directory and suggest using it
  3. Auto-generate a scene wrapper with floor plane for physics collision
keyframe-editor /path/to/robot.xml --name my_robot

Note: For better visualization and physics, create or use a proper scene.xml.

Creating a Scene XML

If your robot model doesn't have a scene.xml, you can create one:

<mujoco model="my_robot_scene">
  <!-- Include your robot model -->
  <include file="robot.xml"/>

  <!-- Add floor and lighting -->
  <asset>
    <texture type="2d" name="groundplane" builtin="checker" 
             rgb1="0.2 0.3 0.4" rgb2="0.1 0.2 0.3"
             markrgb="0.8 0.8 0.8" width="300" height="300"/>
    <material name="groundplane" texture="groundplane" 
              texuniform="true" texrepeat="5 5" reflectance="0.2"/>
  </asset>

  <worldbody>
    <light pos="0 0 3.5" dir="0 0 -1" directional="true"/>
    <geom name="floor" type="plane" size="10 10 0.05" material="groundplane"/>
  </worldbody>
</mujoco>

Command-Line Options

keyframe-editor <xml_path> [OPTIONS]

Required Arguments

  • xml_path: Path to the MuJoCo XML file (scene.xml recommended, or robot.xml)

Optional Arguments

  • --name <name>: Name for this project (used in save filenames). Default: robot
  • --root-body <body_name>: Name of the root body for ground alignment. Auto-detected if not specified.
  • --config <path>: Path to YAML configuration file. Overrides auto-detection.
  • --generate-config <path>: Generate a YAML configuration file from the model and exit.
  • --data <path>: Path to load existing keyframe data from.
  • --save-dir <dir>: Directory to save keyframe data. Default: keyframes
  • --no-auto-floor: Disable automatic floor injection for robot-only XML files.

Configuration Files

You can create a YAML configuration file to customize robot-specific settings:

name: my_robot
root_body: base_link
end_effector_sites:
  - left_foot
  - right_foot
mirror_pairs:
  left_hip_pitch: right_hip_pitch
  left_knee: right_knee
mirror_signs:
  left_hip_pitch: -1
  left_knee: -1
dt: 0.02
save_dir: keyframes
scene:
  auto_inject_floor: true
  show_floor: true

Generate a default config from your model:

keyframe-editor robot.xml --generate-config config.yaml

Features

  • Visual-Centric Joint Control: Control motion joints intuitively
  • Automatic Mechanism Detection: Handles differential drives, gear couplings, and parallel linkages
  • Mirror Mode: Automatically mirrors joint movements with correct sign conventions
  • Physics Simulation: Test keyframes and trajectories with full MuJoCo physics
  • Ground Placement: Automatically places robot on ground based on lowest collision geometry
  • End-Effector Tracking: Auto-detects and tracks end-effector sites/bodies
  • Mink IK Solver: QP-based IK for end-effector target solving

Python API

You can also use the editor programmatically:

from robot_keyframe_kit import ViserKeyframeEditor, EditorConfig

# Load config from file
config = EditorConfig.from_yaml("config.yaml")

# Or create config programmatically
config = EditorConfig(
    name="my_robot",
    root_body="base_link",
    auto_inject_floor=True,
    show_floor=True,
)

# Create editor
editor = ViserKeyframeEditor(
    "scene.xml",
    config=config,
)

# Editor runs until interrupted

Save File Format

Motion data is saved as LZ4-compressed pickle files (.lz4) using joblib. Files are saved to {save_dir}/{name}/{motion_name}.lz4.

Loading Save Files

import joblib

data = joblib.load("keyframes/my_robot/walk.lz4")

File Structure

Key Type Description
keyframes List[dict] List of keyframe dictionaries (see below)
timed_sequence List[Tuple[str, float]] Sequence of (keyframe_name, duration_sec) pairs
time ndarray (T,) Timestamps for each trajectory frame
qpos ndarray (T, nq) Full MuJoCo qpos at each frame
motor_vel ndarray (T, n_motors) Motor/actuator joint velocities (rad/s)
joint_vel ndarray (T, n_joints) UI-visible joint velocities (rad/s)
action ndarray (T, nu) or None Motor commands (if action trajectory was played)
body_pos ndarray (T, nbody, 3) Body positions (world or relative frame)
body_quat ndarray (T, nbody, 4) Body orientations as quaternions (w, x, y, z)
body_lin_vel ndarray (T, nbody, 3) Body linear velocities
body_ang_vel ndarray (T, nbody, 3) Body angular velocities
site_pos ndarray (T, n_sites, 3) End-effector site positions
site_quat ndarray (T, n_sites, 4) End-effector site orientations
is_robot_relative_frame bool Whether poses are in robot-relative frame

Keyframe Dictionary Structure

Each keyframe in the keyframes list contains:

Key Type Description
name str Human-readable keyframe name
motor_pos ndarray (nu,) Motor/actuator positions
joint_pos ndarray (nj,) or None Joint positions (may differ from motor_pos with transmissions)
qpos ndarray (nq,) or None Full MuJoCo qpos including base pose

Example Usage

import joblib
import numpy as np

# Load motion data
data = joblib.load("keyframes/toddlerbot/wave.lz4")

# Get keyframes
for kf in data["keyframes"]:
    print(f"Keyframe: {kf['name']}, motor_pos shape: {kf['motor_pos'].shape}")

# Get trajectory
times = data["time"]  # (T,)
qpos = data["qpos"]   # (T, nq)
print(f"Trajectory: {len(times)} frames, {times[-1]:.2f}s duration")

# Get timed sequence for playback
for keyframe_name, duration in data["timed_sequence"]:
    print(f"  {keyframe_name}: {duration}s")

Troubleshooting

Robot Falls Through Floor

  • Check: Does your XML have a floor plane? Use scene.xml if available.
  • Solution: The editor auto-injects a floor, but collision filtering may need adjustment.
  • Best Fix: Use a proper scene.xml with correct collision settings.

Slow Physics Simulation

  • Check: Model timestep settings (model.opt.timestep)
  • Solution: Editor uses n_frames=20 substeps per control step for stability.

Wrong Joint Selection

  • Check: Are you seeing motor joints instead of motion joints?
  • Solution: The editor auto-detects differential drives and gear mechanisms. Check your config for manual overrides.

Citation

If you find this tool useful for your research, please consider citing:

@misc{yang2026locomotion,
  title = {Locomotion {{Beyond Feet}}},
  author = {Yang, Tae Hoon and Shi, Haochen and Hu, Jiacheng and Zhang, Zhicong and Jiang, Daniel and Wang, Weizhuo and He, Yao and Wu, Zhen and Chen, Yuming and Hou, Yifan and Kennedy, Monroe and Song, Shuran and Liu, C. Karen},
  year = 2026,
  month = jan,
  number = {arXiv:2601.03607},
  eprint = {2601.03607},
  primaryclass = {cs},
  publisher = {arXiv},
  doi = {10.48550/arXiv.2601.03607},
  urldate = {2026-01-08},
  archiveprefix = {arXiv},
  keywords = {Computer Science - Robotics}
}

@article{shi2025toddlerbot,
  title={ToddlerBot: Open-Source ML-Compatible Humanoid Platform for Loco-Manipulation},
  author={Shi, Haochen and Wang, Weizhuo and Song, Shuran and Liu, C. Karen},
  journal={arXiv preprint arXiv:2502.00893},
  year={2025}
}

License

MIT License

Metadata

Release files for robot-keyframe-kit 0.3.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for robot-keyframe-kit 0.3.5
File Size Uploaded
robot_keyframe_kit-0.3.5.tar.gz 66.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for robot-keyframe-kit 0.3.5
File Interpreter ABI Platform
robot_keyframe_kit-0.3.5-py3-none-any.whl Python 3 none any Details

Total release size: 132.1 kB

Release files / robot_keyframe_kit-0.3.5.tar.gz

Download URL robot_keyframe_kit-0.3.5.tar.gz
Size 66.8 kB
Tags Source
SHA-256 checksum
How to use checksums
38f0231f2fc8a19286134176e298b0c5efe3f3b53ef4ce36879355e2ef3255a3
BLAKE2b-256 checksum
How to use checksums
f85ec18fdbe8e0204c1486dae8f4d3708f506598222ad028081741002342dff5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.7

Release files / robot_keyframe_kit-0.3.5-py3-none-any.whl

Download URL robot_keyframe_kit-0.3.5-py3-none-any.whl
Size 65.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
95ebbae46e9339934a089230c5eb93e57ebb4c1a7cb990399fdf9e590352d097
BLAKE2b-256 checksum
How to use checksums
e594dd5c6159a8c0a80550eff4a725256783791a7664ed15c085e63c3374921a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.7

Release history Release notifications | RSS feed

This release

0.3.5 This release

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page