ABU Robocon 2025 · Basketball

A two-robot basketball
control stack.

Holonomic four-wheel drive, a depth-camera hoop detector, a PID alignment loop and a three-preset flywheel shooter — split across a ROS 2 host and four Arduino Mega boards, all talking over one deliberately simple serial line.

2 robots 4 Arduino boards ~7,100 lines ROS 2 Humble/Jazzy RealSense D455 YOLO last.pt
Bot 1 on court · ABU Robocon 2025 Annotated clips →
The loop

From joystick to flywheel in four hops

Every command — human or autonomous — takes the same path. That single choice is what lets the same firmware serve both manual driving and vision-guided alignment.

PS4 pad joy_node RealSense D455 colour + depth ROS 2 host detector + PID smart_drive_bridge Serial line 115200 baud "axes;buttons\n" Drive Mega 4 wheels Shoot Mega flywheel + servo /joy /value_x /value_y one line, 20 Hz
The whole system. The vision branch (orange) does not get its own protocol — it overwrites two axis slots in the same joystick packet the human would have sent.
Live

The vision alignment loop, running

This is not an illustration. It runs the committed PIDController, the same error terms the detector publishes, and the pid() mixer from the drive firmware — so it reproduces what the robot actually does, including what it gets wrong.

realsense_basket_detector.py → pid() in Drive_with_auto.ino

Click the court to drop the robot somewhere else. The cyan cone is the D455's field of view; the green arc is the setpoint it is chasing.

statusADJUSTING
range
setpoint
horizontal_position
distance_error
value_x
value_y
Full simulator, with gains →

Leave it on As committed and the robot never settles at the right range. Switch to Corrected mapping and the same gains converge — the difference is two lines in pid(). What's wrong and why →

Subsystems

Four pieces worth understanding

By the numbers

Tuned constants, as committed

Every value here is read straight out of the source — not a spec sheet. Where the two robots differ, both are listed.

180Drive PWM ceiling (of 255)
100Rotation PWM
60/40Auto translate / rotate PWM
5.726 mTarget shooting range
55°Camera / launch angle
0.5Kp, both axes
±0.5PID output clamp
30 HzDetection loop
The shooter presets are not the same on both robots

Bot 1 fires at PWM 100 / 120 / 150 from a 90° servo rest position; bot 2 at 50 / 80 / 120 from 100°. The pin maps differ too — see the pin tables.

Review

Twelve findings from reading it end to end

Reading all four firmware variants and six ROS nodes side by side surfaces real inconsistencies — a distance target that resolves to the wrong number, a PID that advances twice per frame, and two override buttons that latch on different indices.