ballistics.py and stereo.py from the AEGIS repo.
Hitting a moving target with a projectile that has flight time takes more than aiming at it. Recover range from a stereo pair, then solve a ballistic intercept, leading the target and holding over for gravity and drag so the dart and target meet.
Z = focal · baseline / disparity. Note how the range
uncertainty grows with the square of distance: stereo is sharp up close, vague far away.The same point lands at slightly different columns in the left and right cameras; that shift is the range. Nearer objects shift more, so range is inversely proportional to disparity.
How disparity → rangeBecause range ∝ 1/disparity, a fixed ±1 px matching error blows up with the square of distance. Stereo is crisp up close (±cm) and vague far off (±tens of cm).
Why error grows with distance²The dart has flight time, so aiming at a mover lands behind it. Push target-speed up and watch the lead angle grow: the solver aims where the target will be.
Lead = velocity × time-of-flightGravity drops the dart, so the launch aims above the target. Add drag and it bleeds speed mid-flight, shortening range and steepening the drop, so the hold-over grows.
What drag does