Perception ◆ Nonlinear control ◆ University of Toronto, 2024 → re-tested 2026
Stairs and obstacles, seen once, then walked. A monocular network turns one photo into stair rise and run, or an obstacle's distance, depth and height; a five-link biped with knees turns that geometry into virtual-holonomic-constraint gaits that are hybrid limit cycles, pre-plans its steps and walks over the obstacle. Everything below was re-run from the archived code and data, and the parts that broke are reported as found.
Demonstration (1 min 20 s): the perception layer on a real staircase, the walker on flat ground, down a slope, up a 5° staircase and down a 10° staircase with treads and risers, and the geometric reason a knee-less biped cannot take steeper stairs.

Metric depth from a fine-tuned Metric3D v2, surface normals, two predominant normal directions (treads, risers), plane offsets clustered into a lattice. This scene: rise 14.2 cm, run 28.1 cm (tape: 12.0 / 29.6).

Virtual holonomic constraints tie the actuated joints to the stance-leg angle; hybrid invariance through the impact map, transversality and a virtual mass/potential test decide whether a stable limit cycle exists. Shown: the two-link curve; the five-link walker uses four Bézier curves.

Hybrid limit cycles for a RABBIT-style walker, verified against its return map. From one view of an obstacle the planner schedules the approach and two step-over gaits chained through the impact map, and the robot clears the box in collision-checked simulation.
Depth sensors on walking robots and exoskeletons are bulky; the 2024 study asked whether one RGB camera can recover the geometry that matters for a stair, its rise and run. Metric3D v2 was fine-tuned on a new dataset of 16,780 RGB-D images of indoor and outdoor stairs (Intel RealSense D415/D435, head-mounted), the metric depth was back-projected with the camera intrinsics, and planes were extracted from the point cloud.
The archived sample set has five scenes with the RGB image, the RealSense depth, the network's point cloud and normal map, and tape measurements of two steps per staircase. The re-implemented extractor works from surface normals instead of iterative RANSAC, which on these clouds fragments the grazing treads and fits planes across the nosing:
Deterministic, 0.09 s per scene from the RealSense cloud (0.32 s from the ASCII monocular cloud, dominated by parsing).



























The five archived scenes (8 June 2024, two buildings), one per row. Blue = tread points, red = riser points; dashed lines are the fitted lattices. Full-resolution panel in the report.
| scene | tape h | D435 h | mono h | tape b | D435 b | mono b |
|---|---|---|---|---|---|---|
| WE 17:51 | 14.2 | 16.5 | 10.7 | 27.1 | 19.3 | 25.9 |
| WE 18:27 | 19.5 | 19.6 | 19.9 | 25.3 | 25.1 | 23.3 |
| WI 17:41 | 12.0 | 15.1 | 15.5 | 29.6 | 31.2 | 33.5 |
| WI 17:47 | 12.0 | 14.2 | 12.0 | 29.6 | 28.1 | 28.3 |
| WI 18:12 | 15.0 | 15.7 | 18.0 | 32.1 | 33.3 | 27.7 |
| MAE [cm] | 1.7 | 2.1 | 2.5 | 2.5 |
All in cm. The tape values average the two measured steps. Largest misses: the WE 17:51 scene (camera pitched only 47°, risers nearly edge-on) and a worn concrete stair whose nosing strip reads 3 cm high on both clouds.


Dataset & data products
measurements.csv. The monocular depth tensors are empty files in the archive; the point clouds derived from them are intact.data_scripts/process.py), depth → PLY back-projection, rosbag point-cloud extractor with Open3D filtering, a RealSense ROS workspace and an RViz distance-measuring plugin used for the tape-measure protocol.
Recording rigs from the poster: a lower-limb exoskeleton with leg-mounted cameras and the head-mounted RealSense used for the stair scenes.
Five real staircases, one pass each. Left to right: the image, the metric depth, the surface normals (treads and risers are the two dominant directions), and the side profile with the fitted tread and riser planes against the tape measurement. Rise / run in cm: tape → estimate.




















The same layer inside the simulator
On the walker the depth camera sits in the head and is read at 1 Hz. Each frame becomes an organised point cloud, normals (3 px, stride 2), an up-facing mask (15°), a walking corridor (±0.35 m), height clusters (8 mm bins), extents from the raw cloud, a ramp plane fit, and the semantics: ground, crate (a short raised level with the floor continuing behind), stairs (monotone levels), drop. The perceived levels are merged into a world model in absolute coordinates; below is the live log of one run.
# online_box03: crate 10 cm high, 12 cm deep, 3.0 m ahead -> walking after 28 steps, 22.0 s simulated [ 0.00 s step 0] perceive (42 ms): levels z-0cm x0.26-2.92, z-0cm x3.43-4.54 [ 0.80 s step 0] touchdown: phase velocity 2.77 (gait's fixed point 2.94), theta 1.001 [ 0.80 s step 1] decide: regular 0.40 m (chained) [0.03 s] [ 1.00 s step 1] perceive (46 ms): levels z+0cm x0.67-2.94, z+0cm x3.37-4.04 [ 1.60 s step 1] touchdown: phase velocity 2.77 (gait's fixed point 2.78), theta 1.002 [ 1.60 s step 2] decide: regular 0.40 m (chained) [0.00 s] [ 2.00 s step 2] perceive (29 ms): levels z+0cm x1.08-2.96, z+0cm x3.33-4.40 [ 2.40 s step 2] touchdown: phase velocity 2.80 (gait's fixed point 2.78), theta 1.002 [ 2.40 s step 3] decide: regular 0.40 m (chained) [0.00 s] [ 3.00 s step 3] perceive (50 ms): levels z+0cm x1.49-2.99, z+0cm x3.27-5.02 [ 3.19 s step 3] touchdown: phase velocity 2.80 (gait's fixed point 2.80), theta 1.003 [ 3.19 s step 4] decide: regular 0.40 m (chained) [0.00 s] [ 3.98 s step 4] touchdown: phase velocity 2.80 (gait's fixed point 2.80), theta 1.002 [ 3.98 s step 5] decide: regular 0.40 m (chained) [0.00 s] [ 4.00 s step 5] perceive (74 ms): levels z+0cm x2.29-3.00, z+0cm x3.23-6.29 [ 4.77 s step 5] touchdown: phase velocity 2.77 (gait's fixed point 2.80), theta 1.001 [ 4.77 s step 6] decide: regular 0.40 m (chained) [0.00 s] [ 5.00 s step 6] perceive (45 ms): levels z+0cm x2.70-3.00, z+10cm x3.00-3.11, z+0cm x3.18-5.95 | stairs: up first riser 0.55 m, rise +10 cm, run nan cm, 1 treads [ 5.55 s step 6] touchdown: phase velocity 2.78 (gait's fixed point 2.77), theta 1.002 [ 5.55 s step 7] step-over plan: mode LT, leading step 0.57 m, library check failed -> transition re-designed, energy margins [0.13, 7.12] [ 5.55 s step 7] decide: leading leg over the box: 0.57 m step (transition redesigned) [47.45 s] [ 6.00 s step 7] perceive (48 ms): levels z+0cm x3.15-8.87 [ 6.45 s step 7] touchdown: phase velocity 3.47, theta 1.011 [ 6.45 s step 8] decide: trailing leg over the box (ends in the regular gait) (queued) [ 7.00 s step 8] perceive (39 ms): levels z+0cm x3.70-6.90 [ 7.09 s step 8] touchdown: phase velocity 2.73 (gait's fixed point 1.85), theta 1.003 [ 7.09 s step 9] decide: regular 0.40 m (chained) [0.00 s] [ 7.82 s step 9] touchdown: phase velocity 2.84 (gait's fixed point 2.71), theta 1.001 [ 7.82 s step 10] decide: regular 0.40 m (chained) [0.00 s] [ 8.00 s step 10] perceive (71 ms): levels z+0cm x4.51-7.75 [ 8.57 s step 10] touchdown: phase velocity 2.85 (gait's fixed point 2.78), theta 1.002 [ 8.57 s step 11] decide: regular 0.40 m (chained) [0.00 s] [ 9.00 s step 11] perceive (28 ms): levels z+0cm x4.92-8.14 [ 9.32 s step 11] touchdown: phase velocity 2.83 (gait's fixed point 2.79), theta 1.001 [ 9.32 s step 12] decide: regular 0.40 m (chained) [0.00 s] [ 10.00 s step 12] perceive (65 ms): levels z+0cm x5.33-9.01 [ 10.08 s step 12] touchdown: phase velocity 2.83 (gait's fixed point 2.79), theta 1.002 [ 10.08 s step 13] decide: regular 0.40 m (chained) [0.00 s] [ 10.84 s step 13] touchdown: phase velocity 2.82 (gait's fixed point 2.79), theta 1.001 [ 10.84 s step 14] decide: regular 0.40 m (chained) [0.00 s] [ 11.00 s step 14] perceive (23 ms): levels z+0cm x6.14-9.42 [ 11.61 s step 14] touchdown: phase velocity 2.82 (gait's fixed point 2.79), theta 1.001 [ 11.61 s step 15] decide: regular 0.40 m (chained) [0.00 s] [ 12.00 s step 15] perceive (38 ms): levels z+0cm x6.55-9.74 [ 12.38 s step 15] touchdown: phase velocity 2.82 (gait's fixed point 2.79), theta 1.002 [ 12.38 s step 16] decide: regular 0.40 m (chained) [0.00 s] [ 13.00 s step 16] perceive (31 ms): levels z+0cm x6.96-10.40 [ 13.15 s step 16] touchdown: phase velocity 2.82 (gait's fixed point 2.80), theta 1.002 [ 13.15 s step 17] decide: regular 0.40 m (chained) [0.02 s] [ 13.92 s step 17] touchdown: phase velocity 2.81 (gait's fixed point 2.79), theta 1.001 [ 13.92 s step 18] decide: regular 0.40 m (chained) [0.00 s] [ 14.00 s step 18] perceive (61 ms): levels z+0cm x7.77-11.26 [ 14.69 s step 18] touchdown: phase velocity 2.81 (gait's fixed point 2.79), theta 1.001 [ 14.69 s step 19] decide: regular 0.40 m (chained) [0.00 s] [ 15.00 s step 19] perceive (60 ms): levels z+0cm x8.18-11.36 [ 15.47 s step 19] touchdown: phase velocity 2.82 (gait's fixed point 2.79), theta 1.002 [ 15.47 s step 20] decide: regular 0.40 m (chained) [0.00 s] [ 16.00 s step 20] perceive (25 ms): levels z+0cm x8.59-11.89 [ 16.25 s step 20] touchdown: phase velocity 2.79 (gait's fixed point 2.80), theta 1.001 [ 16.25 s step 21] decide: regular 0.40 m (chained) [0.00 s] [ 17.00 s step 21] perceive (48 ms): levels z+0cm x9.00-13.04 [ 17.02 s step 21] touchdown: phase velocity 2.79 (gait's fixed point 2.77), theta 1.002 [ 17.02 s step 22] decide: regular 0.40 m (chained) [0.00 s] [ 17.80 s step 22] touchdown: phase velocity 2.79 (gait's fixed point 2.78), theta 1.002 [ 17.80 s step 23] decide: regular 0.40 m (chained) [0.00 s] [ 18.00 s step 23] perceive (53 ms): levels z+0cm x9.82-13.04 [ 18.58 s step 23] touchdown: phase velocity 2.79 (gait's fixed point 2.78), theta 1.001 [ 18.58 s step 24] decide: regular 0.40 m (chained) [0.00 s] [ 19.00 s step 24] perceive (42 ms): levels z+0cm x10.22-13.42 [ 19.35 s step 24] touchdown: phase velocity 2.79 (gait's fixed point 2.78), theta 1.001 [ 19.35 s step 25] decide: regular 0.40 m (chained) [0.00 s] [ 20.00 s step 25] perceive (35 ms): levels z+0cm x10.63-14.11 [ 20.13 s step 25] touchdown: phase velocity 2.80 (gait's fixed point 2.77), theta 1.002 [ 20.13 s step 26] decide: regular 0.40 m (chained) [0.00 s] [ 20.91 s step 26] touchdown: phase velocity 2.78 (gait's fixed point 2.78), theta 1.000 [ 20.91 s step 27] decide: regular 0.40 m (chained) [0.00 s] [ 21.00 s step 27] perceive (48 ms): levels z+0cm x11.44-14.88 [ 21.69 s step 27] touchdown: phase velocity 2.79 (gait's fixed point 2.77), theta 1.001 [ 21.69 s step 28] decide: regular 0.40 m (chained) [0.00 s] [ 22.00 s step 28] perceive (25 ms): levels z+0cm x11.85-15.03

Runs entirely in your browser: a 27 MB Depth Anything V2 network estimates depth, the BipedNav pipeline finds the treads and risers (or the floor and the first obstacle), and prints rise/run or distance/depth/height. Nothing is uploaded.
Stock scenes from the archived dataset (tape measurements known; camera height set automatically):
How the scale is recovered: the network's output is inverse depth up to an affine map, so the pipeline searches the shift that makes the dominant up-facing surface planar and sets the scale so that surface lies at the camera height you enter. The stock scenes use the camera height measured by the depth camera; for your own photo, enter roughly the height of your phone above the floor (1.4–1.7 m when standing). The metric fine-tuned Metric3D v2 of the original study is more accurate than this browser-sized model; the geometry pipeline is the same.
Three walkers, one method: a hybrid limit cycle designed as virtual holonomic constraints, verified against its return map, then walked in a collision-checked simulation and in MuJoCo.
Point feet, four actuators. Period 0.78 s, Floquet multiplier 0.78, 53 N·m; the walker settles onto the cycle from 1.25× its speed.
The flat gait redesigned as a fully actuated periodic step minimising squared torque under natural-posture constraints: 0.50 m stride, period 0.78 s, mean torque 12 N·m, cost of transport 0.30, torso lean under 7°.
The gait the robot walks everywhere on the flat: fully actuated, energy-minimising, torso within 7° of vertical, knee flexing to 80° in swing, centre of pressure inside the inner 70 % of the foot. 0.50 m strides at 0.78 s, 0.2 mm of slip per step, arms swinging with the opposite leg, head held level so the camera keeps its view of the floor.
Why the footed walker no longer stoops. The first footed flat gait was a hybrid gait with a passive stance ankle and a 12° forward lean baked into its design, which read as a shuffle. With the ankle actuated the flat gait is designed like every other footed step: a periodic, fully actuated trajectory that minimises squared torque subject to a torso within 7° of vertical, a hip above 0.9 leg lengths, 4 cm of foot clearance, knees that never straighten fully, and a landing that sticks. Its centre of pressure stays inside the inner 70 % of the foot for the whole step (a version that rode the heel limit tipped in physics), its cost of transport is 0.27, and the same step then runs in MuJoCo from the measured state. Three things had to be true before the terrain steps could start and end in this gait. The humanoid’s arms and head carry 1 % of the upper-body mass and its trunk mass sits exactly where the model’s torso point mass is, so the impact map is the model’s. The reference of a new step is attached to the measured state 8 ms after touchdown, not at the touchdown instant, because MuJoCo’s compliant contact takes a few milliseconds to resolve and the velocities at first contact are still the pre-impact ones. And every terrain step is re-designed in those 8 ms from the state actually measured, which is what makes the hand-over back into the walking gait survive.


A slope is a rotated floor: the five-link library holds periodic gaits at ±3°, ±6° and ±10°; the footed walker has fully actuated periodic steps on ±6° ramps, entries onto a ramp whose foot is 18 cm ahead and exits onto the level.
Library gait on the slope, walked in the collision-checked simulation.
Descending gaits are faster and land with a straighter knee.
The steepest library gait.
Ten degrees down.
Fully actuated periodic step with the foot parallel to the slope, centre of pressure inside the foot.
Same on the way down.
Regular gait → entry onto the ramp → slope steps → exit onto the level → regular gait.
The same sequence downhill.
From one view of the floor the perception layer returns the first crate in the corridor (distance, depth, height to about 1 cm). The point-foot walker crosses it with two chained step-over gaits; the footed walker lands its leading foot 5 cm past the crate and its trailing step returns to the regular gait.
| case | true box (dist / depth / height) | perceived | plan | result | peak torque |
|---|---|---|---|---|---|
| 0 | 1.20 m / 15 cm / 8 cm | 1.20 m / 14 cm / 9 cm | 2 × 0.46 m, then 0.63 m over, resume 0.40 m | 8/8 steps, no collision | 432 N·m |
| 1 | 1.60 m / 20 cm / 15 cm | 1.59 m / 18 cm / 16 cm | 3 × 0.44 m, then 0.71 m over, resume 0.40 m | 5/9 steps, then trip | 800 N·m |
| 2 | 2.00 m / 25 cm / 22 cm | 1.99 m / 23 cm / 23 cm | 4 × 0.43 m, then 0.76 m over, resume 0.40 m | 10/10 steps, no collision | 419 N·m |
| 3 | 1.00 m / 30 cm / 12 cm | 1.00 m / 28 cm / 13 cm | 2 × 0.37 m, then 0.78 m over, resume 0.40 m | 2/8 steps, then trip | 426 N·m |
| 4 | 1.40 m / 10 cm / 5 cm | 1.40 m / 9 cm / 6 cm | 3 × 0.38 m, then 0.54 m over, resume 0.40 m | 9/9 steps, no collision | 415 N·m |
2 approach steps of 0.46 m, 0.63 m over with the leading leg, trailing leg over, regular gait resumed — 8/8 steps, no collision.
3 approach steps of 0.44 m, 0.71 m over with the leading leg, trailing leg over, regular gait resumed — 5/9 steps, then trip.
4 approach steps of 0.43 m, 0.76 m over with the leading leg, trailing leg over, regular gait resumed — 10/10 steps, no collision.
2 approach steps of 0.37 m, 0.78 m over with the leading leg, trailing leg over, regular gait resumed — 2/8 steps, then trip.
3 approach steps of 0.38 m, 0.54 m over with the leading leg, trailing leg over, regular gait resumed — 9/9 steps, no collision.
Leading step 0.50 m over the crate, trailing step 0.40 m back into the regular gait; both fully actuated, centre of pressure inside the foot.
The plan executed in physics: leading foot 5 cm past the crate, then the regular gait.
The tallest crate crossed.
| crate | height cm | depth cm | result | τmax N·m | slip cm | landing err mm |
|---|---|---|---|---|---|---|
| crate00 | 5 | 20 | walked 9/9 | 149 | 0.3 | 0.2 |
| crate01 | 8 | 15 | walked 9/9 | 227 | 0.2 | 0.2 |
| crate02 | 10 | 20 | walked 9/9 | 116 | 0.2 | 0.1 |
| crate03 | 10 | 30 | fell after 4 steps | 0 | 0.2 | – |
| crate04 | 12 | 25 | design infeasible | 0 | 0.0 | – |
| crate05 | 15 | 20 | walked 9/9 | 151 | 0.3 | 0.3 |

The five-link library holds a periodic gait for every (run, rise) cell and interpolates between them; the footed walker takes each stair as one fully actuated step into the landing state of that stair's cell.
Landing knee 49°, torso lean +29°, foot lift 39 cm, period 0.70 s, Floquet 0.41, peak torque 380 N·m; 8/8 steps.
Landing knee 56°, torso lean +29°, foot lift 35 cm, period 0.90 s, Floquet 0.32, peak torque 380 N·m; 8/8 steps.
Landing knee 50°, torso lean +29°, foot lift 44 cm, period 0.55 s, Floquet 0.40, peak torque 380 N·m; 8/8 steps.
Landing knee 67°, torso lean +29°, foot lift 36 cm, period 0.96 s, Floquet 0.21, peak torque 380 N·m; 8/8 steps.
Landing knee 26°, torso lean -6°, foot lift 45 cm, period 0.42 s, Floquet 0.08, peak torque 381 N·m; 8/8 steps.
Landing knee 27°, torso lean -6°, foot lift 45 cm, period 0.42 s, Floquet 0.05, peak torque 381 N·m; 8/8 steps.
Entry from the regular gait, three climbing steps, exit onto the landing; the centre-of-pressure panel shows the ankle at work.
Four different stairs, one step each, exit back into the regular gait.
Three 10 cm stairs with the arms held still: the climbing steps land within a millimetre; the step off the top falls, kept in.
Four different stairs down, every landing within 5 mm of the design.


Flights whose rise and run change from one stair to the next. The five-link walker re-plans its virtual constraint per stair from the perceived geometry (analytic simulation); the footed humanoid does the same in MuJoCo.
| run | stairs | rise range | run range | gaits | result | peak torque |
|---|---|---|---|---|---|---|
| up gentle | 8 | 6–8 cm | 32–34 cm | 7 chained / 0 re-designed / 1 infeasible | all 14 steps | 624 N·m |
| up perceived | 8 | 10–14 cm | 27–29 cm | 7 chained / 0 re-designed / 1 infeasible | all 14 steps | 614 N·m |
| up steep | 8 | 14–19 cm | 24–31 cm | 0 chained / 0 re-designed / 1 infeasible | 3/4 steps, then trip | 429 N·m |
| up growing | 10 | 5–19 cm | 27–33 cm | 7 chained / 1 re-designed / 2 infeasible | all 16 steps | 800 N·m |
| up irregular | 10 | 9–16 cm | 24–34 cm | 6 chained / 1 re-designed / 3 infeasible | all 16 steps | 627 N·m |
| down gentle | 8 | 6–8 cm | 33–35 cm | 2 chained / 0 re-designed / 1 infeasible | 5/6 steps, then scuff | 401 N·m |
| down perceived | 8 | 9–13 cm | 32–34 cm | 3 chained / 0 re-designed / 3 infeasible | 8/9 steps, then scuff | 800 N·m |
| down steep | 8 | 12–17 cm | 30–37 cm | 3 chained / 0 re-designed / 4 infeasible | 9/10 steps, then fell | 800 N·m |
| down growing | 10 | 5–16 cm | 31–37 cm | 4 chained / 0 re-designed | 6/7 steps, then scuff | 539 N·m |
| down irregular | 10 | 8–14 cm | 30–36 cm | 3 chained / 0 re-designed / 4 infeasible | 9/10 steps, then singular | 800 N·m |
Runs 32–34 cm, every stair different. Landing knee 40–47°, gaits 7 chained / 0 re-designed / 1 infeasible; all 14 steps, peak torque 624 N·m.
Runs 27–29 cm, every stair different. Landing knee 41–57°, gaits 7 chained / 0 re-designed / 1 infeasible; all 14 steps, peak torque 614 N·m.
Runs 24–31 cm, every stair different. Landing knee 66–66°, gaits 0 chained / 0 re-designed / 1 infeasible; 3/4 steps, then trip, peak torque 429 N·m.
Runs 27–33 cm, every stair different. Landing knee 44–64°, gaits 7 chained / 1 re-designed / 2 infeasible; all 16 steps, peak torque 800 N·m.
Runs 24–34 cm, every stair different. Landing knee 42–60°, gaits 6 chained / 1 re-designed / 3 infeasible; all 16 steps, peak torque 627 N·m.
Runs 33–35 cm, every stair different. Landing knee 22–23°, gaits 2 chained / 0 re-designed / 1 infeasible; 5/6 steps, then scuff, peak torque 401 N·m.
Runs 32–34 cm, every stair different. Landing knee 15–26°, gaits 3 chained / 0 re-designed / 3 infeasible; 8/9 steps, then scuff, peak torque 800 N·m.
Runs 30–37 cm, every stair different. Landing knee 22–27°, gaits 3 chained / 0 re-designed / 4 infeasible; 9/10 steps, then fell, peak torque 800 N·m.
Runs 31–37 cm, every stair different. Landing knee 19–25°, gaits 4 chained / 0 re-designed; 6/7 steps, then scuff, peak torque 539 N·m.
Runs 30–36 cm, every stair different. Landing knee 22–26°, gaits 3 chained / 0 re-designed / 4 infeasible; 9/10 steps, then singular, peak torque 800 N·m.
Footed humanoid in physics. Ten flights of 3–5 descending stairs with random rise (5–15 cm) and run (29–38 cm): 7 of 10 walked end to end, landing errors under 5 mm, foot slip 2 mm. The failures are the 13–14 cm drops, where no step satisfies the torque, friction and centre-of-pressure constraints at 400 N·m. These ten flights and the crate runs were measured with the earlier hybrid walking gait; the long course below is the end-to-end run with the natural gait, and re-measuring the batches with it is in progress.
Every stair different; entry, five stair steps, exit, regular gait.
Runs 33–35 cm.
Runs 31–34 cm.

| flight | stairs | rise cm | run cm | result | τmax on stairs N·m | slip cm | landing err mm |
|---|---|---|---|---|---|---|---|
| down00 | 3 | 9–9 | 33–35 | walked 11/11 | 133 | 0.2 | 5 |
| down01 | 3 | 10–11 | 31–34 | walked 11/11 | 138 | 0.2 | 4 |
| down02 | 4 | 9–12 | 29–32 | fell after 8 steps | 156 | 9.0 | 96 |
| down03 | 4 | 11–13 | 30–33 | design infeasible | 0 | 0.0 | – |
| down04 | 4 | 6–9 | 29–31 | walked 12/12 | 237 | 0.2 | 4 |
| down05 | 5 | 11–14 | 29–34 | design infeasible | 0 | 0.0 | – |
| down06 | 3 | 8–10 | 30–32 | walked 11/11 | 173 | 0.2 | 4 |
| down07 | 5 | 5–10 | 29–33 | walked 13/13 | 153 | 0.2 | 5 |
| down08 | 4 | 7–9 | 29–36 | walked 12/12 | 204 | 0.2 | 1 |
| down09 | 4 | 10–11 | 33–35 | walked 12/12 | 160 | 0.2 | 3 |
Point feet cannot do stair transitions in physics: the pinned-foot model never forbade negative ground forces or a foot that will not lift. Feet with actuated ankles make the robot fully actuated in single support, so every stair, crate or slope step becomes a time-parametrised trajectory designed against the real geometry, with the centre of pressure kept inside the foot.

What a step must satisfy
What broke in physics, and what fixed it
For a fully actuated step the top-right panel replaces the phase portrait: the centre of pressure must stay between heel and toe for the whole step.
Twelve of twelve steps, landings within 5 mm.
Thirteen metres of everything in a single MuJoCo run with the footed humanoid: flat walking in the natural gait, three stairs up, the step off the top, a crate, a 6° ramp down, three stairs down and the step back onto the flat. Every terrain step is a fully actuated trajectory designed against that feature's geometry and re-designed 8 ms after each touchdown from the state actually measured.
28 of 28 steps in 28.1 s of simulation: 18 of 18 terrain steps designed feasible, foot slip under 5 cm, peak torque 800 N·m, and the stairs landed within 10 mm of their designed rise.

| step | what | period s | stride m | rise m | slip cm | τmax N·m |
|---|---|---|---|---|---|---|
| R | regular gait, 0.50 m | 0.78 | +0.500 | -0.000 | 0.0 | 220 |
| R | regular gait, 0.50 m | 0.78 | +0.500 | -0.000 | 0.0 | 207 |
| R | regular gait, 0.50 m | 0.78 | +0.500 | -0.000 | 0.0 | 207 |
| R | regular gait, 0.50 m | 0.78 | +0.500 | -0.000 | 0.0 | 207 |
| U1 | stair up | 0.93 | +0.320 | +0.100 | 0.0 | 154 |
| U2 | stair up | 1.20 | +0.300 | +0.100 | 0.0 | 90 |
| U3 | stair up | 1.18 | +0.300 | +0.099 | 0.0 | 136 |
| X1 | step off the top of the flight | 1.70 | +0.397 | -0.000 | 0.0 | 321 |
| F | short-stride gait, 0.40 m | 1.33 | +0.400 | -0.000 | 0.0 | 86 |
| F | short-stride gait, 0.40 m | 1.33 | +0.400 | -0.000 | 0.0 | 48 |
| L | crate: leading step | 1.17 | +0.399 | -0.000 | 0.0 | 227 |
| T | crate: trailing step | 1.14 | +0.401 | -0.000 | 0.0 | 48 |
| F | short-stride gait, 0.40 m | 1.33 | +0.400 | -0.000 | 0.1 | 85 |
| E | onto the ramp | 1.11 | +0.422 | -0.102 | 2.9 | 231 |
| S1 | ramp step, 6° down | 0.68 | +0.456 | -0.090 | 5.4 | 800 |
| S2 | ramp step, 6° down | 0.91 | +0.398 | -0.042 | 0.1 | 199 |
| S3 | ramp step, 6° down | 0.94 | +0.398 | -0.042 | 0.0 | 121 |
| S4 | ramp step, 6° down | 0.82 | +0.389 | -0.035 | 0.0 | 85 |
| X2 | off the ramp | 1.20 | +0.417 | -0.009 | 0.3 | 150 |
| A | approach: stride set from the drop edge | 1.13 | +0.300 | -0.000 | 0.0 | 141 |
| D1 | stair down | 1.01 | +0.320 | -0.100 | 0.1 | 224 |
| D2 | stair down | 0.81 | +0.320 | -0.090 | 0.2 | 198 |
| D3 | stair down | 0.89 | +0.320 | -0.103 | 0.0 | 136 |
| X3 | off the flight onto the flat | 0.79 | +0.500 | +0.000 | 0.0 | 79 |
| RJ | rejoin the regular gait | 0.84 | +0.500 | -0.000 | 0.0 | 198 |
| R | regular gait, 0.50 m | 0.78 | +0.500 | -0.000 | 0.0 | 186 |
| R | regular gait, 0.50 m | 0.78 | +0.500 | -0.000 | 0.0 | 198 |
| R | regular gait, 0.50 m | 0.78 | +0.500 | -0.000 | 0.0 | 198 |
The whole loop in physics with the humanoid: the head camera is read at 1 Hz, floor levels, crates, drop edges and ramps go into a world model, and at every touchdown the next step is chosen and designed from that model. The design time is real and shown; the simulation waits for it.
28 of 28 steps in 28.1 s of simulation: 18 of 18 terrain steps designed feasible, foot slip under 5 cm, peak torque 800 N·m, and the stairs landed within 10 mm of their designed rise.
Drops of 10, 9 and 11 cm perceived from 1.5 m, approached with 0.35 m steps, taken in one go; a flight with a 12 cm drop fell on that stair.
The combined course with the picture-in-picture camera and the HUD.
Two crates and two flights of different stairs, all perceived, in one run.
Live trace of the long perceived course
# online_b7on_long2: seven-link (feet, actuated ankles) -> done after 34 steps, 31.3 s simulated, 530 s of step design [ 0.00 s step 0] perceive (50 ms): levels z+0cm x0.34-2.29, z+0cm x2.76-5.48 [ 0.82 s step 1] touchdown: step of 0.82 s, stride (+0.399, +0.000) m, slip 0.1 cm, peak torque 332 N·m, tracking 0.009 rad [ 0.82 s step 1] decide: regular 0.40 m (flat ahead) [0.00 s] [ 1.00 s step 1] perceive (30 ms): levels z+0cm x0.66-2.34, z+10cm x2.35-2.53, z+0cm x2.69-3.37 | obstacle: box 1.95 m ahead, 18 cm deep, 10 cm high [ 1.63 s step 2] touchdown: step of 0.81 s, stride (+0.399, -0.000) m, slip 0.2 cm, peak torque 405 N·m, tracking 0.028 rad [ 1.63 s step 2] decide: crate in 1.55 m: approach flat 0.34 m (designed, 3 s) [2.94 s] [ 2.00 s step 2] perceive (33 ms): levels z+0cm x1.06-2.33, z+10cm x2.35-2.53, z+0cm x2.66-4.27 | obstacle: box 1.55 m ahead, 18 cm deep, 10 cm high [ 2.54 s step 3] touchdown: step of 0.91 s, stride (+0.340, -0.001) m, slip 0.0 cm, peak torque 200 N·m, tracking 0.078 rad [ 2.54 s step 3] decide: crate in 1.21 m: approach flat 0.34 m (designed, 3 s) [2.87 s] [ 3.00 s step 3] perceive (35 ms): levels z+0cm x1.40-2.33, z+10cm x2.35-2.54, z+0cm x2.64-5.53 | obstacle: box 1.21 m ahead, 19 cm deep, 10 cm high [ 3.45 s step 4] touchdown: step of 0.91 s, stride (+0.340, -0.001) m, slip 0.0 cm, peak torque 93 N·m, tracking 0.027 rad [ 3.45 s step 4] decide: crate in 0.87 m: approach flat 0.34 m (designed, 3 s) [2.92 s] [ 4.00 s step 4] perceive (29 ms): levels z+0cm x1.79-2.35, z+10cm x2.35-2.54, z+0cm x2.62-5.49 | obstacle: box 0.87 m ahead, 19 cm deep, 10 cm high [ 4.36 s step 5] touchdown: step of 0.91 s, stride (+0.340, -0.001) m, slip 0.0 cm, peak torque 230 N·m, tracking 0.047 rad [ 4.36 s step 5] decide: crate in 0.53 m: approach flat 0.34 m (designed, 3 s) [2.82 s] [ 5.00 s step 5] perceive (25 ms): levels z+0cm x2.30-2.35, z+10cm x2.35-2.54, z+0cm x2.60-5.44 | obstacle: box 0.53 m ahead, 19 cm deep, 10 cm high [ 5.27 s step 6] touchdown: step of 0.91 s, stride (+0.340, -0.001) m, slip 0.0 cm, peak torque 93 N·m, tracking 0.047 rad [ 5.27 s step 6] decide: crate 10 cm high, 19 cm deep, 19 cm ahead: leading stride 0.49 m (ok), trailing (ok), 45 s [45.01 s] [ 6.00 s step 6] perceive (94 ms): levels z+10cm x2.41-2.55, z+0cm x2.57-5.49 [ 6.44 s step 7] touchdown: step of 1.17 s, stride (+0.493, -0.000) m, slip -0.0 cm, peak torque 75 N·m, tracking 0.082 rad [ 6.44 s step 7] decide: crate: trailing step (queued) (queued) [ 7.00 s step 7] perceive (29 ms): levels z+0cm x2.92-5.54 [ 7.61 s step 8] touchdown: step of 1.17 s, stride (+0.400, -0.000) m, slip 0.1 cm, peak torque 118 N·m, tracking 0.050 rad [ 7.61 s step 8] decide: regular 0.40 m (flat ahead) [0.00 s] [ 8.00 s step 8] perceive (36 ms): levels z+0cm x3.32-5.29 [ 8.49 s step 9] touchdown: step of 0.88 s, stride (+0.399, +0.000) m, slip 0.1 cm, peak torque 323 N·m, tracking 0.028 rad [ 8.49 s step 9] decide: regular 0.40 m (flat ahead) [0.00 s] [ 9.00 s step 9] perceive (43 ms): levels z+0cm x3.72-5.56, z-29cm x6.40-6.86 | stairs: down first riser 2.10 m, rise -29 cm, run nan cm, 1 treads [ 9.34 s step 10] touchdown: step of 0.85 s, stride (+0.399, -0.000) m, slip 0.1 cm, peak torque 347 N·m, tracking 0.025 rad [ 9.34 s step 10] decide: stairs down in 1.70 m: approach flat 0.38 m (designed, 4 s) [4.01 s] [ 10.00 s step 10] perceive (39 ms): levels z+0cm x4.37-5.57, z-10cm x5.72-5.91, z-29cm x6.38-7.97, z-29cm x8.39-9.45 [ 10.25 s step 11] touchdown: step of 0.91 s, stride (+0.381, -0.000) m, slip 0.0 cm, peak torque 77 N·m, tracking 0.089 rad [ 10.25 s step 11] decide: stairs down in 1.34 m: approach regular 0.40 m [0.00 s] [ 11.00 s step 11] perceive (33 ms): levels z+0cm x5.03-5.59, z-10cm x5.68-5.91, z-19cm x6.01-6.21, z-29cm x6.34-7.97, z-29cm x8.32-9.39 [ 11.03 s step 12] touchdown: step of 0.79 s, stride (+0.399, -0.001) m, slip 0.2 cm, peak torque 370 N·m, tracking 0.128 rad [ 11.03 s step 12] decide: stairs down in 0.95 m: approach flat 0.38 m (designed, 4 s) [3.99 s] [ 11.94 s step 13] touchdown: step of 0.91 s, stride (+0.385, -0.001) m, slip 0.1 cm, peak torque 108 N·m, tracking 0.020 rad [ 11.94 s step 13] decide: stairs down in 0.56 m: approach flat 0.38 m (designed, 4 s) [4.40 s] [ 12.00 s step 13] perceive (50 ms): levels z+0cm x5.28-5.59, z-10cm x5.64-5.91, z-19cm x5.98-6.21, z-29cm x6.30-8.00, z-29cm x8.31-9.40 [ 12.85 s step 14] touchdown: step of 0.91 s, stride (+0.384, -0.000) m, slip 0.1 cm, peak torque 111 N·m, tracking 0.018 rad [ 12.85 s step 14] decide: stair down: edge in 18 cm, rise -10.0 cm, stride 0.32 m (ok, tau 122 N·m, 149 s) [148.87 s] [ 13.00 s step 14] perceive (49 ms): levels z-10cm x5.66-5.91, z-19cm x5.94-6.23, z-29cm x6.28-7.97, z-29cm x8.30-9.45 [ 13.80 s step 15] touchdown: step of 0.94 s, stride (+0.320, -0.100) m, slip 0.0 cm, peak torque 86 N·m, tracking 0.071 rad [ 13.80 s step 15] decide: stair down: edge in 19 cm, rise -9.0 cm, stride 0.33 m (ok, tau 132 N·m, 12 s) [12.09 s] [ 14.00 s step 15] perceive (32 ms): levels z-9cm x6.13-6.22, z-19cm x6.26-7.99, z-19cm x8.29-9.46 [ 14.62 s step 16] touchdown: step of 0.83 s, stride (+0.330, -0.090) m, slip 0.1 cm, peak torque 107 N·m, tracking 0.063 rad [ 14.62 s step 16] decide: stair down: edge in 17 cm, rise -10.0 cm, stride 0.31 m (ok, tau 120 N·m, 82 s) [82.20 s] [ 15.00 s step 16] perceive (39 ms): levels z-10cm x6.52-7.98, z-10cm x8.26-9.43 [ 15.49 s step 17] touchdown: step of 0.86 s, stride (+0.310, -0.100) m, slip 0.0 cm, peak torque 90 N·m, tracking 0.054 rad [ 15.49 s step 17] decide: exit step (bad clear_obs=-0.002, tau 79 N·m, 66 s) [66.42 s] [ 16.00 s step 17] perceive (42 ms): levels z-0cm x7.05-7.99, z-0cm x8.27-9.45 [ 16.37 s step 18] touchdown: step of 0.89 s, stride (+0.400, -0.001) m, slip 0.0 cm, peak torque 136 N·m, tracking 0.076 rad [ 16.37 s step 18] decide: regular 0.40 m (flat ahead) [0.00 s] [ 17.00 s step 18] perceive (39 ms): levels z+0cm x7.18-7.99, z+8cm x8.00-8.14, z+0cm x8.22-9.44 | obstacle: box 1.23 m ahead, 14 cm deep, 8 cm high [ 17.20 s step 19] touchdown: step of 0.82 s, stride (+0.399, -0.001) m, slip 0.2 cm, peak torque 348 N·m, tracking 0.023 rad [ 17.20 s step 19] decide: crate in 0.83 m: approach flat 0.34 m (designed, 4 s) [3.72 s] [ 18.00 s step 19] perceive (31 ms): levels z+0cm x7.89-8.00, z+8cm x8.00-8.15, z+0cm x8.21-9.46 | obstacle: box 0.83 m ahead, 15 cm deep, 8 cm high [ 18.10 s step 20] touchdown: step of 0.91 s, stride (+0.340, -0.001) m, slip 0.0 cm, peak torque 102 N·m, tracking 0.021 rad [ 18.10 s step 20] decide: crate in 0.49 m: approach flat 0.34 m (designed, 3 s) [3.37 s] [ 19.00 s step 20] perceive (27 ms): levels z-0cm x8.25-9.42, z-8cm x9.56-9.78, z-37cm x10.62-14.52 | stairs: down first riser 1.91 m, rise -18 cm, run 36 cm, 2 treads [ 19.01 s step 21] touchdown: step of 0.91 s, stride (+0.340, -0.001) m, slip 0.0 cm, peak torque 93 N·m, tracking 0.027 rad [ 19.01 s step 21] decide: crate 8 cm high, 15 cm deep, 15 cm ahead: leading stride 0.41 m (ok), trailing (ok), 58 s [57.60 s] [ 20.00 s step 21] perceive (37 ms): levels z-0cm x8.39-9.44, z-8cm x9.54-9.78, z-18cm x9.90-10.10, z-37cm x10.59-15.30 | stairs: down first riser 1.59 m, rise -10 cm, run 33 cm, 3 treads [ 20.20 s step 22] touchdown: step of 1.19 s, stride (+0.409, -0.001) m, slip -0.0 cm, peak torque 93 N·m, tracking 0.048 rad [ 20.20 s step 22] decide: crate: trailing step (queued) (queued) [ 21.00 s step 22] perceive (28 ms): levels z+0cm x8.62-9.45, z-8cm x9.53-9.80, z-18cm x9.90-10.11, z-37cm x10.56-15.67 | stairs: down first riser 1.19 m, rise -10 cm, run 33 cm, 3 treads [ 21.39 s step 23] touchdown: step of 1.19 s, stride (+0.400, -0.001) m, slip 0.0 cm, peak torque 231 N·m, tracking 0.039 rad [ 21.39 s step 23] decide: stairs down in 0.80 m: approach flat 0.34 m (designed, 3 s) [3.11 s] [ 22.00 s step 23] perceive (38 ms): levels z+0cm x9.05-9.45, z-8cm x9.50-9.79, z-18cm x9.87-10.11, z-27cm x10.20-10.44, z-37cm x10.56-15.93 | stairs: down first riser 0.79 m, rise -9 cm, run 33 cm, 4 treads [ 22.30 s step 24] touchdown: step of 0.91 s, stride (+0.340, -0.000) m, slip 0.0 cm, peak torque 110 N·m, tracking 0.025 rad [ 22.30 s step 24] decide: stairs down in 0.46 m: approach flat 0.34 m (designed, 3 s) [2.88 s] [ 23.00 s step 24] perceive (23 ms): levels z-8cm x9.61-9.80, z-18cm x9.85-10.11, z-27cm x10.17-10.44, z-37cm x10.53-15.65 | stairs: down first riser 0.80 m, rise -10 cm, run 32 cm, 3 treads [ 23.21 s step 25] touchdown: step of 0.91 s, stride (+0.340, -0.001) m, slip 0.0 cm, peak torque 114 N·m, tracking 0.042 rad [ 23.21 s step 25] decide: stair down: edge in 12 cm, rise -8.0 cm, stride 0.26 m (ok, tau 155 N·m, 16 s) [15.80 s] [ 24.00 s step 25] perceive (39 ms): levels z-18cm x10.04-10.12, z-27cm x10.16-10.44, z-37cm x10.51-15.81 | stairs: down first riser 0.78 m, rise -9 cm, run 32 cm, 2 treads [ 24.06 s step 26] touchdown: step of 0.85 s, stride (+0.260, -0.080) m, slip 0.0 cm, peak torque 131 N·m, tracking 0.047 rad [ 24.06 s step 26] decide: stair down: edge in 20 cm, rise -10.0 cm, stride 0.34 m (ok, tau 147 N·m, 5 s) [4.90 s] [ 24.90 s step 27] touchdown: step of 0.84 s, stride (+0.340, -0.100) m, slip 0.0 cm, peak torque 162 N·m, tracking 0.030 rad [ 24.90 s step 27] decide: stair down: edge in 18 cm, rise -9.0 cm, stride 0.32 m (ok, tau 122 N·m, 9 s) [9.26 s] [ 25.00 s step 27] perceive (33 ms): levels z-9cm x10.40-10.45, z-19cm x10.49-16.29 | stairs: down first riser 0.51 m, rise -10 cm, run nan cm, 1 treads [ 25.74 s step 28] touchdown: step of 0.84 s, stride (+0.320, -0.091) m, slip 0.1 cm, peak torque 95 N·m, tracking 0.069 rad [ 25.74 s step 28] decide: stair down: edge in 19 cm, rise -10.0 cm, stride 0.33 m (ok, tau 108 N·m, 48 s) [47.54 s] [ 26.00 s step 28] perceive (41 ms): levels z-10cm x10.69-16.54 [ 26.59 s step 29] touchdown: step of 0.85 s, stride (+0.330, -0.100) m, slip 0.0 cm, peak torque 118 N·m, tracking 0.040 rad [ 26.59 s step 29] decide: exit step (ok, tau 74 N·m, 3 s) [3.38 s] [ 27.00 s step 29] perceive (38 ms): levels z+0cm x11.18-16.30 [ 27.48 s step 30] touchdown: step of 0.89 s, stride (+0.400, -0.001) m, slip 0.0 cm, peak torque 73 N·m, tracking 0.022 rad [ 27.48 s step 30] decide: regular 0.40 m (flat ahead) [0.00 s] [ 28.00 s step 30] perceive (86 ms): levels z+0cm x11.25-14.36 [ 28.29 s step 31] touchdown: step of 0.81 s, stride (+0.399, +0.000) m, slip 0.2 cm, peak torque 351 N·m, tracking 0.016 rad [ 28.29 s step 31] decide: regular 0.40 m (flat ahead) [0.00 s] [ 29.00 s step 31] perceive (29 ms): levels z+0cm x12.15-17.24 [ 29.10 s step 32] touchdown: step of 0.81 s, stride (+0.399, -0.001) m, slip 0.2 cm, peak torque 388 N·m, tracking 0.028 rad [ 29.10 s step 32] decide: regular 0.40 m (flat ahead) [0.00 s] [ 29.90 s step 33] touchdown: step of 0.81 s, stride (+0.399, -0.000) m, slip 0.1 cm, peak torque 401 N·m, tracking 0.027 rad [ 29.90 s step 33] decide: regular 0.40 m (flat ahead) [0.00 s] [ 30.00 s step 33] perceive (30 ms): levels z+0cm x12.45-17.03 [ 30.70 s step 34] touchdown: step of 0.80 s, stride (+0.399, -0.001) m, slip 0.2 cm, peak torque 373 N·m, tracking 0.024 rad [ 30.70 s step 34] decide: regular 0.40 m (flat ahead) [0.00 s] [ 31.00 s step 34] perceive (43 ms): levels z+0cm x12.86-14.82

Earlier, the point-foot five-link walker ran the same loop: flat walking was exact and one crate was crossed, but every staircase fell at the first transition. The technical report keeps those runs and the diagnosis (negative ground forces, fast touchdowns, a trailing foot that did not lift) that led to the footed robot.
The course project designed the gait on the acrobot (two links, one hip motor). Re-running it against physics instead of against itself gave three findings.

The report's six VHC coefficients, δ = 0.336, M⁻ = 0.121, V⁻ = −0.254, Vmax = 3.42; the measured return-map slope 0.9329 matches δ²/M⁻ = 0.9326. The basin is one-sided: the gait cannot start slower than its limit cycle.

q̇⁺ = −q̇ is not the Jacobian of q₁⁺ = q₁ + q₂ − π, q₂⁺ = 2π − q₂. Under the exact swap the report gait keeps δ = 0.115 instead of 0.336 and has no stable orbit; retraction gaits recover it. Both conventions are implemented; the five-link walker uses the exact one.

The slope model lets the swing foot pass through the tread behind the stance foot; on the report's staircase the dip is 5 cm. Checking gaits against treads and risers is what produced the foot-placement rule above.


Everything on this page is regenerated by a Python harness in BipedNav/experiments (numpy, scipy, sympy, matplotlib, OpenCV; ffmpeg for the video; no ROS, no MATLAB). The MATLAB originals remain in control/MATLAB. The technical report is the lab notebook: methods, every number, and the limitations.
Credits
Perception. Andrew Qiu, Aravind Narayanan, Qilong Cheng, Brokoslaw Laschowski — Neural Robotics Lab, KITE Toronto Rehabilitation Institute and the Robotics Institute, University of Toronto, 2024. Metric3D v2 (Hu et al., 2024).
Control. Qilong Cheng, ECE1658 Geometric Nonlinear Control of Robotic Systems (Prof. Manfredi Maggiore), University of Toronto, 2024; virtual holonomic constraints after Maggiore & Consolini (2013), impact model after Westervelt, Grizzle et al. (2007).
2026 re-test. Python re-implementation, verification, terrain and collision model, gait optimiser, video and this page. Limitations, including the open question of the impact-map convention in the course material, are listed in the report.