Firmware simulation, Unity project, and sim-verified robot fixes
Simulation - sim/: the unchanged robot firmware compiled into hexapod_sim.dll against PC stand-ins (Arduino, Servo, Wire + register-level MPU6050, RF24 with matching-config radio), a kinematic body model (support plane + planted-foot odometry) that also drives the simulated IMU, and a headless smoke test (sim_smoke). build.ps1 builds and tests. - Hexapod_Simulation_Unity/ folded in (history kept in a bundle outside the repo). Assets/HexapodSim loads the DLL, drives the existing leg rig, and offers joystick / keyboard / robot-serial input plus a test panel. Robot (all found or confirmed in the simulation) - Config.h geometry taken from the Unity model. - IK femur elevation sign, gait stance direction, body pose rotation direction, yaw lever arm. - Stance feet integrated from the current command; gait restarts at mid-stance; heading integrates the applied turn rate, only while walking. - Leg clearance and reach checks (Limits::feetFeasible); walk command and body pose scaled as a whole, pose scale rate-limited, planted feet guarded so the body never snaps or legs collide. - Robot-gyro self-leveling as an integrator. - Heading mode: steering relative to the body; S walks backward. - Standing height from the remote (STANCE_HEIGHT_RANGE_MM). Protocol v3 (reflash both boards) - CmdPacket gains body_height (22 bytes). Remote - Height slider (Nextion hHeight/nHeight, serial [ ]). - Fixed unspecified I2C read order in RemoteIMU. LEGACY/: owner's old Nextion HMI and remote hardware assets. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
91dac16fca
commit
935526eab5
145 files changed
+431258
-114
No files matched your search
@@ -0,0 +1,120 @@
|
||||
# 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 4.0 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 |
|
||||
|---|---|
|
||||
| `Servo::writeMicroseconds()` | the pulse stored per pin, decoded back to angles with `Config.h`'s `SERVO_US_*` |
|
||||
| `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 repo root 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).
|
||||
- Servo calibration. The sim decodes pulses with `Config.h`'s single
|
||||
`SERVO_US_AT_0DEG` / `SERVO_US_PER_DEG`, i.e. what the firmware *intends*,
|
||||
not per-servo offsets or directions.
|
||||
- The remote firmware. `SimRemote.cs` mirrors its packet rules instead.
|
||||
Reference in new issue
Block a user