Simulations

Run the firmware
without the robot

The first two simulators are direct ports of the committed control logic — the same if/else ladder, the same integer map(), the same axis indices. That makes them useful for more than illustration: the behaviour you see is the behaviour that was uploaded.

What is ported and what is modelled

Ported exactly: the drive decision ladder, Arduino's map() truncation, the PID class, the error terms, the pid() auto mixer and every PWM constant. Modelled: how PWM becomes metres per second, and how flywheel PWM becomes exit velocity. Those two constants are calibration sliders — nothing in the repository measures them.

Simulator 01

Drive mixer

Drag the stick. Each wheel shows the PWM the firmware would write and the direction bit that accompanies it; the branch name above the robot is the exact else if that matched. Try the rotation triggers at partial travel.

controlMotors() — Drive_1_for_new_controllers.ino

Triggers rest at +1.0 and travel to −1.0 when pressed.

branchStop
x = axes[0] × 1800
y = axes[1] × 1800
rotAnticlock0
rotclock0
M1·M2·M3·M40 · 0 · 0 · 0

Rotation is unreachable while translating

The two rotation branches sit below all eight translation branches. Any non-zero stick deflection — after the 0.1 deadzone — wins, so you cannot strafe and spin at once. For a holonomic base that is a real capability left on the table.

Straight moves only drive one pair

On a pure +x move the firmware writes M2 = M4 = 0 and leaves their direction pins untouched. The idle pair still contributes drag, which is part of why the robot creeps off a straight line over a long run.

Simulator 02

Vision alignment loop

Click anywhere on the court to drop the robot there and watch the loop close. The cyan cone is the D455's ~69° horizontal field of view; the green arc is the distance setpoint the controller is actually chasing.

realsense_basket_detector.py → pid() in Drive_with_auto.ino

statusADJUSTING
range
setpoint
horizontal_position
distance_error
value_x
value_y
What this simulator is really showing

Leave it on As committed and the robot will centre itself and then sit at the wrong range indefinitely. Two committed details cause that, and you can toggle each one:

  • The setpoint is cosine-corrected but the measurement is not. 5.726 m becomes 3.284 m on the setpoint side, while the cosine on the measured side is commented out (realsense_basket_detector.py:311).
  • The range branch never runs. pid() tests axes[3] only after axes[2] == 0 exactly (Drive_with_auto.ino:323), and a float PID output is essentially never exactly zero.

Switch to Corrected mapping to see the same gains converge cleanly.

Simulator 03

Shooter trajectory

The three PWM presets and the 55° launch angle come from the firmware. The conversion from PWM to ball speed does not exist anywhere in the repository, so it is exposed as a calibration constant — set it from one measured shot and the rest of the curve follows.

Ballistics from the committed presets

verdict
PWM written150
exit speed
time to rim plane
height at rim
needed for this shot

The trim has no ceiling

Buttons 11 and 12 add or subtract 10 PWM per press with no clamp (_shoot_with_auto.ino:424). Eleven presses on bot 1's top preset exceeds the 255 write limit and silently wraps the analogWrite argument. Any preset button resets the trim to zero.

Angle is open loop

The tilt motor runs while a button is held with no encoder, limit switch or feedback of any kind, so the 55° in the vision node is an assumption about where the mechanism happens to be — not a commanded state the software can verify.