Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PiDog Quadruped Locomotion via Reinforcement Learning and Sim2Real

A locomotion RL policy for the Sunfounder PiDog: trained in simulation, deployed on the robot's onboard Raspberry Pi 4.

The starting problem is that Sunfounder publishes no URDF and no CAD model for PiDog — a moderator confirmed as much on their own forum — and no community model exists either. So the robot description here is derived from the ground-truth kinematic constants hardcoded in Sunfounder's own control library (sunfounder/pidog) and its servo driver (sunfounder/robot-hat), rather than measured off a drawing that doesn't exist.

That origin shapes the whole repo: every constant is labelled with where it came from. Sourced, derived, or estimated — never silently mixed.


Status

Task State
1. URDF + joint limits derived from pidog.py done, validated in MuJoCo
2. Real mass / inertia measurements partly — bugs fixed, numbers pending
3. Isaac Lab training environment scaffolded, not yet run on a GPU
4. ONNX export + on-robot bridge not started

Layout

urdf_description/     the robot model and how it was derived
  generate_urdf.py      SINGLE SOURCE OF TRUTH -- edit constants, re-run
  derive_joint_limits.py  reproduces pidog.py's IK; derives the joint limits
  validate_urdf.py      loads in MuJoCo, cross-checks FK against that IK
  MEASUREMENTS.md       worksheet of what still needs a scale and calipers
  README.md             sourced vs derived vs estimated, constant by constant

urdf/pidog.urdf       generated output -- never hand-edit, it gets overwritten

pidog_rl/             sim-agnostic layer, shared by training and deployment
  hardware.py           every "what the real robot does" constant, cited
  servo_model.py        latency / slew / backlash model for domain randomization

isaac/                Isaac Lab training environment (see isaac/README.md)
tests/                local tests -- no Isaac Sim, no GPU required

Getting started

Nothing here needs a GPU except the actual training run.

# regenerate the robot description
python urdf_description/generate_urdf.py

# reproduce the joint-limit derivation from pidog.py's own IK
python urdf_description/derive_joint_limits.py

# load it in MuJoCo, check FK against that IK, render a pose
python urdf_description/validate_urdf.py

# test the sim-agnostic layer
python tests/test_hardware_and_servo.py

validate_urdf.py needs mujoco; the tests need torch. Training additionally needs Isaac Sim and Isaac Lab on an NVIDIA RTX machine — see isaac/README.md.

The three constraints that shape every design decision

1. The robot cannot feel its own legs

PiDog has no joint encoders and no torque sensing. At deploy time the only proprioception is the SH3001 IMU and the angles the policy itself commanded. Standard quadruped RL environments feed measured joint positions and velocities into the policy; doing that here trains something that cannot be deployed at all — and it fails silently, learning beautifully in sim and then flailing on hardware.

So the policy observation is restricted to what the robot can actually sense, and a test in tests/ statically parses the environment and fails if a non-observable term ever leaks in. The critic is allowed privileged state, since it is discarded at export.

2. The IMU is fresh at 20 Hz, so control runs at 20 Hz

pidog.py's _imu_thread sleeps 0.05 s between sensor reads. Training at 200 Hz and deploying at 20 Hz is a classic silent sim-to-real gap, so the environment pins its control period to the real sensor rate.

3. The servos are the hard part, not the compute

An RPi 4 runs a small MLP inside a 50 ms control period without difficulty. The real risk is the open-loop hobby servo between the action and the world: command latency, a 428 °/s slew ceiling, gear backlash, and stale zero calibration. pidog_rl/servo_model.py models all four and randomizes them per episode.

Working style

These are load-bearing, not preferences:

  • generate_urdf.py is the only place the URDF is written. Edit the constants block and re-run. urdf/pidog.urdf is generated output.
  • Every constant is labelled by provenance. # EST marks a guess and stays until a real measurement replaces it. Sourced constants cite the file and symbol they came from. Derived constants cite the script that derives them.
  • Validate by behaviour, not by parsing. A URDF change is checked by loading it in MuJoCo and confirming its forward kinematics reproduce pidog.py's inverse kinematics — not by confirming the XML is well-formed.

Provenance summary

Sourced (exact, from pidog.py / robot_hat): link lengths 42/76 mm, hip mount rectangle 117×98 mm, 2-DOF sagittal-only legs, 3-DOF head with its 45° pitch offset, servo command clamp ±90°, slew ceilings 428/300/500 °/s, servo interpolation at 100 Hz, IMU at 20 Hz.

Derived (reproducible via derive_joint_limits.py): hip and knee limits, the knee's 90° mechanical zero offset, and the leg joint axis direction — which determines which way the robot walks. Details in urdf_description/README.md.

Estimated (still guesses): all masses and inertias, the chassis bounding box, centre-of-mass offset, servo stall torque, and the neck/tail mount offsets. Listed with instructions in urdf_description/MEASUREMENTS.md.

Credits

Kinematic constants, IK, gait tables and servo timing all reverse-engineered from sunfounder/pidog and sunfounder/robot-hat.

About

Training a quadruped locomotion policy with the SunFounder PiDog, using URDF description, Inverse Kinematics, Reinforcement Learning through Isaac Sim, and Sim2Real Transfer

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages