Conversation
…d flight time analysis Adds a complete shot tuning workflow: record shots via webcam with configurable frame rate (30/60/120 fps), connect to robot NT4 telemetry for live distance/RPM/hood angle, replay videos with frame-by-frame stepping (keyboard shortcuts: j/k, h/l, arrows, space), mark shooter-exit and target-hit timestamps to compute flight time, and export data points to the existing Shot Maps interpolation tables. Uses a raw NT4 WebSocket client (bypassing ntcore-ts-client which crashes on WPILib struct types) to read pose, actual shooter lead/follower velocities, and hood angle. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…' into 80-shot-tuning-mode
Auto-collapses on connect, shows connected address in status chip, and adds expand/collapse toggle. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…01/2026-Robot-Code into 80-shot-tuning-mode
- Shooter velocity: now reads setpoint RPM from TunableNumbers/CoordinationLayer/ShotTuning/shooterRPM - Hood angle: now reads setpoint degrees from TunableNumbers/CoordinationLayer/ShotTuning/hoodAngleDegrees - Distance: adds /AdvantageKit/RealOutputs/CoordinationLayer/distanceToHub as primary; pose-computed distance shown in parentheses for comparison - Export to shot map now uses NT distance (falls back to pose-computed), and passes RPM/degrees directly (no unit conversion needed) - Field renames: shooterRPMRadPerSec→shooterRPM, hoodAngleRadians→hoodAngleDegrees Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- RecordingControls: set selected camera ID on mount when restoring from localStorage (dropdown now reflects the remembered camera) - ShotMapsEditor: drain pending store BEFORE the robot API call so exported points are never lost when the robot is offline; handle null data in subscribe callback so live exports also appear without a robot connection - ShotMapsEditor: show exported points even when robot API fails (renders editor with error banner rather than showing only error+retry) - Added shotMapsStore singleton for cross-tab in-memory point sharing - VideoReplayPlayer: export uses store instead of direct file write; re-export button stays enabled (only disabled when flight time missing) - ShotMapTuning: snapshot telemetry at record-start, not store-time - TuningAttempt: rename fields to native units (RPM/degrees), add distanceToHubMeters and fps fields; update HUB_CENTER coordinates Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Export from the tuning tab now loads ShotMaps.json fresh, appends the point, and saves back immediately — no caching, safe against concurrent edits. A dirty flag (shotMapsLocalSignal) is set after each save so that the Shot Maps tab automatically reloads from local the next time it mounts, showing the exported point without any user action. Removes the broken module-level subscriber approach (failed because React StrictMode double-fired effects and the component unmounts on tab switch). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…' into 80-shot-tuning-mode
Loads robotToShooter.translation (x, y) from RobotInfo.json at startup and passes it to createNT4Service. The distance to hub is now measured from the shooter position rather than the robot center by rotating the offset into field frame using the robot's heading (3rd float64 in the Pose2d struct). Also adds RobotInfo.json to the Vite local-file allowlist. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Saves vertical space by placing NTConnectionStatus in a flex row alongside the "Shot Map Tuning" h5 instead of a standalone Paper block. The panel already collapses to a compact chip on connect. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rame buttons Chrome: Add HTTP range-request (206 Partial Content) support to the clip-serving middleware. Chrome requires byte-range responses to seek in video files; the previous 200 full-file response made the slider and frame-step buttons silently do nothing. Keyboard: Move keydown handler from window to the container's onKeyDown so it fires via event bubbling regardless of which child has focus. Clicking the video refocuses the container so shortcuts work immediately. Container is also auto-focused on mount and attempt change. Slider and button focus edge cases are handled to avoid double-actions. UI: Add -10 Frames and +10 Frames buttons flanking the -1/+1 Frame buttons. Tooltips updated to show keyboard shortcut hints. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
An 8px tall bar appears below the slider once either timestamp mark is set. It shows a muted base (MUI divider color, theme-aware) with: - Amber highlight spanning the leaves-shooter → hits-target window - Green 2px tick at the leaves-shooter position - Red 2px tick at the hits-target position Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Camera and FPS controls now share a single flex row instead of stacking. FPS ToggleButtonGroup replaced with a compact Select dropdown (80px wide). Actual-fps indicator stays to the right of the dropdowns. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
MUI Slider swallows all keydown events while it holds focus, even with onKeyDownCapture. The fix: use onChangeCommitted (fires on mouse-up / key-up) to return focus to the container div so h-j-k-l and arrow keys work again immediately after scrubbing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
s → Mark Leaves Shooter (start of flight) e → Mark Hit Target (end of flight) Moved markLeavesShooter/markHitTarget before handleKeyDown to fix initialization order, and wrapped them in useCallback. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…-Robot-Code into 80-shot-tuning-mode
…n layer Optimizations to reduce GC pressure on the roboRIO: - Pre-allocated arrays for odometry in ModuleIOTalonFX, GyroIOPigeon2, Drive, Module - Mutable measures (MutAngle, MutAngularVelocity) in Shooter, Hopper, Indexer, Turret, Hood, Intake subsystems - Primitive math replacing geometry object allocations in CoordinationLayer - New MutableMapBasedShotInfo and calculateShotFromMapInPlace() in ShotCalculations - Made EnhancedLine2d mutable with set() method Estimated ~50+ object allocations eliminated per cycle. Co-authored-by: Claude <noreply@anthropic.com>
|
I realize that none of these changes should have an effect on stuff changed in the original 80-shot-tuning branch. I can drop all of those commits and just leave the one commit if that would be helpful. |
godmar
left a comment
There was a problem hiding this comment.
I'm not sure whether we want all of these optimizations without first exhausting other sources of optimizations.
| modulePositions[moduleIndex].distanceMeters | ||
| - lastModulePositions[moduleIndex].distanceMeters, | ||
| modulePositions[moduleIndex].angle); | ||
| // Update moduleDeltas in-place to avoid allocation |
There was a problem hiding this comment.
Yuk. I'm not sure we're so desparate that want to drop all abstractions here.
If anything, we'd have a MutableSwerveModulePosition and an .mutate or .update function to put new values in.
| if (odometrySampleCount <= MAX_ODOMETRY_SAMPLES) { | ||
| // Use pre-allocated positions | ||
| for (int i = 0; i < odometrySampleCount; i++) { | ||
| double positionMeters = inputs.odometryDrivePositionsRad[i] * constants.WheelRadius; |
There was a problem hiding this comment.
see above, should be a mutable update
| .plus(JsonConstants.robotInfo.robotToShooter) | ||
| .getTranslation() | ||
| .toTranslation2d())); | ||
| Pose2d robotPose = drive.getPose(); |
There was a problem hiding this comment.
Should we microoptimize an in-shop test mode?
There was a problem hiding this comment.
Probably not worth it unless our cycle times are genuinely so bad we can't do shop testing.
| "CoordinationLayer/HoodPredictedLocation", | ||
| new Pose2d(movementEnd, robotPose.getRotation())); | ||
| EnhancedLine2d movementLine = new EnhancedLine2d(movementStart, movementEnd); | ||
| // Compute field centric speeds using primitive math instead of Translation2d.rotateBy() |
There was a problem hiding this comment.
Skeptical here too.
At best we'd decompose this after it's been identified as a hotspot/bottleneck.
Remove intermediate pre-allocated arrays in GyroIOPigeon2 and ModuleIOTalonFX. Now copy directly from queues to input arrays without the extra indirection. Addresses godmar's PR #86 review comments about unnecessary intermediate storage. Co-authored-by: Claude <noreply@anthropic.com>
Remove the in-place mutation of SwerveModulePosition fields. Reverts to creating new SwerveModulePosition objects for deltas each cycle, which is cleaner and maintains WPILib abstractions. Co-authored-by: Claude <noreply@anthropic.com>
Address remaining unresolved PR #86 comments: - Module.java: Remove pre-allocated odometry positions array, revert to simple loop that creates new SwerveModulePosition each cycle. Keep the cached loggerKey string optimization. - CoordinationLayer.java: Revert test mode distance calculation and shouldStowHoodBasedOnMovement() to use WPILib geometry classes instead of primitive math (not critical hot paths) - EnhancedLine2d.java: Restore immutability (remove set() method, make fields final again) - Update documentation to reflect current state of optimizations Co-authored-by: Claude <noreply@anthropic.com>
This PR is based off of our #80 branch because that was where we saw performance issues. The most recent commit contains all of the claude changes.
A next step is likely to take a hard look at our logging and make sure that we aren't logging more fields than we need to, since logging is a lot of overhead.