Recursive Self Improvement for Hardware / Paper 01 / Interactive edition
Body, Brain and Structure
TriangleTinyTriangle Engineering LtdJuly 2026Triangle Gym
Abstract
Legged robots are usually designed by a chain of specialists: one chooses the body, another writes the controller, and a third sizes the structure against loads they estimate. Each handoff discards information, and work that designs body and controller together rarely carries through to manufacturable structure1,2,3. This paper reports one pipeline from task to part. A person states what the robot is for, which components can be bought and which materials can be printed. The pipeline returns every dimension of the body, a controller that drives it, the loads that its behaviour produces, and printable, stress checked geometry for every structural member. On a quadruped the full run took about 2.5 hours on one GPU, searching 288 bodies and generating 4.84 kg of structure for a 17.9 kg robot. The run's most useful finding is how such a pipeline fails: almost every defect produced a complete run with plausible numbers. Each was caught by a verification gate written for it, and those gates, inherited by every later project, are how the design engine improves with use.
- Bodies searched
- 288
- Best body
- 17.9 KG
- Generated structure
- 4.84 KG
- Spec to geometry
- 2.5 H, 1 GPU
Mesh / The design, as generated
This view needs WebGL, which this browser has turned off. The rest of the paper works without it.
Train 28.0 min
Search 117.4 min
0Loads under 1 min / Structure 5.4 min2.5 h on one RTX 3090
Fig. 1The best body as the pipeline built it: the five generated parts exported by the run, mirrored for the right side. Stippled parts were generated; flat grey parts were bought (RS03 actuators, pushrods, feet). Drag to turn it. The bar below is wall clock per stage, to scale.
Mesh / The run, end to end
This view needs WebGL, which this browser has turned off.
Fig. 2The design across the whole run, under one camera and one scale. It opens on the 23.2 kg reference body the pipeline was first validated on, with only the thigh and shank generated. It then steps through the best body of each of the 24 search generations, and follows the searched body through 30 July as each structural member is generated and corrected. Search bodies are drawn from their dimensions alone, because no parts were generated during the search.
1The loop
RSIH, recursive self improvement for hardware, is a design engine intended to get better at design with every project it runs. This paper reports its first complete pass. The engine has three layers: a language model that frames the problem and writes the project17; a pipeline of stages that turns the project into a robot; and a library of verification checks, the gates, that decide whether each stage's output is credible before the next stage uses it.
Stages communicate only through files. Every intermediate result can therefore be audited and every stage re-run on its own, and every figure in this paper reads one of those files.
Streamline / Pipeline
Fig. 3Work flows left to right through the stages. Each crossing between stages is a file and a gate. When a run exposes a failure no gate caught, a new gate is added to the shared library, so the next project starts with a better tool. That return path is what makes the engine recursive.
What a human writes, and what comes back
| Specification, from a human | Design, from the system |
| Kinematic topology: 12 actuated joints, three per leg, joint axes, the knee drive | All 16 dimensions: trunk, hip placement, link lengths, stance, where the battery and computer sit |
| Task suite: six scenarios, with terrain, commands, disturbances, payload and weights | Which actuator to fit at each of the three joint groups |
| Component catalogue: actuator mass, torque, inertia, price, envelope drawings | A control policy that drives the chosen body |
| Material catalogue: stiffness, allowable stress, density, minimum wall | Design load cases for every member, measured from behaviour |
| Safety factor, design percentile, voxel size | Five members as watertight, stress-checked meshes, and a design record |
There is no target mass, length or height anywhere in the system. Those are outcomes.
2The body
The body is a parametric family. Sixteen continuous variables set every dimension, and three categorical genes choose an actuator for the abduction, hip pitch and knee joint groups from a catalogue of two quasi direct drive modules: the RobStride RS03 (0.88 kg, 60 N·m peak, $214) and the RS04 (1.42 kg, 120 N·m peak, $267).
Every bound follows one rule: a bound may encode a physical limit, never an expected answer. The minimum thigh length, for example, is the largest actuator's radius plus a pivot boss, so it moves if the catalogue changes. Because the optimiser is continuous, each actuator gene is a number between 0 and 1 mapped onto the catalogue (1).
a_j = A[ min( floor(g_j * |A|), |A| - 1 ) ] g_j in [0, 1](1)
Body / Side view, to scale
Fig. 4Seven of the sixteen variables, each slider spanning its real search bound. Standing height is not a variable: it falls out of the link lengths and stance angles, with joint zero defined as leg straight down. The search found heights from 139 mm to over 400 mm.
The hip pitch and knee actuators share one axis at the top of the thigh, and the knee is driven by a pushrod, so the knee actuator's mass sits at the hip rather than on the swinging leg. The stack sits forward of the abduction actuator, on the roll axis, rather than to the side. On a reference body this reduced the abduction joint's inertia from 0.0923 to 0.0479 kg·m² and its worst gravity holding torque from 4.27 to 1.40 N·m.
3One policy for every body
Scoring a body requires a controller to walk it. Training one for each of 288 candidates would take weeks, so a single policy is trained across a distribution of bodies and then frozen4,5. To drive a body it has not seen, the policy must know which body it is in, so its observation includes a description of its own morphology (2).
o_t = [ v, w, g, c, q - q_stance, dq, a_(t-1) ; phi(theta) ]
48 proprioceptive values 23 body features = 71(2)
Stipple / 4096 environments, 256 bodies
Fig. 5Each point is one simulated environment; each body is tiled across 16 of them, shown as squares. Hover to pick a body. On the right is that body's 71 value observation: the 48 proprioceptive values move every control step, the 23 body features stay fixed for the episode. The bodies here are taken from the search history so their features are real; training drew its 256 bodies uniformly from the same space.
The features are the 16 normalised design variables, four ratios (reach over 0.6 m, shank over thigh, mass over 25 kg, thigh over trunk) and the three actuators' peak torques. The last group lets the policy distinguish a 60 N·m knee from a 120 N·m one.
Vectorised GPU physics varies only the dynamic fields of the model across environments, so the features cannot be stored as metadata. Each environment must recover its body's description from its own physics fields, which requires the compile step to be invertible (3).
exists psi : psi( dynamic_fields( compile(theta) ) ) = phi(theta) for every theta(3)
Actuator identity is recovered from the actuator force range, the only dynamic field it affects. An early test of this condition passed for months without being able to fail, because it never varied the actuators; Section 8 returns to this.
The policy is trained with proximal policy optimisation6 across 4096 parallel simulated environments7,8,9.
Steps60 MParallel envs4096Wall clock28.0 MINEval return1631
4Searching bodies
With the policy frozen, scoring a body is a rollout of about 25 seconds across all six scenarios. CMA-ES10,11 searches the 19 dimensional space, 16 variables and 3 actuator genes, in 24 generations of 12. The objective is the weighted mean return less a steep penalty when the body demands more of its actuators than they can give (4).
J(x) = sum_i w_i R_i(x) / sum_i w_i - 400 * [ (u_rms - 1)+ + (u_peak - 1)+ ](4)
Here urms is the worst joint's RMS torque over its continuous rating, which governs motor heating, and upeak is its peak torque over the transient rating. This duty constraint replaces a target mass: a heavy body is penalised not for its mass, but because the motors it chose cannot carry it.
Stipple / Best body by generation
Fig. 6The highest scoring feasible body found by the end of each generation of the search, drawn from its searched dimensions in side view and to one scale, so a change in size is a real change. Press play to watch the search settle.
Stipple / 288 bodies
Fig. 7Every body the search tried. Filled squares carry the RS03 at all three joints; hollow squares carry at least one RS04; crosses broke the duty limit. The outline is the current generation's hull, the stepped line is the mass and score Pareto front. Hover any point to draw that body. The lowest 3% of scores are pinned to the bottom edge.
The search converged on the lighter actuator at every joint. Among feasible bodies, those with the RS03 throughout have a median mass of 16.0 kg against 21.9 kg for bodies with any RS04, at a slightly higher median score (1.80 against 1.77). Refitting the winning geometry with an RS03, RS04, RS04 set, a plausible human choice, adds 4.3 kg and $424. The optimiser declined to spend either.
Stipple / Actuator choice per generation
Fig. 8Each cell is one generation of 12 bodies: an ink square for every RS03, a hollow square for every RS04. The hip pitch slot starts almost all RS04 and ends almost all RS03. Duty is what makes this choice mean anything; without it, the lighter module is free mass and the gene just drifts.
5The task suite sets the scale
The search converged on a small robot: 17.9 kg for the best scorer, and 14.8 kg for the lightest feasible body, which stands 139 mm tall. This is not a failure of the optimiser but a consequence of what the task suite rewards.
Stipple / Reward against mass, per scenario
Fig. 9Feasible bodies only, with the least squares slope fitted live from the data. Every slope is negative. The lowest 3% of rewards sit on each panel's bottom edge; the fit uses all of them. Push recovery is the steepest by far: short, wide, low bodies resist a shove, which is physically right.
A task suite must contain something the robot can only do by being big enough, or size becomes an artifact of how hard control is.
An obstacle height, a sensor height, a payload that cannot be carried otherwise. This is a specification problem rather than an optimisation one, and it does not show in the aggregate scores: nothing in Fig. 7 looks wrong. Later projects of the engine make it a required input, the capability floor.
6Loads measured from behaviour
The best body is walked by its policy through all six scenarios for 10 seconds each at 250 Hz, giving 60,000 samples per channel. At each step, inverse dynamics gives the wrench each body part applies to its parent. The wrench is transferred to the joint and resolved along the member's axis into the four loads a beam is sized by (5), and each design load is a safety factor applied to its 99.9th percentile (6).
m_a = m_c + (p_c - p_a) x f
F_ax = f . e F_sh = |f - F_ax e| M_t = m_a . e M_b = |m_a - M_t e|(5)
X_design = 1.5 * P99.9( |X| )(6)
Field / Design loads, best body
Envelopes, 60,000 samples
Fig. 10Front leg of the best body. Arrows are the design axial and shear forces on the selected member, the arc is its bending moment, all to one scale. Each envelope row runs from zero to the design value: mean, RMS, 99.9th percentile and observed maximum. A safety factor applied to a finite sample can land above the maximum; that is intended.
Before any load reaches a part, the extraction must reproduce statics on the same body. Standing still, the four ground reactions must sum to the body's weight, and the force at each knee must equal its foot reaction less the weight below the knee. On this run both hold exactly: 176.8 N = 176.8 N and 45.4 N = 45.4 N16.
Readout / Actuator duty, best bodyRS03 / 20 N·M RATED / 60 N·M PEAK
Fig. 11Thermal duty is RMS torque over the continuous rating; transient duty is the design torque over the peak rating. The winner sits comfortably inside both, so the duty constraint was binding on the population, not on this body.
7Generating the structure
Each member is generated by three dimensional topology optimisation on a 6 mm voxel grid, using the SIMP formulation12,13,14. The solver keeps material where it carries load and removes it elsewhere, minimising compliance within a volume budget (7).
min_rho C = sum_k f_k . u_k s.t. K(rho) u_k = f_k , sum_e v_e rho_e <= V*
E_e = E_min + rho_e^3 (E_0 - E_min)(7)
Interfaces where actuators bolt on are forced solid, actuator envelopes and access channels are forced empty, and the volume budget applies to the remainder. The solver runs matrix free on the GPU in double precision and stops with an error if its residual does not converge. Its result is a density field between 0 and 1, and a part is obtained by choosing where to cut it.
Voxel / Density field, from the run
This view needs WebGL, which this browser has turned off.
Fig. 12Each part three ways, all from the run. Voxels, density: the density field itself; cubes are above the cut, points are grey material below it. Lower the cut and grey material joins the part: heavier, and weak. Voxels, stress: the part as shipped, with cubes only where von Mises stress exceeds the slider; the rest is points. Mesh: the exported part, shaded, or stippled by stress, where dot density is stress over the 30 MPa allowable. Drag the mesh to turn it.
| Part | Vol. frac. | Mass kg | x n | Stress, field (conservative) | Stress, binarised16 |
Two stresses are reported because they answer different questions. The field value evaluates grey elements with solid stiffness, so it overstates stress and never understates it. The binarised value re-solves the part as exported. Every part passes the 30 MPa allowable of PA12-CF. The stress fields in Fig. 12 were recovered by rebuilding each part's finite element problem from the run's own loads and interfaces and re-solving the binarised part; all five peaks reproduce the reported binarised values to within 0.05 MPa. With the pushrod, the generated structure totals 4.84 kg, against the 5.09 kg the search assumed.
Volume fraction is not a monotone knob
Below a certain volume fraction the cut must drop to keep the load path connected, which brings grey material into the part and makes it heavier and weaker at once. The shank in aluminium weighs 0.230 kg and peaks at 358 MPa at a volume fraction of 0.05, against 0.190 kg and 69.5 MPa16 at 0.08. Each part is therefore taken to its own governing point, which is why the table shows five different values. The thigh needs 0.38 in PA12-CF where every other part needs between 0.08 and 0.15: it carries 20.3 N·m of torsion, sixteen times the shank's, and the solver builds it as two booms with no web. For this part the printed material is the wrong choice, and the pipeline shows it with numbers.
8Designing for silent failure
The most useful finding of this run is not that the pipeline works but how it failed. Almost every defect produced a complete run, plausible numbers and a valid mesh. Optimisation pipelines coupled to physics rarely crash; they answer a different question from the one asked, confidently and in the same format as a correct answer.
Each gate below was written after a specific silent failure, and each has since caught a real one. Every gate is mutation tested15: the code it guards is deliberately broken to confirm that the gate fires. Break any of them to see what it guards against.
Fig. 13Verification gates and the failures that created them. Mutation testing is how the vacuous actuator test in Section 3 was found.
A gate you cannot make fail is not a gate.
One gate is incomplete. The statics check compares force magnitudes, and |f|² = Fax² + Fsh² about any axis, so a wrench resolved about the wrong axis passes while reporting axial load as shear, which is exactly the error that mis-sizes a member. The fix, a third identity projected onto the member's own axis, has not yet been written.
9What makes it recursive
A pipeline that designs a robot is a generator. What makes the engine recursive is the path back into the tool. In the companion paper17, a language model frames the problem, writes the robot's project against a fixed interface, runs the stages in order at the right cost and reads the results back. The model performs none of the numerics, and the pipeline makes none of the decisions. When a diagnosis cannot be settled from the results, the model writes a new gate into the shared library, and every later project inherits it.
The gates in Section 8 are the record of that loop, run by hand. Whether each project measurably improves the next has not yet been tested; that requires a fixed benchmark of design tasks.
Readout / What has to re-run
Fig. 14Because stages only exchange files, a change only re-runs what is downstream of it. The expensive question is always whether the policy still applies.
10Conclusion
A legged robot can be designed from a task description to printable structure by one pipeline, in about 2.5 hours on one GPU, with every number traceable to the files the run wrote. Its results follow from what it was given: the duty constraint, not a target mass, chose the lighter actuator, and a task suite with no reason to be large produced a small robot. Its most useful lesson is how such a pipeline fails: silently, with complete and plausible output. Verification gates written for each such failure, and inherited by every later project, are how a design engine of this kind improves with use.