Humanoid Wall Climbing
Walls are
terrain, too.
A probabilistic model of micro-spine contact, spine palms designed with it, and whole-body references generated and certified under it, so a humanoid can learn to climb vertical walls.
Get the highlights.
Read the overviewA generated reference up an exterior corner.
One spine palm flips a cinder block.
By hand, and in simulation.
Micro-spines can carry a person up a concrete wall.
A professional climber, in earlier work from our lab.
Overview
Climb to work,
not just to reach.
Damaged structures, bridges and utility poles need inspection and maintenance on rough surfaces nobody prepared for a robot. A humanoid already walks and works with its hands on the ground; we want the same body on the wall. Micro-spines grip such surfaces, but they hold only when loaded the right way, and they let go at random. We model that randomness, design the palm with the model, and generate every motion the robot learns under it.
How the parts fit
From contact model to deploy policy.
- Contact modelMeasured unit strengths, and a palm that fails unit by unit as its load is shared again.
- Palm designWhere the palm hinges on the limb, chosen with the model under hard build limits.
- Reference generationWhole-body dynamics under the model's own latch and release rules, then an independent certificate.
- Policy learningA tracking teacher per certified reference, distilled into one student that deploys.
One model throughout. The same spine model chooses the hinge, decides latches and releases inside the generator, scores each reference's reliability in its certificate, and runs in the training simulator.
Contact model
From one unit
to a whole palm.
A spine palm is twelve spine units. We measured how a single unit lets go, then modeled how a palm fails as load shifts between its units. The same model runs in the palm design, the reference generator, its certificate and the training simulator.
Twelve units. Every way they can fail.
The palm holds as long as enough units do. The model tracks which units still hold, how the load is shared among them, and every round in which they can let go.
Which units hold
A palm has \(N=12\) units. Their strengths are independent draws from one measured distribution, but their failure probabilities differ, because each unit carries its own load. A failed unit stays out until the palm latches again.
How the load is shared
The palm's wrench about the array centre: \(x\) along the rake, \(y\) lateral, \(z\) out of the wall, so \(F_z>0\) pulls. \(A_i\) is rigid-palm, equal-stiffness bolt-group statics over the units still holding, so it changes whenever one fails; failed units carry nothing.
Early failure, screened once
On a rough surface some units never catch: on the bench they let go while the shear and lateral load were still being applied, and \(p_{\mathrm{early}}\) is that share at each tested load. Each unit faces this Bernoulli trial once per latch, at its first load with every unit in place.
A strength kept for the whole latch
\(Q\) is the measured inverse CDF of a unit's pull-off force at that shear and lateral load. A unit keeps its rank \(U_i\) through every load of a latch. It fails when its pull exceeds \(C_i\), or when its shear and lateral load leave the tested range.
Fail together, share again
From a branch with mass \(m\) and survivors \(S\), exactly the subset \(B\) fails in the next round. Strengths persist, so \(q_i\) is conditional: \(a_i\) is the largest \(\alpha_i\) the unit has already held, and a load it has held before adds no hazard. All of \(B\) leaves before the load is shared again.
Sum the tree
A branch ends when a round removes no unit, or at the first release state. \(\mathcal D\) holds those states: fewer than three units, or units all on one line, which cannot carry a moment in every direction.
One realization per palm, on the GPU
\(T\) runs the cascade on fixed ranks from the screened state \(\mathbf e_0\). The simulator never evaluates \(\pi\): each latch draws its ranks and early-failure variates once, and one GPU thread runs \(T\) in every 10 ms hold window, so the rollouts themselves sample \(\pi\). Only the load-independent geometry of all \(2^{12}=4096\) survivor sets is precomputed.
A spine catches on a tiny bump when it is dragged the right way. Real walls are irregular, so not every spine finds one at once. Each spine rides on its own spring and moves on its own, so more of them end up in contact.1
One spine unit
A Rizon arm presses one unit onto a cinder block under force control. After a 10 N preload, the shear and lateral loads ramp to a test point; the normal force then steps down through zero and into tension, 0.5 N every 3 s, until the unit lets go.
With enough shear along the spines, a unit keeps holding while it is pulled away from the wall. Against the rake it holds only while pressed.



A cinder block flipped with a spine palm. In simulation the palm touches down, latches, lifts the block and releases it, the same sequence as on the bench.
Take a closer look.
One load case, round by round.
Swipe the animation sideways to read it.
The 3 × 4 palm seen from outside the wall, under an 8 N pull and 90 N of shear. Each round, overloaded units fail together and the load is shared again. Followed exactly, the tree gives a 58.4% chance that the palm holds; 600 draws, run the way the simulator runs them, give 56.3%.
Palm design
Hinged where
the spines hold.
Twelve units share one plate that turns freely on the limb, so the limb passes only a force through the hinge. Where that hinge sits decides how the force reaches the units: above the spine face, shear becomes a peeling moment that lifts the top row; off centre along the face, the normal force does the same.
Two iterations, closer to the wall.
Each version moves the hinge toward the spine face. The second sits much closer than the first, but its force line still misses the array centre.




| S ↓ T → | −20press | 0 | 10 | 20 | 30 | 45 |
|---|---|---|---|---|---|---|
| 50 | 1.00 | 1.00 | 0.52 | 0.01 | 0 | 0 |
| 100 | 1.00 | 1.00 | 0.97 | 0.34 | 0.01 | 0 |
| 150 | 0.99 | 0.99 | 0.98 | 0.81 | 0.18 | 0 |
| 200 | 0.93 | 0.90 | 0.88 | 0.74 | 0.36 | 0.01 |
| 250 | 0.92 | 0.91 | 0.83 | 0.60 | 0.20 | 0.02 |



The hinge, chosen with the model.
Every design variable stays inside what can be built: hinge geometry, stop angles and spring rates come from real parts.
Hinge height
One palm under 150 N of shear and no pull, 20,000 draws of unit strength. Height \(h\) is measured from the spine face.
- \(h=0\)
- holds with probability 0.985
- 3 mm
- 0.907
- 5 mm
- 0.223
- 10 mm
- 0
Each millimetre of height adds about 0.6 N of pull on every top-row unit at this shear.
A fork palm for the 27-DoF wrist
Two columns of six units clamp the wrist roll axis, with the palm centre level with it. A pin hangs the palm in a U-fork: it tilts ±6° on its stops and slides 2 mm along the normal on preloaded springs.
In fourteen corner load cases the forearm's three 9 N·m motors stay within their limits; a rigid flange mount exceeds them. Designed and checked in simulation.
Reference generation
References the
spines can hold.
A spine palm latches only after enough preload, holds only while each unit stays inside its measured limits, and lets go when the load says so. A kinematic reference cannot know when any of that happens. We generate each reference as a whole-body dynamic trajectory under the training simulator's own contact rules, then certify it from the stored trajectory alone.
A task says what. The generator decides how.
A task contributes only an adapter. Generation, the event rules and the certificate are the same code for every task. Select a block to see how it works.
Swipe the figure sideways, or pick a block below.
Language and files in
A task starts as a description and its files: the robot, the objects, the CAD of the surfaces to climb or grip. An LLM agent, or a person, writes the task adapter from them.
Upstream and optional, a GPU statics search chooses the pad design and a chain of whole-body static keyframes for the plan.
A failure says why
When a step is infeasible or a check fails, the generator reports the time, the phase, the conflicting constraints and the shortfall.
That report goes back to the task input. The design variables or the plan are revised, and generation resumes from the last phase checkpoint instead of from the start.
Everything task-specific, in one place
- Scene
- The robot, the objects, the CAD surfaces, the pad layout and the world.
- Contact plan
- Phases, each with a contact mode per limb and the event that ends it.
- Interaction
- Goals and style, written in the frame of the related object: a block's end face, a wall's corner.
- Reference problem
- Design variables \(\psi\), costs, and the task's own checks for the certificate.
The same problem always gives the same bytes, so a reference is reproducible from its adapter alone.
A start the robot can hold still in
- Whole-body IK
- The robot onto the first phase's contact targets.
- Passive joints
- Free hinges and palm springs settled by their springs, stops and gravity.
- Static hold
- A QP for the joint torques and contact forces that hold that pose, inside every limit and unit domain.
Joint torques only. No motor, PD or servo model.
Each integration step solves one QP; every 20 ms the plant decides what changed.
A phase machine sets the problem
Each phase of the contact plan says which contacts are held and what the task asks for. It ends when its exit event fires, a latch, a release or a touchdown, never at a scheduled time.
Equations of motion, exactly
The unknowns are the joint torques \(\tau\), the contact forces \(\lambda\) and the reactions \(r\) of passive joints held on their stops. The accelerations \(\dot v\) are eliminated through this equation, so it holds at every step.
Held contacts and limits
\(\mathcal K\) is the friction cones and, for a latched spine palm, every unit's load inside its measured domain and a trust box around the current load.
Cost: the task, and the chance to hold
\(J\) is the probability that every latched palm keeps holding. Each solve is checked against its KKT conditions, or the step fails.
A holding probability the solver can climb
The plant's failure cascade is run on 512 fixed draws of unit strength, with each of its rules softened so the result is smooth in the load. Near the current load it enters the QP as a quadratic model.
Integrate
Contact drift is removed by a mass-weighted projection, and a passive joint that reaches its stop takes an inelastic impact. Every step stores \(q, v, \dot v, \tau, \lambda\), contact points, modes and events.
An event referee every 20 ms
4,096 persistent realizations of a latched palm's units follow it through holding windows, early failures and cascades. Rigid parts touch down and lift off. Events end phases, so the plan never schedules a contact change that only the plant may decide.
Trust the trajectory, not the generator. The certificate reads only the stored trajectory and recomputes every claim with its own code.
Trajectory certificate
A reference passes when all ten checks pass.
- T1
- Equations of motion, by inverse dynamics
- T2
- Contact force laws: cones, unit domains, stops that only push
- T3
- Integration, and how far drift corrections and impacts moved it
- T4
- Geometry: planned contacts touch, nothing else does
- T5
- Joint ranges and torque limits
- T6
- Events replayed through a fresh referee, with the release rule
- T7
- Impacts and closing speeds
- T8
- Convergence: the same plan at half the step
- T9
- The 50 Hz clip against the trajectory
- T10
- The task's own checks
Reliability and release
A legal release unhooks. The palm is pulled off along the normal during its unloading phase, while every unit still holding carries at most 0.2 N of shear along the spines. Pulling off under shear is a failure, not a release.
R1, per latch. Each of 65,536 realizations draws its unit strengths once and follows the stored loads through the plant's holding windows, failures and load sharing. It reports the share that hold through the phase, and the share that release legally.
R2, the whole task. Realizations that release legally are grouped by release step; each group resumes the generator from the unloading checkpoint and is certified again. Intervals are Clopper–Pearson.
Two tasks. One generator.
A block flip with one hand, and a climbing cycle up an exterior corner, both on the 27-DoF robot with fork palms. Only the adapters differ.
Block flip completes (R2): the palm holds, releases legally and the block ends upright.
Corner cycle, all eight latches hold (product of R1 over the cycle). The weakest single latch, a foot, holds at 0.94.
Certificate checks pass on both. Half-step convergence (T8) is still open.3
Policy learning
A teacher per skill.
One student to deploy.
Each skill is first learned by its own teacher, which tracks a certified reference and sees what only the simulator knows. All teachers are then distilled into one student that acts from proprioception and an operator's skill command.2
Stage I
Skill teachers
- Certified referenceOne per skill from the generator. Each starts and ends where its neighbours do, so the transitions are learned too.
- Teacher \(\pi_k\)Tracks its reference. Asymmetric actor–critic: latch states, unit strengths and contact forces enter the critic only.
- Wall-climb simulator500 Hz physics with the spine model, its random failures and domain randomization; adaptive sampling of start phases.
- Skills
- walk
- onto the wall
- climb up
- climb down
- off the wall
Climbing down is generated, not replayed. A reversed climb would pull the spines against their rake, so every skill gets its own reference and certificate.
Stage II
One student, PPO with DAgger
- ObservationsProprioceptive history, the wall pose from motion capture, and the skill the operator selects.
- Student \(\pi_S\)One policy for every skill. Whether a palm is latched is inferred from proprioception.
- Teachers \(\pi_k\)Label the states the student visits with the active skill's teacher action.
Results
Policies,
task by task.
In the order a mission needs them: get from the ground onto the wall, then climb it. Both run in simulation with the spine model's random latches and failures.
Task 1
From the ground onto the wall.
Standing on the floor, the policy places its hands and feet on an inclined wall, latching each palm on the way: the move every mission makes between ground and wall.
Task 2
Up a vertical wall.
A teacher tracks a kinematic climbing cycle on a 90° wall. In a 30-second rollout its spine engagement follows the reference schedule closely, and no actuator goes above 72% of its torque limit.4
Engage-schedule match between the policy and the reference over the 30-second rollout.
Fraction of time each limb is engaged. The reference asks for 0.82–0.84.
Peak torque-to-limit ratio, at the left shoulder pitch. The most-loaded joint keeps a margin throughout.
The 30-second tracesSpine engagement and torque, limb by limb
Two rewards for spinesHow this teacher is shaped to engage on time
Spines hold only when they engage on time and with enough preload. Two terms shape that.
Schedule mismatch discount
When a limb's engagement disagrees with its engage gate for longer than a grace period, every tracking reward is discounted, down to a quarter.
\[\begin{gathered}m_h=\mathbf 1[\hat e_h\ne e_h]\cdot\min\!\Big(\frac{d_h\,T_{\mathrm{cyc}}}{\tau_g},\,1\Big)\\ G=f+(1-f)\Big(1-\frac1H\sum_h m_h\Big)\in[0.25,\,1]\end{gathered}\]with \(\tau_g=0.25\) s and \(f=0.25\). Joint-position, end-effector and root-orientation tracking are multiplied by \(G\):
\[\begin{aligned} r_{\mathrm{jpos}}&=\exp\!\big(-\tfrac{1}{\sigma^2}\,\mathrm{mean}_j(\hat q_j-q_j)^2\big)\cdot G\\ r_{\mathrm{jvel}}&=\exp\!\big(-\tfrac{1}{\sigma^2}\,\mathrm{mean}_j(\hat{\dot q}_j-\dot q_j)^2\big)\\ r_{\mathrm{ee}}&=\exp\!\big(-\tfrac{1}{\sigma^2}\,\mathrm{mean}_h\lVert\hat{\mathbf p}^r_h-\mathbf p^r_h\rVert^2\big)\cdot G\\ r_{\mathrm{ori}}&=\exp\!\big(-\tfrac{1}{\sigma^2}\,\theta_{\mathrm{geo}}(\hat q^{\mathrm{root}},q^{\mathrm{root}})^2\big)\cdot G \end{aligned}\]with \(\sigma\) = 0.2 rad, 1.5 rad/s, 0.1 m and 0.3 rad, in order.
- \(h\)
- end effector: two hands, two feet
- \(\hat e_h,\ e_h\)
- estimated engage gate; engaged now
- \(d_h\)
- nearest normalized distance to a phase edge
- \(T_{\mathrm{cyc}}\)
- reference period
Scheduled press
Rewards pressing the palm into the wall, up to 12 N, while a limb is in its engage phase, or within 0.3 s of it, but not yet engaged. It shapes the preload that lets spines catch.
\[\begin{aligned}r_{\mathrm{press}}=\sum_h\ &\underbrace{\min\!\Big(\frac{F_h^{\mathrm{pad}}}{12\ \mathrm N},\,1\Big)}_{\text{press ratio}}\\ \cdot\ &\underbrace{\mathbf 1\Big[\Big(\hat e_h\ \lor\ t_h^{\mathrm{grip}}\le\frac{0.3\ \mathrm s}{T_{\mathrm{cyc}}}\Big)\land\lnot e_h\Big]}_{\text{reward gate}}\end{aligned}\]- \(F_h^{\mathrm{pad}}\)
- press force at end effector \(h\)
- \(t_h^{\mathrm{grip}}\)
- normalized time to the next engage
- \(\hat e_h\)
- engage phase (estimated engage gate)
- \(\lnot e_h\)
- not engaged now
Infrastructure
Walls to
climb on.
Two walls for the climbs on hardware. A rough stucco panel, close to a real outdoor wall, for the spines to grip, and a full-height wall on an aluminum-extrusion frame.
A stucco panel, made by hand.





A full-height wall frame.


Supplementary
On the real robot.
Bringing up the real robotThe deployment stack, and a first sim-to-real test on the ground

1Robot on gantry
Suspended, feet unloaded.

2Power on, go to ZERO
Cubic trajectory from the power-on pose.

3Lower to ground
Feet loaded, gantry slack.

4Unlock, select task
Gamepad, LT + RT.

5Task running
The control loop below.

6Power off
Return to ZERO first, then hoist up.
Going to ZERO interpolates from the power-on pose with zero joint velocity at both ends: \(q(s)=q_{\mathrm{init}}+(q_{\mathrm{ZERO}}-q_{\mathrm{init}})(3s^2-2s^3)\), with \(s=t/T\).
One control loop, for robot and simulator
- Operator
- Gamepad publishes commands
- Web panel read-only telemetry; starts and stops processes
- LCM busUDP multicast between processes.
- Real-time loop, 500 Hz
- Safety guards
- Task scheduling zero, walk, walk_amp, hold
- RL policy inference 50 Hz
- Telemetry and logging 50 Hz
- Backend
- Real robot fieldbus at 500 Hz to motors and sensors
- Simulation MuJoCo model
Status key
Not finished yet.
A mark on a clip says how far its task has come. Clips without a mark are complete as shown.
Reference only
A generated or scripted reference motion. No policy has been trained on it yet.
Block flip · exterior corner
Policy in simulation
A trained policy that so far runs only in simulation. It has not been deployed on the robot.
Ground to wall · vertical wall
- The palm builds on linearly constrained compliant spines: S. Wang, H. Jiang and M. R. Cutkosky, “Design and modeling of linearly-constrained compliant spines for human-scale locomotion on rocky surfaces,” The International Journal of Robotics Research, 36(9):985–999, 2017. doi:10.1177/0278364917720019
- The teacher–student structure, with one tracking expert per skill distilled by PPO and DAgger, follows “Perceptive Humanoid Parkour,” arXiv:2602.15827, 2026.
- From the latest generated block flip and corner cycle, with 65,536 realizations each.
- From one 30-second rollout of the teacher policy on a 90° wall in simulation.
Paper in preparation
Humanoid Wall Climbing with Compliant Spines
1Stanford University2Cornell University
†Co-corresponding authors