Skip to content

Exporting a robot

experiments/export.py --type <type> writes exports/<type>/:

File Content
control.json the evolved controller for the ESP32 firmware (format 3), described in formato-controle.md
bom.md, bom.csv servos, printed parts with quantities and material, electronics, screws, tyres
assembly.md one row per servo in layout order: id, node slot, parent chain in words (for example core right-front > joint pitch > joint roll), axis, link length, sign; mounting direction and calibration step
parts/*.stl one file per distinct size (needs the cad extra): link_{L}x{W}x{T}.stl (bent links add _L{deg} or _arc{deg}; a joint's link adds _u{axis} for the fork, a tip cradle _c{axis}), elbow_{D}mm_{A}deg_{W}x{T}.stl, foot_{R}.stl (blade, pad and claw feet: foot_{shape}_{R}.stl), wheel_{R}.stl, spring_{W}x{B}.stl, tail_{L}.stl, skid.stl, spike.stl, caster_wheel_{R}.stl, caster_fork.stl, cradle_{axis}.stl (variants _w{deg}, _back, _free) with wedge_{deg}.stl, segment_plate_{L}x{W}.stl for each spine segment, the torso as torso_plate.stl or torso_tile_{i}.stl, and splice_plate_{span}.stl across each torso cut (sizes in whole millimetres)
robot.xml the MuJoCo model, for inspection

The export walks the module tree: every joint, link and spring needs a link of its own length and section, every elbow an elbow plate for its distance and angle, every servo one cradle, every wheel, caster, tail, skid, spike and foot (explicit, or the free tip of a limb) one print. Links, elbows, feet and springs get one STL per distinct size. Springs and spikes are printed in TPU, the rest in PLA. The bill of materials counts everything from the tree.

A servo is held by a printed cradle that belongs to its parent, around the body as the simulation places it (0.4 mm of slack per side, an M2 cap on each horn face with the four screws into the tapped holes). On the torso the cradle is its own part (cradle_{axis}.stl) with a foot carrying the common M3 pattern; at the tip of a link it is printed as one piece with the link, and an elbow plate ends in the cradle of its child. The joint's own link starts as a U fork that clasps both horns of the servo, one arm on each horn face with the horn hole pattern, and joins the plate beyond the servo, out of the circle the cradle fills, so the link turns the whole joint range.

The foot goes down to the torso plate on the side that points down. When the slot is rolled by an angle that is not a multiple of 90 degrees (up to 20), the foot is tilted and slid along the axis, and a printed wedge_{deg}.stl between the tab and the foot takes up the tilt; face mounts and segment plates never get one. A servo whose output axis stands vertical bolts down behind itself (_back). A face mount, a roll joint whose body would stand through the plate, or a roll steeper than 20 degrees gets a cradle without a foot (_free) that you have to hold with a bracket of your own.

Parts that are rigid with a link and overlap it are printed as one piece with it: a plain link hung on a joint or on another link (_k{n} in the name), the bar to a passive module on the side of a link (_b{distance}a{angle}, ending in a spigot for a foot), and the cradle of the servo at the tip. The side servos hang on elbow plates bolted to a fin the link tip narrows to; the fin and the cut beside it follow the cradle's distance, angle and roll (_e{at}x{x0}x{x1}). The torso plate sits plate_drop mm below the joint plane, 22 or more when a servo on an edge hangs lower. Everything is drawn in whole millimetres and degrees, so a part can sit half a millimetre from the simulation's frame; the check places the modules where the printed parts put them.

python tools/check_assembly.py --archive a.pkl --type <type> builds every part at its simulation frame and reports each pair of printed parts and servo bodies that overlap, at the spawn pose and at four poses of a straight walk (0.5, 1.5, 2.5 and 3.5 s). Only the screwed laps (0.5 mm or less: a cradle on its servo, an elbow tongue on its link, a wedge on its tab) are allowed. The simulation collides the same shapes (cradle, fork, bosses, elbow strut, torso plate and tabs), so a body it accepts is meant to pass this check.

python tools/parts_sheet.py exports/<type> draws every STL of the export on one image (exports/<type>/parts.png), with its bounding box in mm, to check the parts before slicing.

Hollowed parts (optional)

experiments/export.py --type <type> --organic also writes parts_organic/: the links and elbow plates hollowed by 2D topology optimisation (darwinbot/organic.py), with the horn end clamped and the stall load at the far end. Evolution chose each part's size and interfaces; the optimisation only removes material from the middle, keeping a rim along every edge and a solid boss at both ends, so holes and outline are unchanged. Parts typically keep 50 to 90% of their material, and each takes about 10 s.

Two cautions: the load case is in-plane only (out-of-plane bending is carried by the rim, not optimised), and the hollowed robot is lighter than the one evolution scored. Nothing here has been printed yet.

Servo dimensions in darwinbot/parts.py (horn and mounting holes, body size) come from the SO-ARM100 STEP model of the STS3215, not from a caliper measurement: check them against a real servo before printing.