Files
hexapod-robot/2026-current/sim/README.md
T
mangavalk dfd4d34512 Fold LEGACY into the generation folders
The LEGACY copies of HexapodRobot, Hexapod_NEW, Hexapod_Teensy and the old remote sketch were identical to the imported repos and are removed. The old Nextion design moves to 2019-teensy-nrf24/remote-nextion/, the 2019 remote case files to 2019-teensy-nrf24/remote-case/. Paths in CLAUDE.md, READMEs, remote/ comments, sim/build.ps1, the Unity DLL message and .vscode/settings.json now point to the new places. robot/ is not touched (its CLAUDE.md asks to check with the owner first).
2026-10-25 17:30:35 +01:00

5.1 KiB
Raw Blame History

Firmware simulation (software-in-the-loop)

This folder compiles the unchanged robot firmware (robot/*.cpp plus robot.ino) into a Windows DLL. The Unity project (Hexapod_Simulation_Unity/) runs that DLL, so the code you test in the simulation is exactly the code you flash to the Teensy. robot/ has no #ifdef SIM anywhere.

robot/ (unchanged) ──► PlatformIO + Teensy core ──► Teensy 3.6 firmware
                   └─► CMake + g++ + sim/shim/  ──► sim/build/hexapod_sim.dll ──► Unity

How it works

shim/ provides PC stand-ins for the only hardware the firmware touches:

Firmware uses Simulated as
analogWrite() hardware PWM (how ServoDriver drives the servos) the pulse width per pin, worked out from duty, resolution and frequency, then decoded back to angles through Config.h's per-servo SERVOS table
Wire + MPU6050 registers a register-level fake MPU6050 at 0x68, fed from the simulated body's tilt and rotation
RF24 a simulated radio: packets are received only if channel, address, data rate and payload size match, and the RX FIFO holds 3
millis() / micros() / Serial a simulated clock that Unity advances, and captured serial I/O

robot_ino.cpp compiles robot.ino itself and exposes read-only views of its globals (state machine, heading, IMU filter, gait phase) for status display. HexapodSimApi.h is the C API. Its forward kinematics is written separately from robot/Kinematics.cpp on purpose, so it can catch IK mistakes.

Build

Needs a 64-bit g++ and CMake. Strawberry Perl's C:\Strawberry\c\bin has g++, cmake and ninja, and the script falls back to it automatically. From the 2026-current folder in PowerShell:

.\sim\build.ps1             # configure (first time) + build + smoke test
.\sim\build.ps1 -NoTest     # build only
.\sim\build.ps1 -Clean      # rebuild from scratch

To run the steps by hand, use separate lines. Windows PowerShell 5.1 has no &&:

cmake -S sim -B sim\build -G Ninja
cmake --build sim\build
.\sim\build\sim_smoke.exe

Rebuild after any change in robot/ or shared/. In Unity, press Play (or Reload firmware in the panel) to pick up the new DLL. Unity copies the DLL before loading it, so it never locks the build output and you don't need to restart the editor.

Headless smoke test (tests/sim_smoke.cpp)

It drives the firmware the way the remote would and checks:

  • disarmed at power-on,
  • arm lands in SIT,
  • stand reaches STAND,
  • IK gives valid solutions and the feet end up at STANCE_HEIGHT,
  • FLAG_WALK leads to WALKING,
  • +vx moves the body forward,
  • link loss disarms,
  • a wrong-size packet is ignored,
  • the serial harness still works.

Using it in Unity

Open Hexapod_Simulation_Unity and press Play in Main.unity. No scene edits are needed: HexapodSimBootstrap adds a HexapodSimulation object, disables the old movement scripts (Walk, RotationControl, Leg, HandleHoystick), and binds the existing leg rig by name (Leg → hip1 / Hip2 / Knie). The on-screen panel (F1 toggles it) offers three input sources:

  • Joystick: the real remote as a USB controller, on input axes "1"–"6" like the old HandleHoystick. Axis assignment and inversion are set on the SimRemote component. The panel shows the raw axes so you can fix them.
  • Keyboard: test without a remote. WASD walks, Q/E turns, IJKL + U/O drive the right stick, 1–7 flip the toggles, Backspace disarms, +/- change speed.
  • Robot serial: no radio at all. Keystrokes go to robot.ino's own TEST_SERIAL_INPUT harness.

The panel also has every remote toggle, the speed slider, simulated handset tilt (remote gyro), a ground tilt slider (to test the robot gyro), and live firmware state, joint angles, foot contact, the packet on air and robot serial output.

The body moves kinematically, computed in the DLL (SimBody.cpp), so Unity shows what the smoke test checks:

  • The body rests on the support plane of its feet, the plane all feet are on or above.
  • Grounded feet don't slide.
  • The simulated MPU6050 reads that body's tilt and rotation rate.

The sphere at each foot (Point) is placed by the DLL's forward kinematics. If it doesn't sit on the tibia tip, the rig and Config.h disagree.

Setup that lives in the Inspector on HexapodSimulation:

  • forwardAxis: robot forward = Unity −X by default, taken from the old scene's invertForLeftLeg naming.
  • unitsPerMm: 0.1, since the model is in cm.
  • kneeRestDeg: −90, the rig's knee pose at rotation 0.

For a custom setup instead of the bootstrap, add a HexapodSimulation component to the scene yourself.

What is not simulated

  • Physics (mass, falling, slipping, servo torque and speed).
  • Whether the calibration matches the real servos. The sim decodes pulses through the same SERVOS table the firmware uses, so it shows what the firmware intends, including pulse-limit clamping (which is how it caught the old ±90° coxa offsets). Whether a real servo turns that way is a bench check.
  • The remote firmware. SimRemote.cs mirrors its packet rules instead.