Skip to content

Add shot tuning mode and improve shooter tuning slightly#82

Open
aidnem wants to merge 30 commits intomainfrom
80-shot-tuning-mode
Open

Add shot tuning mode and improve shooter tuning slightly#82
aidnem wants to merge 30 commits intomainfrom
80-shot-tuning-mode

Conversation

@aidnem
Copy link
Contributor

@aidnem aidnem commented Feb 28, 2026

No description provided.

@aidnem aidnem linked an issue Feb 28, 2026 that may be closed by this pull request
@aidnem aidnem changed the title 80 shot tuning mode Add shot tuning mode and improve shooter tuning slightly Feb 28, 2026
@aidnem aidnem requested a review from godmar February 28, 2026 03:32
godmar and others added 4 commits February 28, 2026 08:02
…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>
@godmar
Copy link
Contributor

godmar commented Feb 28, 2026

I think we accidentally collided on this branch. I didn't know you wanted to merge this.
I checked in what Claude gave me for the video tuning app.

BTW, what fps do you think we'll need for this?

PS: It looks like I get only 30fps on the webcam I own or that are builtin my laptop. I tried connecting my Pixel 9a via UVC, but that also only supports 30fps.

godmar and others added 2 commits February 28, 2026 09:52
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>
@godmar godmar removed their request for review February 28, 2026 15:08
@aidnem
Copy link
Contributor Author

aidnem commented Feb 28, 2026

I think we accidentally collided on this branch. I didn't know you wanted to merge this.
I checked in what Claude gave me for the video tuning app.

Sorry about that. We can keep this open until we try out the app at shop.

BTW, what fps do you think we'll need for this?

I'm not sure. I think 30 is probably good enough. The flight times are probably all going to be over 1 second anyway, so that's like 3.3% margin of error at the worst. Also, the ThriftyCams at shop are 60, so if we can get those to work it'll probably be even better.

const dx = poseX - HUB_CENTER.x;
const dy = poseY - HUB_CENTER.y;
onTelemetry({
distanceMeters: Math.sqrt(dx * dx + dy * dy),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@godmar The coordination layer logs a distance from the shooter to the hub whenever the robot is in test mode:

    if (DriverStation.isTest()) {
      // Log distance to hub for test modes
      drive.ifPresent(
          drive -> {
            Logger.recordOutput(
                "CoordinationLayer/distanceToHub",
                AllianceBasedFieldConstants.hubInnerCenterPoint()
                    .toTranslation2d()
                    .getDistance(new Pose3d(drive.getPose())
                        .plus(JsonConstants.robotInfo.robotToShooter).getTranslation().toTranslation2d()));
          });
    }

Could this just read that value from the network? that would save us from having to do the robot to shooter calculation in the app and also prevent the poses from getting out of sync with each other if the constants ever change.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The settings_ui rn outputs both (they should be identical). It uses the CoordinationLayer/distanceToHub value.

aidnem and others added 11 commits February 28, 2026 13:48
- 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>
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>
godmar and others added 5 commits February 28, 2026 21:06
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>
@godmar
Copy link
Contributor

godmar commented Mar 1, 2026

@aidnem check out the latest improvements. Chrome should now work, and the hot key should work, too.

They are

  • h - 10 frames back
  • j - 1 frame back
  • k - 1 frame forward
  • l - 10 frames forward
  • s - mark left time stamp when ball leaves shooter
  • e - mark right time stamp when target is hit

Remember that the "add" button will add to the saved .json file, which is not automatically loaded in the other tab (you have to "Load local" there).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add proper shot tuning mode

2 participants