# Stair Rover: building the real robot

The simulation in this folder's parent is the digital twin of this robot: it loads the same part models
that go to the printer (`models/`), places them from the same description (`models/machine.json`) and
moves them the way the servos would. Everything here is generated by `build.py`.

**State of this design:** drawn from the manufacturers' dimension drawings and checked in software only.
Nothing has been printed or assembled, and the software that would run on the robot does not exist yet.
Print `servo_test_plate.stl` and `rail_test_piece.stl` first.

- `stl/` – printable parts, already lying in their print orientation, millimetres
- `step/` – the same parts as STEP for a CAD program
- `PARTS.md` – all lists: printed parts, bought parts, screws, cable lengths, servo numbers
- `stair-rover-parts.zip` – `stl/`, `step/` and the lists in one file
- `build.py` – the parametric source (CadQuery); the numbers it shares with the simulation are in `../spec.json`
- `check.py` – the software check described below

## The robot in short

- A chassis 143 mm long that stands on two driven wheels in the middle and four steel balls (two in
  front, two behind; the front pair is 1 mm higher, so it rests on the wheels and the rear pair).
- A front foot with two rollers and a rear foot with two driven wheels. Each moves up and down on a
  printed rail with a rack (module 1.5, 20-tooth pinion, 94 mm per turn of the servo). The two rails and
  the two carriages are the same parts. The front rail is fixed to the chassis and the carriage carries
  the foot; at the rear the carriage is fixed to the chassis and the rail carries the foot.
- Six Waveshare ST3215 bus servos: two lifts, two drive wheels, two wheels on the rear foot.
- Raspberry Pi 5, lidar on top of the front rail for the map of each floor, a camera and a zone distance
  sensor looking down ahead, a second zone sensor looking down behind, two distance sensors under each
  foot (they feel the edge of a step) and one on each side, an orientation sensor.
- 231 mm long, 220 mm wide, about 370 mm high, about 1.5 kg. Steps up to 200 mm high.

Why the drive axle is in the middle of the chassis: after a step the robot stands with its rear balls
just past the edge it climbed, and before the next step with its front just short of the next edge. With
the axle halfway between those two positions, one arc about the centre of a turning stair takes it from
one to the other. With the axle at the rear (the first layout) every such arc ended about 3 cm too far
inside the turn.

## What the simulation says and does not say

`node tests/matrix.mjs` runs the robot up and down some 2,500 staircases (`tests/results.json`, shown on
the page). It simulates where the robot rests on its wheels, what would tip or fall, what would touch
the stairs, wheel slip and noisy sensors. It does **not** simulate: flexing parts, play in the rails,
slipping on a polished nose, carpet, open risers, or how the camera and the zone sensors find the edge of
a step. The controller is handed that edge as a line, a few millimetres off; writing and proving that
perception on real stairs is the largest open piece of work.

`python hardware/check.py` intersects every model with every other, the feet at nine heights each, and
compares the models with `spec.json` (where the wheels touch, what the simulation assumes about
clearances and outlines).

## Printing (Bambu Lab X2D)

- PETG for everything except tyres; TPU 95A for `drive_tyre`, `rear_tyre` and `roller_tyre`.
- 0.2 mm layers, 4 walls, 30 % gyroid infill; 6 walls and 50 % for `rail`, `carriage` and `lift_pinion`.
- `rail` is 312 mm long and lies diagonally on the bed (240 x 240 mm), on its side, so that the teeth of
  the rack are drawn in the plane of the layers. No supports.
- `chassis` prints as it stands; supports only inside the two horn openings. `front_foot` needs supports
  under its neck, `sensor_mast` prints upside down.
- The sliding fit between rail and carriage is drawn with 0.25 mm clearance per side. Try it with
  `rail_test_piece` first. If it binds, sand the rail; if it rattles, a strip of thin tape inside the
  sleeve takes up the play.

## Assembly

1. **Servo numbers first.** Out of the box every servo has ID 1. Connect one at a time to the bus
   adapter and set the IDs from the table in `PARTS.md` with Waveshare's servo tool. Set the two lift
   servos to step (multi-turn) mode and the four wheel servos to wheel mode.
2. **Heat-set inserts.** Three M3 inserts into the underside of each `carriage`, four into the caster
   towers of the `chassis`, four into the posts of the `deck`.
3. **Servos into their walls.** Each servo sits behind a 4.4 mm wall with its horn through the 21 mm
   opening, held by four 2 x 6 mm self-tapping screws into the holes of its output face: two in the
   chassis, two in the `rear_foot`, one in each `carriage`.
4. **Wheels and pinions.** Push the tyres over the wheels. Wheels onto the horns with four M3 x 8,
   `lift_pinion` with four M3 x 16.
5. **Balls.** Press the four steel balls into their cups from below.
6. **Front rail.** Slide a carriage onto a rail from the top, pinion in the rack. Stand the rail's web in
   the fork at the front of the chassis and clamp it with four M3 x 25 and nuts. Bolt `front_foot` under
   the carriage (three M3 x 12 from below), rollers with their bearings on M5 x 30.
7. **Rear rail.** Bolt the second carriage onto the pedestal at the back of the chassis (three M3 x 12
   from below). Stand the second rail in the socket of `rear_foot` (two M3 x 25), then feed it up
   through the carriage.
8. **Decks.** Battery on the floor between the drive servos, strap through the slots. `deck` with the
   Pi on the four towers, `top_deck` with adapter, converter, multiplexer and orientation sensor on top.
9. **Sensor mast** onto the top of the front rail (two M3 x 25), lidar, camera and zone sensor on it.
10. **Cables.** Routes and lengths are in `PARTS.md` and visible on the page. The four marked *moving*
    hang in a loop; tie them at the slots in the rail webs so that the loop cannot reach a wheel or the
    rack. The cables supplied with the servos are too short for these four.

## Known weak points, before anything is built

- **Where the lift is after switching on.** The servo knows its angle within one turn, and a lift needs
  2.5 turns. The Pi has to store the turn count and check it against the distance sensors under the feet.
  A servo without power does not hold much: if the battery is pulled while the robot stands on its feet,
  it sinks.
- **The rails are printed.** Play and friction of a 312 mm printed slide carrying half the robot on a
  44 mm lever are not known until one is made.
- **Tread depth.** The simulation passes straight stairs down to 200 mm of depth, which leaves only a
  few millimetres in front and behind.
- **Step height.** 200 mm is the end of the rails' travel.
- **Balls as casters** roll well on wood and tiles, poorly on carpet.
- **A fall down a staircase** would destroy the robot and could hurt someone below. First tests on two
  steps, with a line to the sensor mast.
- From the drawings, not measured: depth of the servo's screw holes, diameter of the horn, the lidar's
  hole pattern (31 mm square assumed), the carrier boards of the sensors.
