Fire control SOTM solver with drag compensation and confidence scoring#92
Fire control SOTM solver with drag compensation and confidence scoring#92dmeglan wants to merge 2 commits into
Conversation
…oring Replaces the inline fixed-point SOTM loop in RobotState with a proper Newton-Raphson solver based on Team 5962's open-source fire control system. Key improvements: - Drag-compensated drift: (1 - e^(-ct)) / c instead of linear v*t - Warm start from previous cycle's TOF for 2-3 iteration convergence - Latency compensation (vision pipeline + mechanism response) - 0-100 confidence scoring gates readyToShoot() - Newton-Raphson with analytical derivatives Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3arc7
left a comment
There was a problem hiding this comment.
Eager to see how this works; tuning might be tricky.
|
for simplicity please also use the |
|
|
||
|
|
||
| @dataclass | ||
| class FireControlResult: |
There was a problem hiding this comment.
if using wpistruct, this type can be logged directly. See vision subsystem for how to transform a dataclass into a pykit compatible logging structure
| # Fire control solver configuration | ||
| from util.firecontrol import FireControlConfig | ||
|
|
||
| kFireControlConfig = FireControlConfig( |
There was a problem hiding this comment.
these are a lot of parameters that the LogTunableNumber class can be useful for tuning. See drivewaypoint.py for example usage
| """ | ||
| return cls.flywheelAtSpeed and cls.turretAtAngle and cls.hoodAtAngle | ||
| mechanisms_ready = cls.flywheelAtSpeed and cls.turretAtAngle and cls.hoodAtAngle | ||
| return mechanisms_ready and cls.sotmConfidence >= kMinShootConfidence |
There was a problem hiding this comment.
a "bad" SOTM solve prevents shooting but has no existing indicator of why specifically a shot request was denied. Please revisit a way of on the fly debugging if the shot isn't "up to par"
Summary
Replaces the inline fixed-point SOTM iteration in
RobotState.periodic()with a proper Newton-Raphson fire control solver, based on Team 5962's open-source fire control system (Chief Delphi thread).Why This Change Is Needed
The current SOTM implementation has five significant gaps compared to the reference fire control system:
1. No drag compensation on horizontal ball travel
Current:
effectiveLocation = target - v * shotTime(linear)New: Uses exponential decay:
driftTOF = (1 - e^(-c*t)) / cAir resistance decays the ball's inherited horizontal velocity exponentially. At a drag coefficient of 0.24 and 0.8s flight time, the effective drift is ~0.70s instead of 0.80s — meaning the current code over-compensates by ~12% at longer distances. The ball doesn't drift as far as the linear model predicts because air resistance slows down its inherited sideways velocity during flight.
2. No latency compensation
Current: Uses the robot's instantaneous pose and velocity.
New: Predicts the robot pose forward by
vision_latency + mechanism_latency(~50ms) using first-order kinematics.At 3 m/s robot speed, 50ms of uncompensated latency = 15cm of position error. The robot has moved since the vision frame was captured, and the turret/hood/flywheel take time to respond to new setpoints. By predicting forward, the solver aims at where the robot will be when the mechanisms settle, not where it was when the camera saw the target.
3. No warm start
Current: Starts from raw distance each cycle, runs a fixed number of iterations.
New: Reuses previous cycle's TOF as initial guess for the Newton solver.
Since the robot's state changes smoothly between 20ms cycles, the previous TOF is almost always very close to the new solution. This allows convergence in 2-3 iterations instead of 5+, and prevents oscillation in edge cases where the fixed-point iteration can bounce between two values.
4. No confidence scoring
Current: Binary
readyToShoot()— either all mechanisms are at target, or not.New: 0-100 weighted geometric mean of four components:
One zero in any component kills the entire score. This prevents shooting during transient states (e.g., sudden direction changes, turret catching up, robot at extreme range).
The confidence threshold is configurable via
kMinShootConfidence(default 30).readyToShoot()now requiressotmConfidence >= kMinShootConfidencein addition to the existing mechanism checks.5. Fixed-point iteration vs Newton-Raphson
Current: Simple substitution loop — compute distance, look up TOF, shift target, repeat.
New: Newton's method with analytical derivatives:
Where
d'(t)includes the drag derivativee^(-ct)andg'(d)is the numerical derivative of the TOF lookup. Newton's method converges quadratically vs linearly for fixed-point iteration, meaning it needs far fewer iterations for the same precision.Architecture
Files Changed
src/util/firecontrol.pyFireControlSolver,FireControlConfig,FireControlResultsrc/constants/shooting.pykFireControlConfigandkMinShootConfidencesrc/robotstate.pyreadyToShoot()Drop-in Replacement
The solver populates the same
RobotState.effectiveObjectiveLocationandRobotState.effectiveObjectiveDistanceclass variables that the turret/shooting/hood commands already read. No command code changes needed. The existingtrackedTurretMoving,shootBallsMoving,feedBallsMoving, andangleHoodWithDistanceall work unchanged.FireControlConfigParametersLogging
The solver logs to AdvantageScope under
Robot/SOTM/:TOF— converged time of flight (seconds)Confidence— shot confidence (0-100)Iterations— Newton iterations used this cycleIsStatic— true if robot was below speed thresholdConverged— true if solver converged within toleranceTuning Guide
sotm_drag_coeff— Start at 0.24. Increase if shots land short of target when moving (ball drifts less than expected). Decrease or set to 0 if shots overshoot. This is the most impactful tuning parameter.kMinShootConfidence— Start at 30. Increase if the robot fires bad shots during transients. Decrease if the robot won't fire when it should. WatchRobot/SOTM/Confidencein AdvantageScope.vision_latency/mechanism_latency— Measure with AdvantageScope by comparing vision timestamp vs robot pose timestamp. Default 30ms + 20ms is conservative.min_sotm_speed— Below this speed, the solver skips SOTM entirely and uses direct distance. Default 0.1 m/s (essentially stationary).Reference
The solver algorithm is adapted from
ShotCalculator.javain the reference repo, translated to Python and integrated with our existingRobotStatearchitecture and interpolation maps.Test Plan
Robot/SOTM/Confidenceappears in AdvantageScopesotm_drag_coeffbased on shot accuracy at different speeds/distanceskMinShootConfidencethreshold based on match play experiencereadyToShoot()gates properly with confidence (robot shouldn't fire with low confidence)