From e7f0bfde49b55f3ad1c63e7c57a86fbc1622d22f Mon Sep 17 00:00:00 2001 From: project516 <138796702+Project516@users.noreply.github.com> Date: Thu, 6 Aug 2026 18:07:24 -0500 Subject: [PATCH 1/3] Tailor agent skills to Spectrum 3847; disable AdvantageKit skills Keep only relevant, Spectrum-specific agent skills. Rebrand donor references (Team 8044 IP/topics/AdvantageKit) to 3847 and our real stack: DogLog Telemetry topics, MapleSimSwerveDrivetrain, FuelPhysicsSim, PhotonVision, CTRE Phoenix 6. Disable advantagekit and advantagekit-replay by renaming SKILL.md to SKILL.md.disabled so all agents skip them. Document the policy in AGENTS.md. --- .../{SKILL.md => SKILL.md.disabled} | 0 .../scripts/pull_robot_wpilogs.py | 2 +- .../{SKILL.md => SKILL.md.disabled} | 0 .agents/skills/advantagescope/SKILL.md | 27 ++--- .../advantagescope/scripts/capture_layout.py | 8 +- .../advantagescope/scripts/export_preview.py | 26 ++--- .agents/skills/live-robot-telemetry/SKILL.md | 45 ++++---- .../scripts/list_live_nt_topics.py | 2 +- .../scripts/sample_live_nt.py | 4 +- .../scripts/snapshot_live_nt.py | 2 +- .agents/skills/maple-sim/SKILL.md | 100 ++++++------------ .agents/skills/wpilog-parser/SKILL.md | 4 +- AGENTS.md | 6 ++ 13 files changed, 96 insertions(+), 130 deletions(-) rename .agents/skills/advantagekit-replay/{SKILL.md => SKILL.md.disabled} (100%) rename .agents/skills/advantagekit/{SKILL.md => SKILL.md.disabled} (100%) diff --git a/.agents/skills/advantagekit-replay/SKILL.md b/.agents/skills/advantagekit-replay/SKILL.md.disabled similarity index 100% rename from .agents/skills/advantagekit-replay/SKILL.md rename to .agents/skills/advantagekit-replay/SKILL.md.disabled diff --git a/.agents/skills/advantagekit-replay/scripts/pull_robot_wpilogs.py b/.agents/skills/advantagekit-replay/scripts/pull_robot_wpilogs.py index 6c77cabe..82948f06 100644 --- a/.agents/skills/advantagekit-replay/scripts/pull_robot_wpilogs.py +++ b/.agents/skills/advantagekit-replay/scripts/pull_robot_wpilogs.py @@ -32,7 +32,7 @@ def newest_remote_log(user: str, host: str, directory: str) -> str: def main() -> None: """Main.""" parser = argparse.ArgumentParser() - parser.add_argument("--host", default="10.80.44.2", help="Robot IP") + parser.add_argument("--host", default="10.38.47.2", help="Robot IP") parser.add_argument("--user", default="admin", help="Robot SSH user") parser.add_argument("--remote-dir", default="/U", help="Robot log directory") parser.add_argument("--out", default="RobotLogs", help="Local output directory") diff --git a/.agents/skills/advantagekit/SKILL.md b/.agents/skills/advantagekit/SKILL.md.disabled similarity index 100% rename from .agents/skills/advantagekit/SKILL.md rename to .agents/skills/advantagekit/SKILL.md.disabled diff --git a/.agents/skills/advantagescope/SKILL.md b/.agents/skills/advantagescope/SKILL.md index 023eeafd..3bce883f 100644 --- a/.agents/skills/advantagescope/SKILL.md +++ b/.agents/skills/advantagescope/SKILL.md @@ -1,6 +1,6 @@ --- name: advantagescope -description: "Use for AdvantageScope visualization automation: building/running the Team 8044 AdvantageScope fork, opening WPILOGs with layouts, using opt-in agent control/export hooks, capturing 2D/3D field screenshots or frame sequences, and falling back to vanilla AdvantageScope/manual inspection when hooks are unavailable." +description: "Use for AdvantageScope visualization automation: building/running our AdvantageScope fork (Spectrum 3847) or vanilla AdvantageScope, opening WPILOGs/DataLogs with layouts, using opt-in agent control/export hooks, capturing 2D/3D field screenshots or frame sequences, and falling back to vanilla AdvantageScope/manual inspection when hooks are unavailable." metadata: short-description: Automate AdvantageScope visualization --- @@ -9,8 +9,8 @@ metadata: ## Core Rules -- This skill is the robot-repo consumer workflow for AdvantageScope visualization. It should help agents discover robot logs/assets, generate layouts, locate the Team 8044 fork, and export previews. -- Keep fork maintenance details in the Team 8044 AdvantageScope repo's `$advantagescope-fork` skill. Use that skill when modifying, rebasing, packaging, or debugging fork internals. +- This skill is the robot-repo consumer workflow for AdvantageScope visualization. It should help agents discover robot logs/assets, generate layouts, locate our AdvantageScope fork or vanilla AdvantageScope, and export previews. +- Keep fork maintenance details in the AdvantageScope repo's `$advantagescope-fork` skill (we maintain our own fork). Use that skill when modifying, rebasing, packaging, or debugging fork internals. - Do not hard-code season-specific field ids, robot model names, autos, or layouts. Discover custom assets from `AScope_Assets` and use explicit task arguments. - Do not automate by screen clicks or fixed coordinates. Use local agent control/export hooks when available. - If only vanilla AdvantageScope is available, open the log/layout manually and use WPILOG parsing for objective results. @@ -18,14 +18,7 @@ metadata: ## Build And Runtime -- Use the Team 8044 fork for agent exports: - ```sh - https://github.com/Team8044/AdvantageScope - ``` -- When changing the fork itself, switch to the fork checkout and use its repo-local `$advantagescope-fork` skill. -- Prefer an explicit `--fork ` argument or `ADVANTAGESCOPE_FORK=` when a checkout is already known. -- If no checkout is known, discover local git repos whose remotes include `Team8044/AdvantageScope`; common search roots include the current repo's parents and `~/Documents/GitHub`. -- If the fork is not available locally, ask the user before cloning/building it because that requires network, disk, and dependency changes. +- Prefer our AdvantageScope fork for agent exports. If the fork is not checked out locally, ask the user before cloning/building it because that requires network, disk, and dependency changes; otherwise fall back to vanilla AdvantageScope plus WPILOG summaries. - `export_preview.py` can also use `ADVANTAGESCOPE_EXECUTABLE` or `--advantagescope ` when a packaged/built fork executable is already available. - Do not copy robot assets into the fork. Custom robot assets should stay in this robot repo's `AScope_Assets` folder and be loaded through AdvantageScope's user assets feature. @@ -64,7 +57,7 @@ metadata: --agent-headless ``` - For auto previews, use a real-time export window anchored to the logged auto start instead of the start of the file. Prefer the first timestamp where `/DriverStation/Autonomous` and `/DriverStation/Enabled` are both true, then export `--start --end --fps 30`. -- Realtime export records the active 2D/3D field canvas while AdvantageScope playback runs at 1x. A current Team 8044 fork waits for selected-renderer readiness before recording, so 3D field assets should be loaded in frame 0 without a fixed delay. A preview should take roughly the requested video duration plus small startup/transcode overhead. +- Realtime export records the active 2D/3D field canvas while AdvantageScope playback runs at 1x. A current fork waits for selected-renderer readiness before recording, so 3D field assets should be loaded in frame 0 without a fixed delay. A preview should take roughly the requested video duration plus small startup/transcode overhead. - For agent exports, prefer `--agent-headless` instead of Chromium `--headless`. It keeps AdvantageScope windows hidden while preserving the normal renderer/WebGL lifecycle needed for 3D recording. - The skill includes helper scripts: ```sh @@ -93,7 +86,7 @@ metadata: --fps 30 ``` - Agent realtime export should produce `preview.webm` directly from the renderer. It should also produce `preview.mp4` when bundled FFmpeg conversion succeeds. -- Use `--agent-export-mode multiview` for synced hub + satellite realtime videos. The Team 8044 fork records the selected hub canvas and the first satellite canvas at the same time, then composes a side-by-side `preview.mp4` with bundled FFmpeg. +- Use `--agent-export-mode multiview` for synced hub + satellite realtime videos. The fork records the selected hub canvas and the first satellite canvas at the same time, then composes a side-by-side `preview.mp4` with bundled FFmpeg. - Use `--agent-export-mode frames` only for debugging deterministic frame stepping; normal auto previews must not use the frame-by-frame path. - Use `--agent-allow-frame-only` only with frame export debugging when no encoder is available. - Optional control mode: @@ -112,7 +105,7 @@ metadata: - Use Line Graph tab type `1` for static plotted data from WPILOGs. - A Line Graph controller state uses `leftSources`, `rightSources`, and `discreteSources`. Numeric source entries should use `type: "smooth"`, `logType: "Number"`, `visible: true`, and `options` with `color` and `size`. Discrete boolean overlays can use `type: "graph"` with `logType: "Boolean"`. -- Prefer `capture_layout.py` for graph screenshots. It launches the Team 8044 fork in `--agent-control --agent-headless`, waits for `liveStatus.ready=true`, optionally sends `setTime`, sends `capture`, and closes cleanly. +- Prefer `capture_layout.py` for graph screenshots. It launches the fork in `--agent-control --agent-headless`, waits for `liveStatus.ready=true`, optionally sends `setTime`, sends `capture`, and closes cleanly. - Pair graph screenshots with `$wpilib-sim` topic summaries from `read_wpilog_values.py` so users get both the visual trend and concrete min/max values. - Fast path for current-style graph requests: ```sh @@ -150,10 +143,10 @@ metadata: - Use `scripts/generate_multiview_3d_joysticks_layout.py` for 3D Field + Joysticks layouts. The helper can select the field tab or joystick tab with `--selected-tab field|joysticks` and can select a specific joystick layout for a port, for example `--joystick-port 0 --joystick-layout "Xbox Controller (White)"`. - For game pieces, add `--game-piece-topic ` and `--game-piece-variant `. For MapleSim 2026 fuel, use `/RealOutputs/FieldSimulation/Fuel` and variant `Fuel`. - For projectile or path overlays, add `--trajectory-topic `. For MapleSim fuel shots, use `/RealOutputs/FieldSimulation/FuelShotTrajectory`; the helper adds it as a 3D Field `trajectory` source with a bold orange line by default. -- For robot sources that include Z/pitch/roll, pass `--topic-type Pose3d` to `scripts/generate_field3d_layout.py`. For MapleSim bump traversal, use `/RealOutputs/FieldSimulation/RobotPose3d` with `--topic-type Pose3d`. +- For robot sources that include Z/pitch/roll, pass `--topic-type Pose3d` to `scripts/generate_field3d_layout.py`. For MapleSim bump traversal, use `Sim/RobotPose3d` (logged under `/Robot/` by DogLog) with `--topic-type Pose3d`. - Use explicit field and robot model arguments from the task or asset discovery. Do not bake season-specific asset ids into the skill or helper defaults. - Export with `export_preview.py --mode multiview --headless`. Expected outputs are `view-0-hub.webm`, `view-1-satellite.webm`, `preview.mp4`, and `manifest.json`. -- Joysticks multiview is supported by the Team 8044 fork's renderer-owned canvas capture path. Validate manifests report the joystick view with `sourceMode: "renderer-canvas"` and `sourceName: "JoysticksRenderer"`. +- Joystick multiview is supported by the fork's renderer-owned canvas capture path. Validate manifests report the joystick view with `sourceMode: "renderer-canvas"` and `sourceName: "JoysticksRenderer"`. - Fast path for a 3D teleop preview plus live Xbox joystick pane: ```sh python3 .agents/skills/advantagescope/scripts/generate_multiview_3d_joysticks_layout.py \ @@ -231,4 +224,4 @@ metadata: 2. Discover custom assets with `discover_ascope_assets.py`, generate a layout with explicit field/model arguments, and export with `export_preview.py`. 3. Check `manifest.json` for the requested mode, selected renderer readiness, no missing sources/assets, valid video output, and no main/renderer error. Multiview exports should include per-view webm files plus composed `preview.mp4`. 4. Confirm wall-clock export time is close to the requested video duration, then inspect frame 0 and a mid-run frame for nonblank output, expected field asset, and visible robot pose. If using an older fork without renderer readiness, use visual inspection fallback and only add a short explicit delay as a last resort. -5. If the fork code itself must change, move to the Team 8044 AdvantageScope checkout and use `$advantagescope-fork`. +5. If the fork code itself must change, move to the AdvantageScope checkout and use `$advantagescope-fork`. diff --git a/.agents/skills/advantagescope/scripts/capture_layout.py b/.agents/skills/advantagescope/scripts/capture_layout.py index 0502c6ba..4dc9e0da 100644 --- a/.agents/skills/advantagescope/scripts/capture_layout.py +++ b/.agents/skills/advantagescope/scripts/capture_layout.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -"""Capture an AdvantageScope layout screenshot with the Team 8044 agent fork.""" +"""Capture an AdvantageScope layout screenshot with the AdvantageScope fork.""" from __future__ import annotations @@ -80,14 +80,14 @@ def resolve_command(args: argparse.Namespace) -> tuple[list[str], Path | None]: """Resolve the AdvantageScope executable command from CLI arguments.""" fork = find_fork(args.fork) if args.fork and fork is None: - raise SystemExit(f"--fork is not a Team 8044 AdvantageScope checkout: {Path(args.fork).expanduser()}") + raise SystemExit(f"--fork is not an AdvantageScope checkout: {Path(args.fork).expanduser()}") if args.advantagescope: return find_advantagescope(args.advantagescope) if fork is not None: command = command_from_fork(fork) if command is None: raise SystemExit( - f"Found Team 8044 AdvantageScope fork at {fork}, but it is not built. " + f"Found AdvantageScope fork at {fork}, but it is not built. " "Run npm ci, npm run compile, npm run wasm:compile, and electron-builder build --dir." ) return command, fork @@ -98,7 +98,7 @@ def main() -> None: """Capture an AdvantageScope layout screenshot via the agent-control API.""" parser = argparse.ArgumentParser() parser.add_argument("--advantagescope", help="AdvantageScope executable path") - parser.add_argument("--fork", help="Team 8044 AdvantageScope fork checkout") + parser.add_argument("--fork", help="AdvantageScope fork checkout") parser.add_argument("--log", required=True, help="WPILOG path") parser.add_argument("--layout", required=True, help="AdvantageScope layout JSON path") parser.add_argument("--out", required=True, help="Output PNG path") diff --git a/.agents/skills/advantagescope/scripts/export_preview.py b/.agents/skills/advantagescope/scripts/export_preview.py index 7142a3ad..3e0891d6 100644 --- a/.agents/skills/advantagescope/scripts/export_preview.py +++ b/.agents/skills/advantagescope/scripts/export_preview.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -"""Export an AdvantageScope MP4 preview with the Team 8044 agent fork.""" +"""Export an AdvantageScope MP4 preview with a Spectrum AdvantageScope fork (or vanilla).""" from __future__ import annotations @@ -12,7 +12,7 @@ from pathlib import Path -FORK_REMOTE_MARKER = "Team8044/AdvantageScope" +FORK_REMOTE_MARKER = "Spectrum3847/AdvantageScope" def find_advantagescope(explicit: str | None) -> tuple[list[str], Path | None]: @@ -38,14 +38,14 @@ def find_advantagescope(explicit: str | None) -> tuple[list[str], Path | None]: return [path_executable], None raise SystemExit( - "Could not find the Team 8044 AdvantageScope fork.\n" + "Could not find the AdvantageScope fork.\n" "Pass --fork , set ADVANTAGESCOPE_FORK, pass --advantagescope , " - "or clone/build https://github.com/Team8044/AdvantageScope." + "or clone/build https://github.com/Spectrum3847/AdvantageScope." ) def find_fork(explicit: str | None) -> Path | None: - """Locate a Team 8044 AdvantageScope git fork checkout.""" + """Locate an AdvantageScope git fork checkout (preferring ours).""" candidates: list[Path] = [] if explicit: candidates.append(Path(explicit).expanduser()) @@ -69,13 +69,13 @@ def find_fork(explicit: str | None) -> Path | None: if path in seen or not (path / ".git").is_dir(): continue seen.add(path) - if is_team8044_fork(path): + if is_advantagescope_fork(path): return path return None -def is_team8044_fork(path: Path) -> bool: - """Check whether a git checkout is the Team 8044 AdvantageScope fork.""" +def is_advantagescope_fork(path: Path) -> bool: + """Check whether a git checkout is the AdvantageScope fork.""" try: result = subprocess.run( ["git", "remote", "-v"], @@ -91,7 +91,7 @@ def is_team8044_fork(path: Path) -> bool: def command_from_fork(fork: Path) -> list[str] | None: - """Build the electron command for a Team 8044 fork checkout, or None.""" + """Build the electron command for an AdvantageScope fork checkout, or None.""" electron = fork / "node_modules/.bin/electron" main = fork / "bundles/main.js" if electron.exists() and main.exists(): @@ -130,10 +130,10 @@ def resolve_assets_path(raw: str | None) -> Path | None: def main() -> None: - """Export an AdvantageScope MP4/MP4 preview with the Team 8044 agent fork.""" + """Export an AdvantageScope MP4/MP4 preview with the AdvantageScope fork.""" parser = argparse.ArgumentParser() parser.add_argument("--advantagescope", help="AdvantageScope executable path") - parser.add_argument("--fork", help="Team 8044 AdvantageScope fork checkout") + parser.add_argument("--fork", help="AdvantageScope fork checkout") parser.add_argument("--log", required=True, help="WPILOG path") parser.add_argument("--layout", required=True, help="AdvantageScope layout JSON path") parser.add_argument("--out", required=True, help="Output directory") @@ -147,7 +147,7 @@ def main() -> None: fork = find_fork(args.fork) if args.fork and fork is None: - raise SystemExit(f"--fork is not a Team 8044 AdvantageScope checkout: {Path(args.fork).expanduser()}") + raise SystemExit(f"--fork is not an AdvantageScope checkout: {Path(args.fork).expanduser()}") if args.advantagescope: command_prefix, command_cwd = find_advantagescope(args.advantagescope) elif fork is not None: @@ -155,7 +155,7 @@ def main() -> None: command_cwd = fork if command_prefix is None: raise SystemExit( - f"Found Team 8044 AdvantageScope fork at {fork}, but it is not built. " + f"Found AdvantageScope fork at {fork}, but it is not built. " "Run npm ci, npm run compile, npm run wasm:compile, and electron-builder build --dir." ) else: diff --git a/.agents/skills/live-robot-telemetry/SKILL.md b/.agents/skills/live-robot-telemetry/SKILL.md index 9f62ec6d..25052ab9 100644 --- a/.agents/skills/live-robot-telemetry/SKILL.md +++ b/.agents/skills/live-robot-telemetry/SKILL.md @@ -1,6 +1,6 @@ --- name: live-robot-telemetry -description: "Use for live real-robot practice telemetry: connecting read-only to NT4, watching odometry and AdvantageKit topics from an active robot, sampling bounded practice windows, and recommending optimizations from live robot data without commanding the robot." +description: "Use for live real-robot practice telemetry: connecting read-only to NT4, watching odometry and DogLog topics from an active robot, sampling bounded practice windows, and recommending optimizations from live robot data without commanding the robot." metadata: short-description: Analyze live robot NT4 telemetry --- @@ -14,51 +14,50 @@ metadata: - Treat live analysis as observation plus recommendations. If a change is needed, summarize the evidence, propose the code/tuning change, and validate it later with sim, WPILOG replay, or a separate user-approved disabled-robot tuning session. - Do not interfere with Driver Station, FMS, practice field control, or the drive team. If telemetry looks unsafe, tell the user to disable the robot; do not try to disable it over NT. - Prefer bounded capture windows. Avoid open-ended live monitors unless the user explicitly asks for one and the command has a clear timeout. -- Real robot logs are written by AdvantageKit to `/U` on the robot. Live data comes from `NT4Publisher`; analyze copied `*.wpilog` files with `$wpilog-decode` after retrieval. +- Real robot logs come from **DogLog** (via `frc.spectrumLib.telemetry.Telemetry`) and publish to NT4. Analyze copied `*.wpilog` files with `$wpilog-decode` after retrieval. ## Connection Workflow -1. Determine the robot IP from the user request or nearby context. Use `10.80.44.2` only when no stronger context exists. -2. Practice robots may use other team-number IPs, for example a practice team number like `9994`; ask or infer the exact IP before connecting if the target is unclear. +1. Determine the robot IP from the user request or nearby context. Use `10.38.47.2` only when no stronger context exists. +2. Practice robots may use other team-number IPs, for example a practice team number like `3847`; ask or infer the exact IP before connecting if the target is unclear. 3. Connect to NT4 on port `5810`. Do not use mDNS as the default path for this team workflow. 4. If the robot is off, rebooting, or changing batteries and NT4 does not respond, poll about once every 30 seconds until it reconnects or the agent is stopped. Avoid tight retry loops while the radio and roboRIO are coming back up. 5. After a reconnect or deploy, ignore the first 20-30 seconds of loop timing unless the user explicitly asks about boot performance; initialization spikes during that window are expected. 6. Start with topic discovery before sampling: ```sh python3 .agents/skills/live-robot-telemetry/scripts/list_live_nt_topics.py \ - --host 10.80.44.2 \ - --filter /AdvantageKit/RealOutputs/Swerve + --host 10.38.47.2 \ + --filter Swerve ``` 7. Take a quick status snapshot before a longer capture: ```sh python3 .agents/skills/live-robot-telemetry/scripts/snapshot_live_nt.py \ - --host 10.80.44.2 \ - --topic /AdvantageKit/RealOutputs/Swerve/Odometry/Robot \ - --topic /AdvantageKit/RealOutputs/Swerve/Actual_Velocity \ - --topic /AdvantageKit/DriverStation/Enabled + --host 10.38.47.2 \ + --topic Swerve/State/Pose \ + --topic Swerve/State/MeasuredStates \ + --topic /DriverStation/Enabled ``` 8. Capture a bounded practice window: ```sh python3 .agents/skills/live-robot-telemetry/scripts/sample_live_nt.py \ - --host 10.80.44.2 \ + --host 10.38.47.2 \ --duration 10 \ --period 0.1 \ - --topic /AdvantageKit/RealOutputs/LoggedRobot/FullCycleMS \ - --topic /AdvantageKit/RealOutputs/LoggedRobot/UserCodeMS \ - --topic /AdvantageKit/RealOutputs/LoopProfiler/Robot/CommandSchedulerMS \ - --topic /AdvantageKit/DriverStation/Enabled \ - --spike-topic /AdvantageKit/RealOutputs/LoggedRobot/FullCycleMS \ + --topic Swerve/CommandSchedulerMS \ + --topic /DriverStation/Enabled \ + --spike-topic Swerve/CommandSchedulerMS \ --spike-threshold 20 ``` ## Useful Topics -- Odometry and drive: `/AdvantageKit/RealOutputs/Swerve/Odometry/Robot`, `/AdvantageKit/RealOutputs/Swerve/Actual_Velocity`, `/AdvantageKit/RealOutputs/Swerve/SwerveStates/Rawgyro`, `/AdvantageKit/RealOutputs/Swerve/SwerveStates/Setpoints`, module inputs under `/AdvantageKit/Swerve/Module*`. -- DriverStation state: `/AdvantageKit/DriverStation/Enabled`, `/AdvantageKit/DriverStation/Autonomous`, `/AdvantageKit/DriverStation/Test`, `/AdvantageKit/DriverStation/AllianceStation`, `/AdvantageKit/DriverStation/Joystick0/AxisValues`, `/AdvantageKit/DriverStation/Joystick0/ButtonValues`. -- Loop timing: `/AdvantageKit/RealOutputs/LoggedRobot/FullCycleMS`, `/AdvantageKit/RealOutputs/LoggedRobot/UserCodeMS`, `/AdvantageKit/RealOutputs/LoggedRobot/LogPeriodicMS`, `/AdvantageKit/RealOutputs/Logger/*MS`, and `/AdvantageKit/RealOutputs/LoopProfiler/...MS` when profiling code is deployed. -- Vision: discover `/AdvantageKit/RealOutputs/Vision`, `/AdvantageKit/Vision`, Limelight tables, and accepted/rejected pose topics before assuming names. -- Superstructure: discover `/AdvantageKit/RealOutputs/SuperStructure`, `/AdvantageKit/RealOutputs/Shooter`, `/AdvantageKit/RealOutputs/Intake`, `/AdvantageKit/RealOutputs/Hopper`, `/AdvantageKit/RealOutputs/Turret`, `/AdvantageKit/RealOutputs/States`, and `/AdvantageKit/RealOutputs/DriverDash`. -- If topic names differ, prefer the discovered AdvantageKit names over adding duplicate robot outputs. +- Odometry and drive: `Swerve/State/Pose`, `Swerve/State/MeasuredStates`, `Swerve/State/MeasuredSpeeds`, `Swerve/State/TargetStates`, `Swerve/SystemState`, `Swerve/CurrentCommand`, and per-module states under `Swerve/Module*`. +- Motor currents: `Swerve/Currents/DriveStatorCurrent`, `Swerve/Currents/SteerStatorCurrent`, `Swerve/Currents/DriveSupplyCurrent`, `Swerve/Currents/SteerSupplyCurrent`. +- DriverStation state: `/DriverStation/Enabled`, `/DriverStation/Autonomous`, `/DriverStation/Test`, `/DriverStation/AllianceStation`, `/DriverStation/Joystick0/AxisValues`, `/DriverStation/Joystick0/ButtonValues`. +- Command scheduler: `Swerve/CurrentCommand`, `Commands` (init/end lifecycle), `Alerts`, `Sim/SimPose` (SIM pose), `Sim/RobotPose3d` (SIM bump-corrected pose). +- Vision: discover `Vision`, `VisionIOSim`, Limelight tables, and accepted/rejected pose topics before assuming names (team uses PhotonVision AprilTag pipelines). +- Superstructure: discover `Intake`, `Shooter`, `Turret`, `Indexer`, `Climb`, `Fuel`, `LED`, and `States` topics before assuming names. +- If topic names differ, prefer the discovered names from `list_live_nt_topics.py` over guessing. ## Analysis Workflow @@ -66,7 +65,7 @@ metadata: - For heading and gyro issues, compare odometry rotation, raw gyro, commanded heading, and DriverStation mode transitions. - For velocity tracking, compare requested path or driver behavior with actual velocity, setpoint topics, module states, and current/voltage topics when available. - For vision, compare accepted observations, camera names, tag counts, timestamps/latency, and pose jumps near observation updates. -- For this robot, do not remove or throttle the per-loop NT flush used to push Limelight robot pose and turret pose data unless the user explicitly approves a replacement. Accurate fast-motion vision depends on those camera inputs being flushed every loop. +- For this robot, do not remove or throttle the per-loop NT flush used to push Limelight robot pose and turret pose data unless the user explicitly approves a replacement. Accurate fast-motion vision depends on those camera inputs being flushed every loop (see vision subsystem in `src/main/java/frc/robot/subsystems/vision`). - For subsystem optimization, tie recommendations to captured evidence: command state, setpoint, measured response, current draw, voltage demand, and DriverStation mode. - When the user wants a visual artifact, capture or retrieve a WPILOG first, then use `$advantagescope` for layouts/exports. Live NT snapshots alone are for data summaries, not full AdvantageScope playback. diff --git a/.agents/skills/live-robot-telemetry/scripts/list_live_nt_topics.py b/.agents/skills/live-robot-telemetry/scripts/list_live_nt_topics.py index b96f3b36..9bd70b6e 100644 --- a/.agents/skills/live-robot-telemetry/scripts/list_live_nt_topics.py +++ b/.agents/skills/live-robot-telemetry/scripts/list_live_nt_topics.py @@ -92,7 +92,7 @@ def main() -> None: """List currently published topics from a live NT4 server.""" parser = argparse.ArgumentParser() - parser.add_argument("--host", default="10.80.44.2", help="Robot IP or hostname") + parser.add_argument("--host", default="10.38.47.2", help="Robot IP or hostname") parser.add_argument("--port", type=int, default=5810, help="NT4 port") parser.add_argument("--timeout", type=float, default=5.0, help="Connection timeout in seconds") parser.add_argument("--filter", default="", help="Only show topics containing this text") diff --git a/.agents/skills/live-robot-telemetry/scripts/sample_live_nt.py b/.agents/skills/live-robot-telemetry/scripts/sample_live_nt.py index b72b50d3..ae1daafb 100644 --- a/.agents/skills/live-robot-telemetry/scripts/sample_live_nt.py +++ b/.agents/skills/live-robot-telemetry/scripts/sample_live_nt.py @@ -274,7 +274,7 @@ def main() -> None: """Sample live NetworkTables data and detect spike anomalies.""" parser = argparse.ArgumentParser() - parser.add_argument("--host", default="10.80.44.2", help="Robot IP or hostname") + parser.add_argument("--host", default="10.38.47.2", help="Robot IP or hostname") parser.add_argument("--port", type=int, default=5810, help="NT4 port") parser.add_argument("--timeout", type=float, default=5.0, help="Connection timeout in seconds") parser.add_argument("--duration", type=float, default=5.0, help="Sampling duration in seconds") @@ -284,7 +284,7 @@ def main() -> None: parser.add_argument("--spike-threshold", type=float, default=0.0, help="Print raw samples where --spike-topic is at least this value") parser.add_argument("--wait-enabled", action="store_true", help="Wait to start the summary window until --enabled-topic is true") parser.add_argument("--until-disabled", action="store_true", help="Stop sampling after --enabled-topic goes false after being true") - parser.add_argument("--enabled-topic", default="/AdvantageKit/DriverStation/Enabled", help="Boolean DriverStation enabled topic") + parser.add_argument("--enabled-topic", default="/DriverStation/Enabled", help="Boolean DriverStation enabled topic") parser.add_argument("--json", action="store_true", help="Print JSON summary") args = parser.parse_args() diff --git a/.agents/skills/live-robot-telemetry/scripts/snapshot_live_nt.py b/.agents/skills/live-robot-telemetry/scripts/snapshot_live_nt.py index fa66f44c..8ff5717f 100644 --- a/.agents/skills/live-robot-telemetry/scripts/snapshot_live_nt.py +++ b/.agents/skills/live-robot-telemetry/scripts/snapshot_live_nt.py @@ -124,7 +124,7 @@ def main() -> None: """Read one timestamped snapshot of selected live NT4 topics.""" parser = argparse.ArgumentParser() - parser.add_argument("--host", default="10.80.44.2", help="Robot IP or hostname") + parser.add_argument("--host", default="10.38.47.2", help="Robot IP or hostname") parser.add_argument("--port", type=int, default=5810, help="NT4 port") parser.add_argument("--timeout", type=float, default=5.0, help="Connection timeout in seconds") parser.add_argument("--topic", action="append", required=True, help="Topic to read; repeatable") diff --git a/.agents/skills/maple-sim/SKILL.md b/.agents/skills/maple-sim/SKILL.md index 0d16ea5c..640000bf 100644 --- a/.agents/skills/maple-sim/SKILL.md +++ b/.agents/skills/maple-sim/SKILL.md @@ -1,6 +1,6 @@ --- name: maple-sim -description: "Use for Team 8044 MapleSim integration work: maintaining the swerve-first MapleSim simulation, verifying WPILib headless sim logs, calibrating physics constants, and extending simulation to intake, projectiles, opponents, or vision." +description: "Use for our Spectrum 3847 MapleSim integration work: maintaining the swerve-first MapleSim simulation, verifying WPILib headless sim logs, calibrating physics constants, and extending simulation to intake, projectiles, opponents, or vision." metadata: short-description: Maintain MapleSim simulation --- @@ -9,32 +9,24 @@ metadata: ## Core Rules -- Keep this skill updated whenever a future agent discovers a repeatable MapleSim workflow, command, API mismatch, or Team 8044-specific simulation convention. -- Preserve the existing AdvantageKit IO abstraction. Do not rewrite `Swerve`, `Module`, Choreo autos, or `SimAgentBridge` unless the task explicitly requires it. -- For drivetrain simulation, prefer MapleSim as the physics source while preserving the existing IO log surface. Team 8044 SIM swerve uses `ModuleIOMapleSim` and `GyroIOMapleSim` for MapleSim-specific physics/control, and keeps `ModuleIOSim` and `GyroIOSim` as the normal lightweight non-MapleSim sim path; do not reintroduce the Phoenix remote-CANcoder sim bridge unless the steering instability that caused azimuth wind/crawl has been solved. -- Check `MapleSimConstants.useMapleSim` before debugging SIM behavior. When true, SIM uses MapleSim arena/physics/collisions/fuel/projectiles. When false, SIM uses lightweight `DCMotorSim` module IO without creating/registering `SwerveDriveSimulation`, `SimulatedArena`, fuel simulation, projectiles, or shot-map verifier hooks. +- Keep this skill updated whenever a future agent discovers a repeatable MapleSim workflow, command, API mismatch, or Spectrum-2026-specific simulation convention. +- Preserve the existing spectrumLib abstraction. Do not rewrite `Swerve`, `SwerveModule`, PathPlanner autos, or `MapleSimSwerveDrivetrain` unless the task explicitly requires it. +- For drivetrain simulation, prefer MapleSim as the physics source while preserving the existing telemetry surface. Spectrum 3847 SIM swerve uses `frc.spectrumLib.swerve.MapleSimSwerveDrivetrain` on `CTRE` Phoenix TalonFX motors/controllers; keep the lightweight non-MapleSim `SimpleMotorFeedforward` path available and do not reintroduce the Phoenix remote-CANcoder sim bridge unless the steering instability that caused azimuth wind/crawl has been solved. +- Check the SIM gate before debugging: MapleSim is constructed and updated only in SIM mode (see `Swerve.startSimThread()` and `RobotSim`), gated by Phoenix `Utils.isSimulation()`. Real and replay modes never run MapleSim. Our robot has no `MapleSimConstants.useMapleSim`-style kill switch — MapleSim is always used in SIM. - Keep real and replay modes isolated from MapleSim. MapleSim belongs in `Constants.RobotMode.SIM`. - Record durable progress and verification notes in `.agents/maple-sim-implementation.md` when changing MapleSim behavior. ## Current Integration Shape +> Tailored for Spectrum 3847 (2026). Our swerve sim lives in `frc.spectrumLib.swerve.MapleSimSwerveDrivetrain`, driven from `Swerve` and `RobotSim` — we do not use the IO/`MapleSimConstants` split assumed by some other team code. Verify names in `src/main/java` before trusting external examples. + - Vendor dependency: `vendordeps/maple-sim.json`. -- SIM orchestration owner when `MapleSimConstants.useMapleSim` is true: `RobotContainer` creates `MapleSimRobotSimulation`, then wires `Swerve` IO from its exposed `SwerveDriveSimulation` and module simulations. Keep arena registration, MapleSim periodic updates, field pose/velocity logging, fuel simulation attachment, and SIM-only verifier hooks in the coordinator package, not in `RobotContainer`. -- SIM drivetrain owner when `MapleSimConstants.useMapleSim` is false: `RobotContainer` creates `Swerve` with `ModuleIOSim` and `GyroIOSim` so existing kinematic yaw fallback works. No MapleSim arena is created, registered, or advanced. -- MapleSim module IO shape: `ModuleIOMapleSim extends ModuleIOTalonFX`, feeds MapleSim state into Phoenix TalonFX/CANcoder sim states, calls `super.updateInputs(...)`, then patches fresh MapleSim physics/current/connection values into `ModuleIOInputs`. -- MapleSim reset coordination lives in `MapleSimRobotSimulation.resetPose(...)` plus registered pose-reset handlers. Do not put per-device reset calls inline in `RobotContainer`. -- MapleSim module IO should report drive position directly from `SwerveModuleSimulation`; MapleSim body pose teleports do not require drive-position offsets unless a future log proves otherwise. -- MapleSim gyro IO shape: `GyroIOMapleSim` receives `SwerveDriveSimulation` and pulls its matching MapleSim `GyroSimulation` internally. With `MapleSimConstants.enableGyroDrift = false` it reports near-driftless Pigeon2-style yaw from the simulated drivetrain pose plus a SIM reset offset; register `GyroIOMapleSim.syncToSimulationPoseReset(...)` with the MapleSim reset coordinator so known-good odometry reset code can stay unchanged. With the toggle true it reports MapleSim's drifted gyro reading. Normal `GyroIOSim` has no MapleSim imports and reports disconnected with a timestamp. -- MapleSim vision sim must register `VisionIOSim.syncToSimulationPoseReset(...)` with the MapleSim reset coordinator. This calls PhotonVision sim's `VisionSystemSim.resetRobotPose(...)` so camera latency history does not publish pre-reset pose observations after an artificial MapleSim teleport. -- Periodic update: `Robot.simulationPeriodic()` calls `RobotContainer.updateSimulation()`, which logs `/RealOutputs/Simulation/MapleSimEnabled` and delegates to `MapleSimRobotSimulation.update()` when present. The coordinator advances `SimulatedArena` and logs `/RealOutputs/FieldSimulation/RobotPosition` plus `/RealOutputs/FieldSimulation/RobotVelocity`. -- Fuel simulation owner when `MapleSimConstants.addGamePieces` is true: `MapleSimRobotSimulation.attachFuelSimulation(...)` constructs `MapleSimFuelSimulation` after `Swerve`, `Intake`, `Shooter`, `Hopper`, and `Turret` exist. `MapleSimFuelSimulation` places `Arena2026Rebuilt` fuel with `resetFieldForAuto()`, runs `IntakeSimulation.OverTheBumperIntake("Fuel", ...)`, launches `RebuiltFuelOnFly`, and logs `/RealOutputs/FieldSimulation/Fuel` as `Pose3d[]`. -- Shot-map verifier hook: `MapleSimFuelShotMapTestControl` owns `/SimAgent/ShotMapTest`, request IDs, pose resets, fuel injection, hood override, shooter/turret/hopper commands, and `ShotMapTest*` logs. `RobotContainer` should not import NetworkTables, timers, or shooter-map constants solely for this verifier. -- Pose reset: `Swerve.setPose(...)` invokes a simulation reset callback in SIM and a no-op callback elsewhere. -- MapleSim-specific configuration lives in `MapleSimConstants`, including the enable flags, initial pose, drivetrain config, physical TODO constants, and fuel tuning constants. -- 2026 arena setup: `MapleSimRobotSimulation` overrides the default MapleSim arena with `new Arena2026Rebuilt(MapleSimConstants.addRampColliders && !MapleSimConstants.enableBumpSimulation)`. With `enableBumpSimulation = true`, hard ramp colliders stay off and `MapleSimBumpSimulation` computes robot Z, pitch, and roll from a 2026 bump heightmap under the four swerve module contact points. MapleSim remains authoritative for planar X/Y/yaw motion; the bump helper must not correct X position, own velocity, or add slide-back behavior. -- 2026 fuel setup: `MapleSimConstants.addGamePieces = true` enables official MapleSim fuel placement and physics. This flag only matters when `MapleSimConstants.useMapleSim` is true. Team 8044 defaults to full-detail fuel staging with `MapleSimConstants.fuelUseEfficiencyMode = false`, so the neutral-zone grid uses MapleSim's `12 x 30 = 360` fuel layout for max-preload matches. `MapleSimConstants.fuelPreloadCount = 8` seeds the robot intake after the first field reset. If debugging pure drivetrain contacts, check these constants and remember fuel poses should be visible at `/RealOutputs/FieldSimulation/Fuel`. -- SIM start pose: use `MapleSimConstants.initialPose` for both `SwerveDriveSimulation` and `Swerve.setPose(...)`. If `/RealOutputs/FieldSimulation/RobotPosition` and `/RealOutputs/Swerve/Odometry/Robot` do not start aligned, AdvantageScope can make MapleSim walls/obstacles look like an offset invisible field. -- Current MapleSim scope includes swerve/arena plus 2026 fuel simulation. Fuel remains MapleSim-only and must be verified with explicit field fuel pose logging and AdvantageScope visualization. +- SIM drivetrain owner: `Swerve` constructs `MapleSimSwerveDrivetrain` (wrapping `SwerveDriveSimulation`) and calls `startSimThread()`, which runs `mapleSimSwerveDrivetrain.update()` (advances `SimulatedArena.simulationPeriodic()`, then injects the simulated pose/yaw into the CTRE TalonFX/CANcoder/`CANvirtual` Pigeon2 sim). +- Arena: `MapleSimSwerveDrivetrain` builds `new Arena2026Rebuilt(false)`, calls `arena.setEfficiencyMode(true)`, overrides `SimulatedArena` timings/instance with it, and registers the drivetrain simulation. It uses `COTS.ofPigeon2()` for the gyro and module constants clamped via `MapleSimSwerveDrivetrain.regulateModuleConstantsForSimulation(...)`. +- Bump / pitch-roll: `Swerve.periodic()` (SIM only) computes `Sim/RobotPose3d` through `frc.rebuilt.RobotBumpSim`; on a ramp it overrides MapleSim with `setSimulationWorldPose`. MapleSim stays authoritative for planar X/Y/yaw. +- Fuel: simulated by `frc.rebuilt.FuelPhysicsSim` under namespace `Sim/Fuel` (not MapleSim-native game pieces). Drivetrain contacts still use the MapleSim arena. +- Telemetry/log topics come from `frc.spectrumLib.telemetry.Telemetry` (DogLog), e.g. `Sim/SimPose`, `Sim/RobotPose3d`, `Swerve/State/Pose`, `Swerve/SystemState`. Real delay logs are saved as `.wpilog`. +- SIM-only code stays gated behind `Utils.isSimulation()`. MapleSim never runs in real or replay modes. ## Known Version Note @@ -83,60 +75,34 @@ metadata: --repo . \ --distances "1.75,3.25,5.0" ``` -- Check MapleSim and swerve topics: +- Check MapleSim, swerve, and fuel topics (DogLog keys as published by `frc.spectrumLib.telemetry.Telemetry`, which DogLog prefixes under `/Robot/`): ```sh python3 .agents/skills/wpilog-decode/scripts/read_wpilog_values.py \ --repo . \ --log \ - --topic /RealOutputs/Swerve/TeleopController/vxMPS \ - --topic /RealOutputs/Swerve/Odometry/Robot \ - --topic /RealOutputs/FieldSimulation/RobotPosition \ - --topic /RealOutputs/FieldSimulation/RobotVelocity \ - --topic /RealOutputs/FieldSimulation/Fuel \ - --topic /RealOutputs/Simulation/Fuel/InRobotCount \ - --topic /RealOutputs/Simulation/Fuel/IntakeRunning \ - --topic /RealOutputs/Simulation/Fuel/ShotsLaunched \ - --topic /RealOutputs/Simulation/Fuel/ShooterForwardTiltFromVerticalDeg \ - --topic /RealOutputs/Simulation/Fuel/ShooterLaunchPitchDeg \ - --topic /RealOutputs/Simulation/Fuel/ShotLaunchSpeedMetersPerSecond \ - --topic /RealOutputs/Simulation/Fuel/ShotExpectedTimeOfFlightSeconds \ - --topic /RealOutputs/Simulation/Fuel/ShotTargetDistanceMeters \ - --topic /RealOutputs/Simulation/Fuel/ReturnedFuelCount \ - --topic /RealOutputs/Simulation/Fuel/LastReturnPose \ - --topic /RealOutputs/Simulation/Fuel/LastReturnVelocityMPS \ - --topic /Swerve/Module0/DriveVelocityRadPerSec \ - --topic /Swerve/Module0/DriveAppliedVolts \ - --topic /Swerve/Module0/DriveSupplyCurrentAmps \ - --topic /DriverStation/Joystick0/AxisValues \ - --topic /DriverStation/Joystick0/Xbox \ - --topic /Swerve/Gyro/Connected \ - --topic /Swerve/Gyro/YawVelocityRadPerSec + --topic /Robot/Sim/SimPose \ + --topic /Robot/Sim/RobotPose3d \ + --topic /Robot/Swerve/State/Pose \ + --topic /Robot/Swerve/SystemState \ + --topic /Robot/Sim/Fuel/Positions \ + --topic /Robot/Sim/Fuel/BlueScore \ + --topic /Robot/Sim/Fuel/RedScore \ + --topic /Robot/Sim/Fuel/Stats/BallCount ``` ## Expected Healthy Signals -- Auto chooser selection succeeds through `SimAgentBridge`. -- `/RealOutputs/Simulation/MapleSimEnabled` should match `MapleSimConstants.useMapleSim`. -- `/RealOutputs/Swerve/Odometry/Robot` and `/RealOutputs/FieldSimulation/RobotPosition` both move during auto. -- `/RealOutputs/Swerve/Odometry/Robot` and `/RealOutputs/FieldSimulation/RobotPosition` must start at the same SIM initial pose. Use `/RealOutputs/FieldSimulation/RobotPosition` as the source of truth for MapleSim collision debugging. -- For bump visualization, use `/RealOutputs/FieldSimulation/RobotPose3d` as the AdvantageScope 3D Field robot source with log type `Pose3d`. Check `/RealOutputs/Simulation/Bump/OnBump`, `/RealOutputs/Simulation/Bump/ModuleHeights`, `/RealOutputs/Simulation/Bump/RobotRollRad`, `/RealOutputs/Simulation/Bump/RobotPitchRad`, and `/RealOutputs/Simulation/Bump/MaxModuleHeight` when tuning the contact heightmap. -- Module drive velocity, applied volts, and current are nonzero during commanded movement. -- `/Swerve/Gyro/Connected` is true in SIM. -- For full-forward teleop or each side of the rectangle, `/RealOutputs/Swerve/TeleopController/vxMPS` or `/RealOutputs/Swerve/TeleopController/vyMPS` should equal `SwerveConstants.speedAt12Volts`; `/RealOutputs/FieldSimulation/RobotVelocity` should move toward the physically achievable speed for the current mass, gearing, wheel radius, friction, and battery model. -- Odometry and MapleSim field pose should be aligned in open-field driving. After hard contact with fixed MapleSim walls/obstacles, wheel odometry may continue integrating slip while the MapleSim body is stopped; this is expected, and collision debugging should use `FieldSimulation/RobotPosition`. -- With `MapleSimConstants.useMapleSim = false`, `FieldSimulation/*` and fuel/projectile/verifier behavior are intentionally absent; use `/RealOutputs/Swerve/Odometry/Robot` and `/RealOutputs/Swerve/Actual_Velocity` for fast path/auto checks. -- With `MapleSimConstants.addGamePieces = true`, `/RealOutputs/FieldSimulation/Fuel` should be a `Pose3d[]` that AdvantageScope can render as 3D Field game pieces with variant `Fuel`. -- During fuel intake tests, `/RealOutputs/Simulation/Fuel/InRobotCount` should increase and `/RealOutputs/Simulation/Fuel/IntakeRunning` should become true when the intake is extended and rollers run forward. -- During fuel shooting tests, `/RealOutputs/Simulation/Fuel/ShotsLaunched` should increase and fuel projectile poses should appear in `/RealOutputs/FieldSimulation/Fuel`. -- Scored fuel keeps MapleSim's normal behavior: `RebuiltFuelOnFly` disappears when `hasHitTarget()` becomes true. Team 8044 only adds a delayed rear return, incrementing `/RealOutputs/Simulation/Fuel/ReturnedFuelCount` when physical `RebuiltFuelOnField` fuel respawns behind the hub with velocity toward field center. -- Fuel projectile pitch uses a frame conversion: MapleSim expects pitch up from horizontal, while the Team 8044 hood encoder reports `0 deg` at the rear hardstop, which is `12 deg` forward from vertical in the real robot. Expected formula: `launchPitch = 90 deg - (12 deg + hoodEncoderAngle)`, so encoder `0 deg` logs about `78 deg` launch pitch. -- Fuel launch speed is calibrated against the real shooter map using one global `MapleSimConstants.fuelShooterLaunchSpeedScale`; the current tuned value is `0.35`. Use `run_shot_map_sim.py` and the `/RealOutputs/Simulation/Fuel/Shot*` topics when changing this scale. -- The shot-map verifier intentionally uses `/SimAgent/ShotMapTest` to set a commanded hood-angle override inside `MapleSimFuelSimulation`; normal MapleSim fuel shots use measured hood position unless that verifier hook is enabled. The verifier's default enabled window is long enough for scored-fuel return to complete. +- Auto chooser selection succeeds (Elastic / NT auto chooser to a registered PathPlanner auto), and the sim logs the WPILOG. +- Auto chooser selection succeeds (Elastic → PathPlanner named auto). +- `Sim/SimPose` (Pose2d) and `Sim/RobotPose3d` (Pose3d) both move during auto/teleop; `Sim/RobotPose3d` is the AdvantageScope 3D Field robot source (log type `Pose3d`). +- `Swerve/State/Pose` (odometry) tracks `Sim/SimPose` in open-field driving; after hard contact with fixed MapleSim walls/obstacles, odometry may keep integrating slip while the MapleSim body stops — collision debugging should use `Sim/RobotPose3d`. +- `Swerve/SystemState` toggles correctly and `Swerve/CurrentCommand` shows the active command. +- `Swerve/Currents/DriveStatorCurrent` and `Swerve/Currents/SteerStatorCurrent` are nonzero during commanded movement. +- Fuel (`frc.rebuilt.FuelPhysicsSim`, root `Sim/Fuel`): `Sim/Fuel/Stats/BallCount` and `ActiveBalls` reflect active pieces; scored fuel increments `Sim/Fuel/BlueScore`/`RedScore`; in-flight projectiles appear in `Sim/Fuel/InFlight`/`Positions`. +- Note: `FuelPhysicsSim` is authoritative for fuel (drag/gravity/Magnus, intake, launches via `ShotCalculator`), independent of the MapleSim drivetrain; do not expect MapleSim-native fuel topics. ## Follow-Up Areas -- Calibrate TODO MapleSim physics constants in `MapleSimConstants`. -- Tune MapleSim fuel TODO constants in `MapleSimConstants` from CAD/testing: intake width/extension, shooter exit pose, shooter wheel radius, launch speed scale, encoder-zero forward tilt, `fuelShotsPerSecond`, and post-score wall/floor/restitution values. -- Decide whether to suppress SIM-only Phoenix stale fault warnings for fault status signals. -- Add high-frequency odometry arrays only if needed. -- Extend to opponent robots and vision simulation in separate deliberate passes. +- Calibrate MapleSim physical constants from CAD/testing as needed. +- Verify SIM Phoenix stale-fault warnings are suppressed the same way real-mode faults are. +- Add high-frequency odometry or opponent/vision simulation only if needed. diff --git a/.agents/skills/wpilog-parser/SKILL.md b/.agents/skills/wpilog-parser/SKILL.md index 60eb1069..629808b6 100644 --- a/.agents/skills/wpilog-parser/SKILL.md +++ b/.agents/skills/wpilog-parser/SKILL.md @@ -6,7 +6,9 @@ license: MIT # wpilog-parser -WPILOG is the binary log format used by logging libraries in the FRC ecosystem. The wpilog-parser library makes it easy to read and analyze the log files using TS/JS. +WPILOG is the standard format used by FRC loggers — the 2026-Spectrum robot logs via **DogLog** (`frc.spectrumLib.telemetry.Telemetry extends DogLog`), so robots publish topics like `Swerve/State/Pose`, `Swerve/SystemState`, `Sim/RobotPose3d`, `Sim/Fuel`. The wpilog-parser library makes it easy to read and analyze the log files using TS/JS. + +Upstream repo: . Logs saved as `.wpilog` (see `simulation/` and `robot/` output dirs). ## Creating a project diff --git a/AGENTS.md b/AGENTS.md index 8b458c28..970dabf6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -31,6 +31,12 @@ Swerve drive with fuel launcher, turret, indexer, intake, vision, LEDs, and clim - **Telemetry**: DogLog via `frc.spectrumLib.Telemetry`; `TuneValue` for live tuning. - **Gamepads**: `Pilot.java` / `Operator.java`; bindings in `PilotStates.java` / `OperatorStates.java`. +## Skills Policy + +`./.agents/skills/` holds agent skills for this team. Keep them tailored to **Spectrum 3847** (team 3847, IP `10.38.47.2`) and to our actual stack: DogLog (via `frc.spectrumLib.telemetry.Telemetry`), MapleSim (`MapleSimSwerveDrivetrain`), `FuelPhysicsSim`, PhotonVision, PathPlanner, CTRE Phoenix 6. We do **not** use AdvantageKit, so: +- New skills must describe our real classes/topics, never generic donor code. Verify names against `src/main/java` and `docs/`. +- To keep a skill from loading across all agents (opencode, Claude Code, etc.), rename its `SKILL.md` → `SKILL.md.disabled` instead of editing frontmatter. Leave the directory's other files in place. + ## Important Notes 1. Run `./gradlew build` after any Java change — it auto-formats and runs SpotBugs/tests. Re-run if it fails on formatting. From 4e8928c63b7175ce49794910a8e99a1105b4bb2c Mon Sep 17 00:00:00 2001 From: Aaron <114454982+A2A1x@users.noreply.github.com> Date: Thu, 6 Aug 2026 20:35:54 -0500 Subject: [PATCH 2/3] ran pass with Opus 4.8 and added md formatting --- .../advantagekit/references/common-issues.md | 18 +- .../advantagekit/references/output-logging.md | 20 +- .../references/recording-inputs.md | 14 +- .agents/skills/advantagescope/SKILL.md | 24 ++- .agents/skills/coderabbitai-review/SKILL.md | 15 +- .agents/skills/frc-code-review/SKILL.md | 11 +- .agents/skills/frc-vision/SKILL.md | 42 ++-- .agents/skills/live-robot-telemetry/SKILL.md | 14 +- .agents/skills/maple-sim/SKILL.md | 14 +- .agents/skills/wpilib-best-practices/SKILL.md | 21 +- .../references/command-based.md | 40 ++-- .../references/command-compositions.md | 32 +-- .../references/command-scheduler.md | 20 +- .agents/skills/wpilib-sim/SKILL.md | 194 ++++++++---------- .agents/skills/wpilog-decode/SKILL.md | 73 ++++--- .agents/skills/wpilog-parser/SKILL.md | 7 +- WPILib-License.md | 16 +- build.gradle | 13 +- docs/dependencies/overview.md | 14 +- docs/frc-software-basics/logic-operators.md | 16 +- .../variables-arithmetic.md | 28 +-- docs/other-guides/2026-season-specific.md | 42 ++-- docs/other-guides/shortcuts.md | 56 ++--- docs/tools/auton.md | 12 +- docs/tools/gradle.md | 22 +- docs/tools/leds.md | 26 +-- docs/tools/pid-tuning.md | 4 +- docs/tools/simulation.md | 8 +- docs/tools/vision.md | 24 +-- src/main/java/frc/spectrumLib/README.md | 102 ++++----- 30 files changed, 495 insertions(+), 447 deletions(-) diff --git a/.agents/skills/advantagekit/references/common-issues.md b/.agents/skills/advantagekit/references/common-issues.md index 392e1c45..d1cc6edf 100644 --- a/.agents/skills/advantagekit/references/common-issues.md +++ b/.agents/skills/advantagekit/references/common-issues.md @@ -6,15 +6,15 @@ Replay works by re-running identical code with identical logged inputs. Any data ### Problem Sources -| Source | Problem | Fix | -| ------ | ------- | --- | -| `Timer.getFPGATimestamp()` | Raw FPGA time — not deterministic | Use `Timer.getTimestamp()` | -| NetworkTables / dashboard inputs | Values change outside the logging cycle | Log as inputs through IO layer | -| YAGSL, Phoenix 6 swerve libraries | Bypass IO abstraction, call hardware directly | Use AKit's swerve template instead | -| `Math.random()` / random number generators | Non-deterministic by nature | Log seed or generated values as inputs | -| Iterating over `HashMap` / unordered collections | Iteration order varies across JVM runs | Use `LinkedHashMap` or sorted collections | -| Filesystem reads | File contents may change | Log file data as inputs | -| Driver Station data accessed before `Logger.start()` | Not yet deterministic | Defer all DS access until after `Logger.start()` | +| Source | Problem | Fix | +|------------------------------------------------------|-----------------------------------------------|--------------------------------------------------| +| `Timer.getFPGATimestamp()` | Raw FPGA time — not deterministic | Use `Timer.getTimestamp()` | +| NetworkTables / dashboard inputs | Values change outside the logging cycle | Log as inputs through IO layer | +| YAGSL, Phoenix 6 swerve libraries | Bypass IO abstraction, call hardware directly | Use AKit's swerve template instead | +| `Math.random()` / random number generators | Non-deterministic by nature | Log seed or generated values as inputs | +| Iterating over `HashMap` / unordered collections | Iteration order varies across JVM runs | Use `LinkedHashMap` or sorted collections | +| Filesystem reads | File contents may change | Log file data as inputs | +| Driver Station data accessed before `Logger.start()` | Not yet deterministic | Defer all DS access until after `Logger.start()` | --- diff --git a/.agents/skills/advantagekit/references/output-logging.md b/.agents/skills/advantagekit/references/output-logging.md index d5185bd3..f0ac687f 100644 --- a/.agents/skills/advantagekit/references/output-logging.md +++ b/.agents/skills/advantagekit/references/output-logging.md @@ -50,16 +50,16 @@ This guarantees the same logic that ran on the robot is used for replay, so odom All types support single values, 1D arrays, and 2D arrays unless noted. -| Category | Types | Notes | -| ---------- | ------- | ------- | -| Primitives | `boolean`, `int`, `long`, `float`, `double`, `String` | — | -| WPILib structs | `Translation2d/3d`, `Pose2d/3d`, `Rotation2d/3d`, `SwerveModuleState`, etc. | Preferred over protobuf — no delay | -| Protobuf | Any WPILib protobuf type | **⚠️ First log can take >100ms** — log once while disabled | -| Records | Custom `record` classes (fields: primitives, enums, structs, nested records) | **⚠️ Same first-log delay as protobuf** — log while disabled; no array fields | -| Enums | Any enum | Logged as `name()` string | -| Colors | WPILib `Color` | Logged as hex triplet string | -| Mechanisms | `LoggedMechanism2d` | Output only | -| Suppliers | `BooleanSupplier`, `IntSupplier`, `LongSupplier`, `DoubleSupplier` | Output only | +| Category | Types | Notes | +|----------------|------------------------------------------------------------------------------|-------------------------------------------------------------------------------| +| Primitives | `boolean`, `int`, `long`, `float`, `double`, `String` | — | +| WPILib structs | `Translation2d/3d`, `Pose2d/3d`, `Rotation2d/3d`, `SwerveModuleState`, etc. | Preferred over protobuf — no delay | +| Protobuf | Any WPILib protobuf type | **⚠️ First log can take >100ms** — log once while disabled | +| Records | Custom `record` classes (fields: primitives, enums, structs, nested records) | **⚠️ Same first-log delay as protobuf** — log while disabled; no array fields | +| Enums | Any enum | Logged as `name()` string | +| Colors | WPILib `Color` | Logged as hex triplet string | +| Mechanisms | `LoggedMechanism2d` | Output only | +| Suppliers | `BooleanSupplier`, `IntSupplier`, `LongSupplier`, `DoubleSupplier` | Output only | **Protobuf / Record first-use pattern** — call once during `disabledInit()` to absorb the delay: diff --git a/.agents/skills/advantagekit/references/recording-inputs.md b/.agents/skills/advantagekit/references/recording-inputs.md index 0c1d87cd..240b11bb 100644 --- a/.agents/skills/advantagekit/references/recording-inputs.md +++ b/.agents/skills/advantagekit/references/recording-inputs.md @@ -45,12 +45,14 @@ All [supported types](https://docs.advantagekit.org/data-flow/supported-types) a Two approaches — pick one consistently: **Naming convention** (simpler): + ```java public double velocityRadPerSec = 0.0; public double positionMeters = 0.0; ``` **Measure objects** (type-safe): + ```java public Distance position = Meters.of(0.0); public LinearVelocity velocity = MetersPerSecond.of(0.0); @@ -88,12 +90,12 @@ Direct NetworkTables access (`SmartDashboard.getNumber()`, `SmartDashboard.getSt ### Logged Replacements -| Instead of | Use | -|-----------|-----| -| `SendableChooser` | `LoggedDashboardChooser` | -| `SmartDashboard.getNumber()` | `LoggedNetworkNumber` | -| `SmartDashboard.getString()` | `LoggedNetworkString` | -| `SmartDashboard.getBoolean()` | `LoggedNetworkBoolean` | +| Instead of | Use | +|-------------------------------|-----------------------------| +| `SendableChooser` | `LoggedDashboardChooser` | +| `SmartDashboard.getNumber()` | `LoggedNetworkNumber` | +| `SmartDashboard.getString()` | `LoggedNetworkString` | +| `SmartDashboard.getBoolean()` | `LoggedNetworkBoolean` | ### Auto Chooser Example diff --git a/.agents/skills/advantagescope/SKILL.md b/.agents/skills/advantagescope/SKILL.md index 3bce883f..8f82eca7 100644 --- a/.agents/skills/advantagescope/SKILL.md +++ b/.agents/skills/advantagescope/SKILL.md @@ -1,9 +1,10 @@ --- + name: advantagescope description: "Use for AdvantageScope visualization automation: building/running our AdvantageScope fork (Spectrum 3847) or vanilla AdvantageScope, opening WPILOGs/DataLogs with layouts, using opt-in agent control/export hooks, capturing 2D/3D field screenshots or frame sequences, and falling back to vanilla AdvantageScope/manual inspection when hooks are unavailable." metadata: - short-description: Automate AdvantageScope visualization ---- +short-description: Automate AdvantageScope visualization +-------------------------------------------------------- # AdvantageScope @@ -25,6 +26,7 @@ metadata: ## Agent Hooks - Before exporting an auto preview, get the WPILOG from `$wpilib-sim`'s permanent workflow: + ```sh python3 .agents/skills/wpilib-sim/scripts/run_auto_sim.py \ --repo . \ @@ -33,7 +35,9 @@ metadata: --duration \ --buffer 1 ``` + Then compute the auto window from logged DriverStation state: + ```sh python3 .agents/skills/wpilib-sim/scripts/find_wpilog_window.py \ --repo . \ @@ -43,6 +47,7 @@ metadata: --duration ``` - Preferred export command from a built fork: + ```sh ./node_modules/.bin/electron bundles/main.js \ --agent-export \ @@ -60,6 +65,7 @@ metadata: - Realtime export records the active 2D/3D field canvas while AdvantageScope playback runs at 1x. A current fork waits for selected-renderer readiness before recording, so 3D field assets should be loaded in frame 0 without a fixed delay. A preview should take roughly the requested video duration plus small startup/transcode overhead. - For agent exports, prefer `--agent-headless` instead of Chromium `--headless`. It keeps AdvantageScope windows hidden while preserving the normal renderer/WebGL lifecycle needed for 3D recording. - The skill includes helper scripts: + ```sh python3 .agents/skills/advantagescope/scripts/discover_ascope_assets.py \ --repo . @@ -90,6 +96,7 @@ metadata: - Use `--agent-export-mode frames` only for debugging deterministic frame stepping; normal auto previews must not use the frame-by-frame path. - Use `--agent-allow-frame-only` only with frame export debugging when no encoder is available. - Optional control mode: + ```sh ./node_modules/.bin/electron bundles/main.js --agent-control --agent-port 0 ``` @@ -108,6 +115,7 @@ metadata: - Prefer `capture_layout.py` for graph screenshots. It launches the fork in `--agent-control --agent-headless`, waits for `liveStatus.ready=true`, optionally sends `setTime`, sends `capture`, and closes cleanly. - Pair graph screenshots with `$wpilib-sim` topic summaries from `read_wpilog_values.py` so users get both the visual trend and concrete min/max values. - Fast path for current-style graph requests: + ```sh python3 .agents/skills/wpilib-sim/scripts/list_wpilog_topics.py \ --repo . \ @@ -141,22 +149,23 @@ metadata: - hub tab 1: Line Graph controller tab, - satellite window: attached to the Line Graph controller UUID. - Use `scripts/generate_multiview_3d_joysticks_layout.py` for 3D Field + Joysticks layouts. The helper can select the field tab or joystick tab with `--selected-tab field|joysticks` and can select a specific joystick layout for a port, for example `--joystick-port 0 --joystick-layout "Xbox Controller (White)"`. -- For game pieces, add `--game-piece-topic ` and `--game-piece-variant `. For MapleSim 2026 fuel, use `/RealOutputs/FieldSimulation/Fuel` and variant `Fuel`. -- For projectile or path overlays, add `--trajectory-topic `. For MapleSim fuel shots, use `/RealOutputs/FieldSimulation/FuelShotTrajectory`; the helper adds it as a 3D Field `trajectory` source with a bold orange line by default. +- For game pieces, add `--game-piece-topic ` and `--game-piece-variant `. For fuel, use `/Robot/Sim/Fuel/Positions` (all pieces) or `/Robot/Sim/Fuel/InFlight` (airborne only) and variant `Fuel`. +- For projectile or path overlays, add `--trajectory-topic `. For our fuel shots, use `/Robot/Sim/Fuel/LastShotArc`; the helper adds it as a 3D Field `trajectory` source with a bold orange line by default. - For robot sources that include Z/pitch/roll, pass `--topic-type Pose3d` to `scripts/generate_field3d_layout.py`. For MapleSim bump traversal, use `Sim/RobotPose3d` (logged under `/Robot/` by DogLog) with `--topic-type Pose3d`. - Use explicit field and robot model arguments from the task or asset discovery. Do not bake season-specific asset ids into the skill or helper defaults. - Export with `export_preview.py --mode multiview --headless`. Expected outputs are `view-0-hub.webm`, `view-1-satellite.webm`, `preview.mp4`, and `manifest.json`. - Joystick multiview is supported by the fork's renderer-owned canvas capture path. Validate manifests report the joystick view with `sourceMode: "renderer-canvas"` and `sourceName: "JoysticksRenderer"`. - Fast path for a 3D teleop preview plus live Xbox joystick pane: + ```sh python3 .agents/skills/advantagescope/scripts/generate_multiview_3d_joysticks_layout.py \ --out artifacts/auto-previews/layouts/teleop-3d-joysticks.json \ --field "" \ --robot "" \ - --pose-topic /RealOutputs/FieldSimulation/RobotPosition \ - --game-piece-topic /RealOutputs/FieldSimulation/Fuel \ + --pose-topic /Robot/Sim/RobotPose3d \ + --game-piece-topic /Robot/Sim/Fuel/Positions \ --game-piece-variant Fuel \ - --trajectory-topic /RealOutputs/FieldSimulation/FuelShotTrajectory \ + --trajectory-topic /Robot/Sim/Fuel/LastShotArc \ --joystick-port 0 \ --joystick-layout "Xbox Controller (White)" \ --selected-tab field @@ -173,6 +182,7 @@ metadata: --mode multiview ``` - Fast path for a 3D auto preview synced with a four-topic current graph: + ```sh python3 .agents/skills/advantagescope/scripts/generate_multiview_layout.py \ --out artifacts/auto-previews/layouts/multiview-3d-drive-current.json \ diff --git a/.agents/skills/coderabbitai-review/SKILL.md b/.agents/skills/coderabbitai-review/SKILL.md index e6689549..61754576 100644 --- a/.agents/skills/coderabbitai-review/SKILL.md +++ b/.agents/skills/coderabbitai-review/SKILL.md @@ -1,8 +1,9 @@ --- + name: coderabbitai-review description: Review an open PR with CodeRabbit — triage its comments, fix valid issues, push, and loop until the review approves. Use when a PR on this repo has a CodeRabbit review pending or needs one. license: MIT ---- +------------ # CodeRabbit PR Review Loop @@ -66,12 +67,12 @@ status check, and note the bot may still be generating its review. Classify every comment: -| Class | Action | -| --- | --- | -| Valid fix | Fix it in code/docs, commit, push. | -| False positive / out of scope | Reply to the thread with a short justification (cite file:line evidence) and resolve it. | -| Already fixed | Reply pointing at the commit that fixed it. | -| Style preference only | Apply only if it matches the repo conventions in `docs/coding-conventions/`; otherwise reply briefly and resolve. | +| Class | Action | +|-------------------------------|-------------------------------------------------------------------------------------------------------------------| +| Valid fix | Fix it in code/docs, commit, push. | +| False positive / out of scope | Reply to the thread with a short justification (cite file:line evidence) and resolve it. | +| Already fixed | Reply pointing at the commit that fixed it. | +| Style preference only | Apply only if it matches the repo conventions in `docs/coding-conventions/`; otherwise reply briefly and resolve. | Rule of thumb: fix fast, cheap, real issues; reply with evidence for everything else. Never blindly apply a suggestion — verify it against the actual code diff --git a/.agents/skills/frc-code-review/SKILL.md b/.agents/skills/frc-code-review/SKILL.md index 8e634866..86df21dd 100644 --- a/.agents/skills/frc-code-review/SKILL.md +++ b/.agents/skills/frc-code-review/SKILL.md @@ -1,11 +1,12 @@ --- + name: frc-code-review description: > - Structured code review for FRC robot Java code. Use when asked to review, audit, or critique robot - code, or when checking code before competition. Covers safety, WPILib best practices, performance, - robustness, and competition readiness. Triggers on: "review my robot code", "check this subsystem", - "is this code competition-ready", or "what's wrong with this command". ---- +Structured code review for FRC robot Java code. Use when asked to review, audit, or critique robot +code, or when checking code before competition. Covers safety, WPILib best practices, performance, +robustness, and competition readiness. Triggers on: "review my robot code", "check this subsystem", +"is this code competition-ready", or "what's wrong with this command". +---------------------------------------------------------------------- # FRC Code Review diff --git a/.agents/skills/frc-vision/SKILL.md b/.agents/skills/frc-vision/SKILL.md index 80ca872b..635c40d1 100644 --- a/.agents/skills/frc-vision/SKILL.md +++ b/.agents/skills/frc-vision/SKILL.md @@ -1,20 +1,38 @@ --- + name: frc-vision description: > - FRC vision processing best practices for Java — PhotonVision, Limelight, and WPILib pose estimation. - Use when implementing or reviewing AprilTag detection, pose estimation, vision-aided odometry, or - vision-based targeting. Triggers on: PhotonVision, Limelight, AprilTags, pose estimation, - VisionSubsystem, addVisionMeasurement, PoseEstimator, or any vision-related robot code task. ---- +Spectrum 3847 FRC vision work in Java — Limelight MegaTag AprilTag pose estimation fused into the +swerve pose estimator. Use when implementing or reviewing AprilTag detection, pose estimation, +vision-aided odometry, or vision rejection/std-dev tuning. Triggers on: Limelight, MegaTag, +AprilTags, pose estimation, Vision subsystem, addVisionMeasurement, SwerveDrivePoseEstimator, or +any vision-related robot code task. +metadata: +short-description: Limelight MegaTag vision + pose fusion +--------------------------------------------------------- + +# FRC Vision (Java) — Spectrum 3847 + +> Vision runs on **Limelight** hardware. Verify class/method names against `src/main/java` before +> trusting external examples. + +## Our Setup -# FRC Vision (Java) +- **Subsystem:** [`frc.robot.subsystems.vision.Vision`](../../../src/main/java/frc/robot/subsystems/vision/Vision.java) `implements Subsystem`. It manages three Limelights — `backLL`, `leftLL`, `rightLL` (hostnames `limelight-back/left/right`) — held in `allLimelights`, and fuses them into the swerve `SwerveDrivePoseEstimator`. +- **Wrapper:** [`frc.spectrumLib.vision.Limelight`](../../../src/main/java/frc/spectrumLib/vision/Limelight.java) wraps the vendored `LimelightHelpers`. Real methods: `getMegaTag1_Pose3d()`, `getMegaTag2_Pose2d()`, `getMegaTag1_PoseEstimate()`, `getMegaTag1PoseTimestamp()`, `getTagCountInView()`, `getRawFiducial()` (can return null), `setRobotOrientation(degrees[, rate])`, `sendValidStatus()/sendInvalidStatus()`. +- **Field layout:** WPILib `AprilTagFieldLayout.loadField(AprilTagFields.k2026RebuiltWelded)` — not PhotonLib. -## Overview +## Each Loop (`Vision.periodic()`) -Covers FRC vision in Java: PhotonVision, Limelight, and WPILib pose estimation. +1. Push robot heading to every Limelight via `setRobotOrientation(...)` so MegaTag2 IMU fusion stays accurate. Do not throttle this — fast-motion accuracy depends on flushing it each loop. +2. Pick the best chassis camera (`getBestLimelight()`, ranked over `swerveLimelights` by tag count + target size). +3. Run the MT1 rejection pipeline (and MT2 while disabled) on the selected camera and add accepted estimates via `addVisionMeasurement(pose, timestamp, stdDevs)`. +4. Log per-camera status through `VisionLogger`. -- **PhotonVision** — AprilTag pipelines on supported cameras (Orange Pi / co-processor), `PhotonCamera` reads, multi-tag results. -- **Limelight** — MegaTag 1/2 pipelines, `LimelightHelpers`, pipeline selection, LED control. -- **WPILib pose estimation** — prefer a drivetrain-specific estimator such as `SwerveDrivePoseEstimator`; the generic `PoseEstimator` is a base class, not a robot-code choice. Covers `addVisionMeasurement(pose, timestamp, stdDevs)`, standard-deviation tuning, vision-vs-odometry weighting, and fusion gotchas (latency, double-counting). +## What to Check When Editing -When implementing or reviewing, check: the transform direction expected by each API (`PhotonPoseEstimator` takes `robotToCamera`; pass `cameraToRobot` only to APIs that require it — the inverse transform produces incorrect poses), rejection criteria (ambiguity, distance, age), a sensible std-dev ladder, and whether vision feeds targeting (turret) or only localization. +- **Timebase:** pose timestamps are converted with Phoenix `Utils.fpgaToCurrentTime(...)` to match the estimator's timebase — keep both operands in the same timebase. +- **Rejection criteria** (`VisionConfig`): stale timestamp (`kMaxTimeDeltaSeconds`), rotation-speed gate, roll/pitch tilt (in degrees, via `Math.toRadians(5)`), out-of-field, tag count/ambiguity/target-size tiers. +- **Std-dev ladder:** `degStds` overrides should only ever *widen* (`Math.max`) toward `kLargeVariance` to discard heading — never narrow a discarded heading back into the fusion. MT2 heading is always discarded; MT1 supplies heading. +- **`resetPoseToVision`** validates both `botpose3D` and the MT2 `megaPose` (out-of-field/height/tilt) before snapping with a tight 0.00001 std-dev. +- **Null safety:** `getRawFiducial()` can return null; guard before dereferencing. diff --git a/.agents/skills/live-robot-telemetry/SKILL.md b/.agents/skills/live-robot-telemetry/SKILL.md index 25052ab9..7c742321 100644 --- a/.agents/skills/live-robot-telemetry/SKILL.md +++ b/.agents/skills/live-robot-telemetry/SKILL.md @@ -1,9 +1,10 @@ --- + name: live-robot-telemetry description: "Use for live real-robot practice telemetry: connecting read-only to NT4, watching odometry and DogLog topics from an active robot, sampling bounded practice windows, and recommending optimizations from live robot data without commanding the robot." metadata: - short-description: Analyze live robot NT4 telemetry ---- +short-description: Analyze live robot NT4 telemetry +--------------------------------------------------- # Live Robot Telemetry @@ -24,12 +25,14 @@ metadata: 4. If the robot is off, rebooting, or changing batteries and NT4 does not respond, poll about once every 30 seconds until it reconnects or the agent is stopped. Avoid tight retry loops while the radio and roboRIO are coming back up. 5. After a reconnect or deploy, ignore the first 20-30 seconds of loop timing unless the user explicitly asks about boot performance; initialization spikes during that window are expected. 6. Start with topic discovery before sampling: + ```sh python3 .agents/skills/live-robot-telemetry/scripts/list_live_nt_topics.py \ --host 10.38.47.2 \ --filter Swerve ``` 7. Take a quick status snapshot before a longer capture: + ```sh python3 .agents/skills/live-robot-telemetry/scripts/snapshot_live_nt.py \ --host 10.38.47.2 \ @@ -38,6 +41,7 @@ metadata: --topic /DriverStation/Enabled ``` 8. Capture a bounded practice window: + ```sh python3 .agents/skills/live-robot-telemetry/scripts/sample_live_nt.py \ --host 10.38.47.2 \ @@ -55,8 +59,8 @@ metadata: - Motor currents: `Swerve/Currents/DriveStatorCurrent`, `Swerve/Currents/SteerStatorCurrent`, `Swerve/Currents/DriveSupplyCurrent`, `Swerve/Currents/SteerSupplyCurrent`. - DriverStation state: `/DriverStation/Enabled`, `/DriverStation/Autonomous`, `/DriverStation/Test`, `/DriverStation/AllianceStation`, `/DriverStation/Joystick0/AxisValues`, `/DriverStation/Joystick0/ButtonValues`. - Command scheduler: `Swerve/CurrentCommand`, `Commands` (init/end lifecycle), `Alerts`, `Sim/SimPose` (SIM pose), `Sim/RobotPose3d` (SIM bump-corrected pose). -- Vision: discover `Vision`, `VisionIOSim`, Limelight tables, and accepted/rejected pose topics before assuming names (team uses PhotonVision AprilTag pipelines). -- Superstructure: discover `Intake`, `Shooter`, `Turret`, `Indexer`, `Climb`, `Fuel`, `LED`, and `States` topics before assuming names. +- Vision: discover `Vision/*` topics, the `limelight-back/left/right` NT tables, and accepted/rejected pose status before assuming names (Limelight MegaTag pipelines). +- Subsystems: discover the real topic roots before assuming names — this robot has `FuelIntake`, `Launcher`, `IndexerBed`, `IndexerTower`, `Hood`, `Leds`, and the `SuperStructure` orchestrator. - If topic names differ, prefer the discovered names from `list_live_nt_topics.py` over guessing. ## Analysis Workflow @@ -65,7 +69,7 @@ metadata: - For heading and gyro issues, compare odometry rotation, raw gyro, commanded heading, and DriverStation mode transitions. - For velocity tracking, compare requested path or driver behavior with actual velocity, setpoint topics, module states, and current/voltage topics when available. - For vision, compare accepted observations, camera names, tag counts, timestamps/latency, and pose jumps near observation updates. -- For this robot, do not remove or throttle the per-loop NT flush used to push Limelight robot pose and turret pose data unless the user explicitly approves a replacement. Accurate fast-motion vision depends on those camera inputs being flushed every loop (see vision subsystem in `src/main/java/frc/robot/subsystems/vision`). +- For this robot, do not remove or throttle the per-loop `setRobotOrientation(...)` heading push to the Limelights unless the user explicitly approves a replacement. Accurate fast-motion MegaTag2 fusion depends on that orientation being flushed every loop (see the vision subsystem in `src/main/java/frc/robot/subsystems/vision`). - For subsystem optimization, tie recommendations to captured evidence: command state, setpoint, measured response, current draw, voltage demand, and DriverStation mode. - When the user wants a visual artifact, capture or retrieve a WPILOG first, then use `$advantagescope` for layouts/exports. Live NT snapshots alone are for data summaries, not full AdvantageScope playback. diff --git a/.agents/skills/maple-sim/SKILL.md b/.agents/skills/maple-sim/SKILL.md index 640000bf..330920da 100644 --- a/.agents/skills/maple-sim/SKILL.md +++ b/.agents/skills/maple-sim/SKILL.md @@ -1,9 +1,10 @@ --- + name: maple-sim description: "Use for our Spectrum 3847 MapleSim integration work: maintaining the swerve-first MapleSim simulation, verifying WPILib headless sim logs, calibrating physics constants, and extending simulation to intake, projectiles, opponents, or vision." metadata: - short-description: Maintain MapleSim simulation ---- +short-description: Maintain MapleSim simulation +----------------------------------------------- # MapleSim @@ -13,7 +14,7 @@ metadata: - Preserve the existing spectrumLib abstraction. Do not rewrite `Swerve`, `SwerveModule`, PathPlanner autos, or `MapleSimSwerveDrivetrain` unless the task explicitly requires it. - For drivetrain simulation, prefer MapleSim as the physics source while preserving the existing telemetry surface. Spectrum 3847 SIM swerve uses `frc.spectrumLib.swerve.MapleSimSwerveDrivetrain` on `CTRE` Phoenix TalonFX motors/controllers; keep the lightweight non-MapleSim `SimpleMotorFeedforward` path available and do not reintroduce the Phoenix remote-CANcoder sim bridge unless the steering instability that caused azimuth wind/crawl has been solved. - Check the SIM gate before debugging: MapleSim is constructed and updated only in SIM mode (see `Swerve.startSimThread()` and `RobotSim`), gated by Phoenix `Utils.isSimulation()`. Real and replay modes never run MapleSim. Our robot has no `MapleSimConstants.useMapleSim`-style kill switch — MapleSim is always used in SIM. -- Keep real and replay modes isolated from MapleSim. MapleSim belongs in `Constants.RobotMode.SIM`. +- Keep real and replay modes isolated from MapleSim. It runs only under Phoenix `Utils.isSimulation()`. - Record durable progress and verification notes in `.agents/maple-sim-implementation.md` when changing MapleSim behavior. ## Current Integration Shape @@ -33,6 +34,7 @@ metadata: - On 2026-06-06, the official docs vendordep URL returned `0.4.0-beta-obstacles-fix`, but the official Maven metadata only published up to `0.4.0-beta`. - This repo pins `maplesim-java` to `0.4.0-beta`. - If dependency resolution fails, check: + ```sh curl -s https://shenzhen-robotics-alliance.github.io/maple-sim/vendordep/repos/releases/org/ironmaple/maplesim-java/maven-metadata.xml ``` @@ -40,10 +42,12 @@ metadata: ## Verification Commands - Compile and test: + ```sh ./gradlew test ``` - Run a headless auto through the permanent sim bridge: + ```sh python3 .agents/skills/wpilib-sim/scripts/run_auto_sim.py \ --repo . \ @@ -53,6 +57,7 @@ metadata: --buffer 1 ``` - Run full-forward teleop through joystick 0 as an Xbox controller: + ```sh python3 .agents/skills/wpilib-sim/scripts/run_teleop_sim.py \ --repo . \ @@ -62,6 +67,7 @@ metadata: --axes "0,-1,0,0,0,0" ``` - Run a timed joystick rectangle in the open center-field gap. In current default MapleSim mode, heightmap bump simulation is enabled and hard ramp colliders are disabled: + ```sh python3 .agents/skills/wpilib-sim/scripts/run_teleop_sim.py \ --repo . \ @@ -70,12 +76,14 @@ metadata: --sequence "1.2:0,-1,0,0,0,0;1.0:-1,0,0,0,0,0;1.2:0,1,0,0,0,0;1.0:1,0,0,0,0,0;0.5:0,0,0,0,0,0" ``` - Run fixed red own-alliance-side fuel shots against the tuned shooter map: + ```sh python3 .agents/skills/wpilib-sim/scripts/run_shot_map_sim.py \ --repo . \ --distances "1.75,3.25,5.0" ``` - Check MapleSim, swerve, and fuel topics (DogLog keys as published by `frc.spectrumLib.telemetry.Telemetry`, which DogLog prefixes under `/Robot/`): + ```sh python3 .agents/skills/wpilog-decode/scripts/read_wpilog_values.py \ --repo . \ diff --git a/.agents/skills/wpilib-best-practices/SKILL.md b/.agents/skills/wpilib-best-practices/SKILL.md index 9a7c2500..74026705 100644 --- a/.agents/skills/wpilib-best-practices/SKILL.md +++ b/.agents/skills/wpilib-best-practices/SKILL.md @@ -1,11 +1,12 @@ --- + name: wpilib-best-practices description: > - WPILib and FRC robot programming best practices, design patterns, and code guidance for Java. - Use when writing, reviewing, or explaining WPILib robot code—command-based project structure, - subsystems, autonomous routines, RobotContainer layout, command definition patterns (inline, - factory, subclass), or Constants organization. ---- +WPILib and FRC robot programming best practices, design patterns, and code guidance for Java. +Use when writing, reviewing, or explaining WPILib robot code—command-based project structure, +subsystems, autonomous routines, RobotContainer layout, command definition patterns (inline, +factory, subclass), or Constants organization. +---------------------------------------------- # WPILib Best Practices @@ -13,11 +14,11 @@ WPILib best practices span multiple domains. Load only the reference(s) relevant ## References -| Domain | Reference | When to load | -| ------ | --------- | ------------ | -| Command-based architecture | [references/command-based.md](references/command-based.md) | Project structure, `Robot`/`RobotContainer` layout, command definition patterns (inline vs factory vs subclass), autonomous routines, subsystem organization, `Constants` class | -| Command Scheduler | [references/command-scheduler.md](references/command-scheduler.md) | How the scheduler runs, per-iteration execution order, default commands, scheduling conflicts, event callbacks, `disable()`/`cancel()` | -| Command Compositions | [references/command-compositions.md](references/command-compositions.md) | Combining commands with `sequence`, `parallel`, `race`, `deadline`, `repeatedly`; end condition and end behavior decorators; `ConditionalCommand`; `ProxyCommand` | +| Domain | Reference | When to load | +|----------------------------|--------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Command-based architecture | [references/command-based.md](references/command-based.md) | Project structure, `Robot`/`RobotContainer` layout, command definition patterns (inline vs factory vs subclass), autonomous routines, subsystem organization, `Constants` class | +| Command Scheduler | [references/command-scheduler.md](references/command-scheduler.md) | How the scheduler runs, per-iteration execution order, default commands, scheduling conflicts, event callbacks, `disable()`/`cancel()` | +| Command Compositions | [references/command-compositions.md](references/command-compositions.md) | Combining commands with `sequence`, `parallel`, `race`, `deadline`, `repeatedly`; end condition and end behavior decorators; `ConditionalCommand`; `ProxyCommand` | ## Quick Navigation diff --git a/.agents/skills/wpilib-best-practices/references/command-based.md b/.agents/skills/wpilib-best-practices/references/command-based.md index 291c7049..077df2d9 100644 --- a/.agents/skills/wpilib-best-practices/references/command-based.md +++ b/.agents/skills/wpilib-best-practices/references/command-based.md @@ -13,14 +13,14 @@ ## Project Structure -| Class/Dir | Responsibility | -| --------- | -------------- | -| `Main` | Entry point (Java only). Do not modify. | -| `Robot` | Control flow. Keep minimal—declarative paradigm. | -| `RobotContainer` | Subsystems, button bindings, autonomous selection. Most setup lives here. | -| `Constants` | Global constants (speeds, PID gains, ports). Use inner classes per subsystem. | -| `Subsystems/` | User-defined subsystem classes | -| `Commands/` | User-defined command classes | +| Class/Dir | Responsibility | +|------------------|-------------------------------------------------------------------------------| +| `Main` | Entry point (Java only). Do not modify. | +| `Robot` | Control flow. Keep minimal—declarative paradigm. | +| `RobotContainer` | Subsystems, button bindings, autonomous selection. Most setup lives here. | +| `Constants` | Global constants (speeds, PID gains, ports). Use inner classes per subsystem. | +| `Subsystems/` | User-defined subsystem classes | +| `Commands/` | User-defined command classes | ### Robot Class Essentials @@ -50,13 +50,13 @@ When a command is reused (teleop bindings, autonomous, self-test), avoid duplica ### Pattern Selection -| Use Case | Preferred Pattern | Avoid | -| -------- | ----------------- | ----- | -| Single-subsystem, no internal state | Instance factory method | Inline everywhere; Command subclass | -| Single-subsystem, has internal state (e.g. PID) | Instance factory with captured state | Command subclass (unless logic is complex) | -| Multi-subsystem | Static or non-static command factory | Instance factory (causes circular deps) | -| Stateful, complex logic, multi-subsystem | Subclass `Command` | Inline/factory if it gets messy | -| Composite (sequence/parallel) | Factory method with `sequence`/`parallel` | Subclass `SequentialCommandGroup` (extra file per group) | +| Use Case | Preferred Pattern | Avoid | +|-------------------------------------------------|-------------------------------------------|----------------------------------------------------------| +| Single-subsystem, no internal state | Instance factory method | Inline everywhere; Command subclass | +| Single-subsystem, has internal state (e.g. PID) | Instance factory with captured state | Command subclass (unless logic is complex) | +| Multi-subsystem | Static or non-static command factory | Instance factory (causes circular deps) | +| Stateful, complex logic, multi-subsystem | Subclass `Command` | Inline/factory if it gets messy | +| Composite (sequence/parallel) | Factory method with `sequence`/`parallel` | Subclass `SequentialCommandGroup` (extra file per group) | ### Instance Factory Methods @@ -183,8 +183,8 @@ public class ScoreCoralCommand extends SequentialCommandGroup { ## Common Anti-Patterns -| Anti-pattern | Problem | Fix | -| ------------ | ------- | --- | -| Calling `subsystem.method()` directly in `teleopPeriodic()` | Bypasses scheduler; conflicts with running commands | Bind to a command via trigger/button instead | -| Defining the same inline command in multiple places | Bugs fixed in one place silently persist elsewhere | Extract to an instance factory method on the subsystem | -| Constants scattered across subsystem files | Same port/gain defined in multiple places | Consolidate into `Constants` with inner classes per subsystem | +| Anti-pattern | Problem | Fix | +|-------------------------------------------------------------|-----------------------------------------------------|---------------------------------------------------------------| +| Calling `subsystem.method()` directly in `teleopPeriodic()` | Bypasses scheduler; conflicts with running commands | Bind to a command via trigger/button instead | +| Defining the same inline command in multiple places | Bugs fixed in one place silently persist elsewhere | Extract to an instance factory method on the subsystem | +| Constants scattered across subsystem files | Same port/gain defined in multiple places | Consolidate into `Constants` with inner classes per subsystem | diff --git a/.agents/skills/wpilib-best-practices/references/command-compositions.md b/.agents/skills/wpilib-best-practices/references/command-compositions.md index 53dd10c4..f9d10471 100644 --- a/.agents/skills/wpilib-best-practices/references/command-compositions.md +++ b/.agents/skills/wpilib-best-practices/references/command-compositions.md @@ -25,13 +25,13 @@ Compositions combine commands into a single command object. They can be nested r ## Composition Types -| Type | Ends when | Factory | Decorator | -| ---- | --------- | ------- | --------- | -| Sequential | All members finish in order | `Commands.sequence(...)` | `.andThen(...)`, `.beforeStarting(...)` | -| Parallel (all) | ALL members finish | `Commands.parallel(...)` | `.alongWith(...)` | -| Parallel race | ANY member finishes | `Commands.race(...)` | `.raceWith(...)` | -| Parallel deadline | The *deadline* command finishes | `Commands.deadline(deadline, ...)` | `.deadlineWith(...)` | -| Repeat | Never (runs until interrupted) | `Commands.repeatingSequence(...)` | `.repeatedly()` | +| Type | Ends when | Factory | Decorator | +|-------------------|---------------------------------|------------------------------------|-----------------------------------------| +| Sequential | All members finish in order | `Commands.sequence(...)` | `.andThen(...)`, `.beforeStarting(...)` | +| Parallel (all) | ALL members finish | `Commands.parallel(...)` | `.alongWith(...)` | +| Parallel race | ANY member finishes | `Commands.race(...)` | `.raceWith(...)` | +| Parallel deadline | The *deadline* command finishes | `Commands.deadline(deadline, ...)` | `.deadlineWith(...)` | +| Repeat | Never (runs until interrupted) | `Commands.repeatingSequence(...)` | `.repeatedly()` | ### Sequential @@ -75,21 +75,21 @@ Compositions automatically inherit the union of all member requirements. A compo ## End Condition Decorators -| Decorator | Behavior | -| --------- | -------- | -| `.withTimeout(seconds)` | Interrupts command after N seconds | -| `.until(BooleanSupplier)` | Interrupts command when condition becomes true | -| `.onlyWhile(BooleanSupplier)` | Interrupts command when condition becomes false | -| `.onlyIf(BooleanSupplier)` | Skips command entirely if condition is false at schedule time | +| Decorator | Behavior | +|-------------------------------|---------------------------------------------------------------| +| `.withTimeout(seconds)` | Interrupts command after N seconds | +| `.until(BooleanSupplier)` | Interrupts command when condition becomes true | +| `.onlyWhile(BooleanSupplier)` | Interrupts command when condition becomes false | +| `.onlyIf(BooleanSupplier)` | Skips command entirely if condition is false at schedule time | --- ## End Behavior Decorators -| Decorator | Behavior | -| --------- | -------- | +| Decorator | Behavior | +|-------------------------------|-----------------------------------------------------------------| | `.finallyDo(BooleanConsumer)` | Runs lambda after command ends; boolean = `true` if interrupted | -| `.handleInterrupt(Runnable)` | Runs lambda only on interruption | +| `.handleInterrupt(Runnable)` | Runs lambda only on interruption | --- diff --git a/.agents/skills/wpilib-best-practices/references/command-scheduler.md b/.agents/skills/wpilib-best-practices/references/command-scheduler.md index dfad4e29..792bd2ba 100644 --- a/.agents/skills/wpilib-best-practices/references/command-scheduler.md +++ b/.agents/skills/wpilib-best-practices/references/command-scheduler.md @@ -49,22 +49,22 @@ Register with `subsystem.setDefaultCommand(command)`. Scheduled automatically wh Hook into scheduler events for logging or telemetry: -| Method | Fires when | -| ------ | ---------- | -| `onCommandInitialize(consumer)` | Command starts | -| `onCommandExecute(consumer)` | Each iteration during execution | -| `onCommandFinish(consumer)` | `isFinished()` returns true | +| Method | Fires when | +|----------------------------------|------------------------------------| +| `onCommandInitialize(consumer)` | Command starts | +| `onCommandExecute(consumer)` | Each iteration during execution | +| `onCommandFinish(consumer)` | `isFinished()` returns true | | `onCommandInterrupt(biConsumer)` | Command is canceled or interrupted | --- ## Control Methods -| Method | Effect | -| ------ | ------ | -| `disable()` | Stops the scheduler: `run()` and `schedule()` become no-ops while disabled, and already scheduled commands stop executing until `enable()` is called | -| `enable()` | Resumes scheduling | -| `cancel(command)` | Explicitly stops a running command; calls `end(true)` | +| Method | Effect | +|-------------------|------------------------------------------------------------------------------------------------------------------------------------------------------| +| `disable()` | Stops the scheduler: `run()` and `schedule()` become no-ops while disabled, and already scheduled commands stop executing until `enable()` is called | +| `enable()` | Resumes scheduling | +| `cancel(command)` | Explicitly stops a running command; calls `end(true)` | --- diff --git a/.agents/skills/wpilib-sim/SKILL.md b/.agents/skills/wpilib-sim/SKILL.md index e784093a..d91d0ee4 100644 --- a/.agents/skills/wpilib-sim/SKILL.md +++ b/.agents/skills/wpilib-sim/SKILL.md @@ -1,9 +1,10 @@ --- + name: wpilib-sim description: "Use for WPILib robot simulation work: running desktop or headless sim, selecting project-specific sim IO, inspecting live NetworkTables outputs, emulating DriverStation/joystick inputs, and producing WPILOGs for verification without adding committed one-off harnesses. Use wpilog-decode for deep WPILOG topic decoding." metadata: - short-description: Run WPILib sim and inspect logs ---- +short-description: Run WPILib sim and inspect logs +-------------------------------------------------- # WPILib Sim @@ -23,30 +24,26 @@ metadata: 1. Ground in the repo with `rg`, `git status --short`, and targeted file reads. 2. Discover the WPILib JDK and any required sim-mode override: - ```sh - ls ~/wpilib - rg -n "RobotMode|robotMode|SIM|simulation|JAVA_HOME|wpilib" - ``` - + ```sh + ls ~/wpilib + rg -n "RobotMode|robotMode|SIM|simulation|JAVA_HOME|wpilib" + ``` 3. Run normal tests before or after risky changes: - ```sh - JAVA_HOME= ./gradlew test - ``` - + ```sh + JAVA_HOME= ./gradlew test + ``` 4. Run normal sim when a human/live tool will drive the robot: - ```sh - JAVA_HOME= ./gradlew simulateJava - ``` - + ```sh + JAVA_HOME= ./gradlew simulateJava + ``` 5. Run headless sim when an agent needs to automate checks without opening GUI windows: - ```sh - JAVA_HOME= \ - ./gradlew --init-script .agents/skills/wpilib-sim/references/headless-sim.gradle simulateJava - ``` - + ```sh + JAVA_HOME= \ + ./gradlew --init-script .agents/skills/wpilib-sim/references/headless-sim.gradle simulateJava + ``` 6. In headless automated runs, the robot still needs DriverStation/joystick state. The bundled scripts write NT state under `/SimAgent/...`, which is a SimAgentBridge-style contract. This repo's robot code does not currently consume those topics, so automated runs require an agent-side bridge before relying on the scripts. For manual simulation, run `./gradlew simulateJava` directly and control DriverStation state through the Sim GUI DriverStation tab. 7. Verify outputs from existing logged topics, preferably IO-layer applied voltage, velocity, position, current, and command/reference topics. Avoid custom test-only outputs unless the user asked for a harness. 8. For log inspection, use `$wpilog-decode`. Compatibility wrappers remain in this skill for older command paths. @@ -56,7 +53,6 @@ metadata: - The scripts in this skill write NT topics under `/SimAgent` to drive a sim through an agent-side bridge: DriverStation state, joystick inputs, clean exit, and the shot-map test table. - Spectrum 2026 robot code does **not** ship that bridge. Until a bridge or equivalent consumer exists in robot code, these scripts can write NT values but cannot enable/disable or cleanly stop this repo's sim on their own. Verify against the Sim GUI DriverStation tab or a working bridge before trusting automated runs. - DriverStation control topics written by the scripts: - - `/SimAgent/DriverStation/AllianceStation` string: `Red1`, `Red2`, `Red3`, `Blue1`, `Blue2`, `Blue3`, or `Unknown` - `/SimAgent/DriverStation/Enabled` boolean - `/SimAgent/DriverStation/Autonomous` boolean @@ -65,18 +61,14 @@ metadata: - `/SimAgent/DriverStation/FmsAttached` boolean - `/SimAgent/Control/Exit` boolean for clean shutdown - `/SimAgent/Control/ExitAfterSeconds` double timeout from bridge startup - - Joystick topics by port: - - `/SimAgent/Joystick//Axes` double array, axis indexes matching WPILib - `/SimAgent/Joystick//Buttons` boolean array, button 1 at index 0 - `/SimAgent/Joystick//POVs` integer array - `/SimAgent/Joystick//IsXbox` boolean - `/SimAgent/Joystick//Type` integer - `/SimAgent/Joystick//Name` string - - Auto selection must go through the real SmartDashboard/NT Auto Chooser, which this repo publishes from `Auton.java`: - - `/SmartDashboard/Auto Chooser/options` - `/SmartDashboard/Auto Chooser/selected` - `/SmartDashboard/Auto Chooser/active` @@ -87,41 +79,41 @@ metadata: - Run a full auto through the real NT Auto Chooser (bridge-gated; see "Agent Sim Control"): - ```sh - python3 .agents/skills/wpilib-sim/scripts/run_auto_sim.py \ - --repo . \ - --auto \ - --alliance \ - --duration \ - --buffer 1 - ``` + ```sh + python3 .agents/skills/wpilib-sim/scripts/run_auto_sim.py \ + --repo . \ + --auto \ + --alliance \ + --duration \ + --buffer 1 + ``` The script launches headless `simulateJava`, waits for the real chooser options, writes the selected auto over NT, enables autonomous, disables/exits cleanly, and prints `latestLog=`. - Write live teleop/joystick state to a running sim: - ```sh - python3 .agents/skills/wpilib-sim/scripts/sim_nt_control.py \ - --repo . \ - --alliance \ - --enabled \ - --port 0 \ - --axes "0,0,0,1" \ - --buttons "false,false,false,false" - ``` + ```sh + python3 .agents/skills/wpilib-sim/scripts/sim_nt_control.py \ + --repo . \ + --alliance \ + --enabled \ + --port 0 \ + --axes "0,0,0,1" \ + --buttons "false,false,false,false" + ``` Use `--exit` to request clean shutdown. - Run a bounded headless teleop simulation with a fixed Xbox joystick state and a clean WPILOG: - ```sh - python3 .agents/skills/wpilib-sim/scripts/run_teleop_sim.py \ - --repo . \ - --alliance Blue1 \ - --duration 5 \ - --port 0 \ - --axes "0,-1,0,0,0,0" - ``` + ```sh + python3 .agents/skills/wpilib-sim/scripts/run_teleop_sim.py \ + --repo . \ + --alliance Blue1 \ + --duration 5 \ + --port 0 \ + --axes "0,-1,0,0,0,0" + ``` ## AdvantageScope Visualization @@ -129,20 +121,17 @@ metadata: - Prefer vanilla AdvantageScope for manual inspection and a fork only when its opt-in agent hooks are available. - Detect the fork by checking for documented agent flags or a known fork checkout/build before relying on automation. If only vanilla AdvantageScope is installed, open logs/layouts manually and provide WPILOG summaries instead of promising robust screenshots or recordings. - Keep robot-specific choices outside AdvantageScope: - - topic names - preferred layouts - auto names - artifact paths - comparison/assertion logic - - The fork's intended flags are: - ```sh - AdvantageScope --agent-control - AdvantageScope --agent-export --log --layout --out --start --end --fps 30 - ``` - + ```sh + AdvantageScope --agent-control + AdvantageScope --agent-export --log --layout --out --start --end --fps 30 + ``` - Agent control must be local-only, opt-in, and token-protected. Prefer commands like `status`, `openLog`, `applyLayout`, `setTime`, `capture`, `export`, and `close`; do not drive the UI by clicking screen coordinates. - For video previews, prefer the fork's realtime canvas recording path. Frame-by-frame PNG export is only a debugging fallback because it is much slower than the auto duration. - Always pair visual artifacts with a data summary from the WPILOG, such as robot mode/type, selected auto, enabled interval, pose movement, final pose, and notable state transitions. @@ -166,75 +155,72 @@ metadata: - `$wpilog-decode` owns WPILOG listing, value summaries, struct decoding, latest-log lookup, and boolean-window lookup. Prefer: - ```sh - python3 .agents/skills/wpilog-decode/scripts/read_wpilog_values.py \ - --repo . \ - --log \ - --topic - ``` - + ```sh + python3 .agents/skills/wpilog-decode/scripts/read_wpilog_values.py \ + --repo . \ + --log \ + --topic + ``` - Backward-compatible wrappers remain in this skill: - - `scripts/find_latest_simlog.py ` - `scripts/list_wpilog_topics.py --repo [--log ] [--filter ]` - `scripts/read_wpilog_values.py --repo --topic [--topic ...] [--log ]` - `scripts/find_wpilog_window.py --repo --log --all-true [--all-true ...] [--duration ]` - - `scripts/run_auto_sim.py --repo --auto --alliance [--duration ] [--buffer 1]` runs headless sim, selects the auto through the NT Auto Chooser, enables autonomous through `/SimAgent` topics (bridge-gated), exits cleanly, and prints the latest log path. - `scripts/run_teleop_sim.py --repo --alliance --duration --axes [--port 0]` runs headless sim, sets a simulated Xbox joystick through `/SimAgent` topics (bridge-gated), enables teleop for the duration, exits cleanly, and prints the latest log path. For Xbox full forward left stick, use `--axes "0,-1,0,0,0,0"`. - `scripts/run_teleop_sim.py` also supports timed joystick sequences with `--sequence "duration:axes;duration:axes"`. For a rectangle with Xbox joystick 0: - ```sh - python3 .agents/skills/wpilib-sim/scripts/run_teleop_sim.py \ - --repo . \ - --alliance Blue1 \ - --port 0 \ - --sequence "1.2:0,-1,0,0,0,0;1.0:-1,0,0,0,0,0;1.2:0,1,0,0,0,0;1.0:1,0,0,0,0,0;0.5:0,0,0,0,0,0" - ``` - + ```sh + python3 .agents/skills/wpilib-sim/scripts/run_teleop_sim.py \ + --repo . \ + --alliance Blue1 \ + --port 0 \ + --sequence "1.2:0,-1,0,0,0,0;1.0:-1,0,0,0,0,0;1.2:0,1,0,0,0,0;1.0:1,0,0,0,0,0;0.5:0,0,0,0,0,0" + ``` - Timed sequences also support per-segment joystick ports, buttons, and POVs with `duration:port:axes:buttons:povs`. Port state persists until changed, which is useful for setting a secondary sim control port while driving with port 0. Example fuel intake/shoot sequence: - ```sh - python3 .agents/skills/wpilib-sim/scripts/run_teleop_sim.py \ - --repo . \ - --alliance Blue1 \ - --port 0 \ - --sequence "1.5:0:0,0,0,0,0,0:false,false,false,false,false,false,false,false,false,false:-1;2.0:0:0,-1,0,0,0,0:false,false,false,false,false,false,false,false,false,false:-1;3.0:0:0,0,0,1,0,0:false,false,false,false,false,false,false,false,false,false:-1" - ``` - + ```sh + python3 .agents/skills/wpilib-sim/scripts/run_teleop_sim.py \ + --repo . \ + --alliance Blue1 \ + --port 0 \ + --sequence "1.5:0:0,0,0,0,0,0:false,false,false,false,false,false,false,false,false,false:-1;2.0:0:0,-1,0,0,0,0:false,false,false,false,false,false,false,false,false,false:-1;3.0:0:0,0,0,1,0,0:false,false,false,false,false,false,false,false,false,false:-1" + ``` - `scripts/run_shot_map_sim.py --repo . --distances "1.75,3.25,5.0"` runs fixed red-alliance own-side MapleSim fuel shots through `/SimAgent/ShotMapTest` (bridge-gated), using shooter-map hood/flywheel values for each distance. It prints one JSON summary per log with launch speed, expected time of flight, trajectory point count, max trajectory height, closest point to the hub target, MapleSim target tolerance status, and scored-fuel return pose/velocity/count. - For MapleSim heightmap bump smoke tests, run teleop sequences that first move to a bump lane and then drive across it. A verified crossing sequence is: - ```sh - python3 .agents/skills/wpilib-sim/scripts/run_teleop_sim.py \ - --repo . \ - --alliance Blue1 \ - --port 0 \ - --sequence "0.5:0,0,0,0,0,0;0.35:1,0,0,0,0,0;2.8:0,1,0,0,0,0;0.5:0,0,0,0,0,0" - ``` + ```sh + python3 .agents/skills/wpilib-sim/scripts/run_teleop_sim.py \ + --repo . \ + --alliance Blue1 \ + --port 0 \ + --sequence "0.5:0,0,0,0,0,0;0.35:1,0,0,0,0,0;2.8:0,1,0,0,0,0;0.5:0,0,0,0,0,0" + ``` A verified stopped-on-bump check is: - ```sh - python3 .agents/skills/wpilib-sim/scripts/run_teleop_sim.py \ - --repo . \ - --alliance Blue1 \ - --port 0 \ - --sequence "0.5:0,0,0,0,0,0;0.35:1,0,0,0,0,0;0.85:0,1,0,0,0,0;2.0:0,0,0,0,0,0" - ``` + ```sh + python3 .agents/skills/wpilib-sim/scripts/run_teleop_sim.py \ + --repo . \ + --alliance Blue1 \ + --port 0 \ + --sequence "0.5:0,0,0,0,0,0;0.35:1,0,0,0,0,0;0.85:0,1,0,0,0,0;2.0:0,0,0,0,0,0" + ``` Acceptance is not slide-back: `/RealOutputs/FieldSimulation/RobotVelocity` should settle near zero while `/RealOutputs/Simulation/Bump/OnBump`, `ModuleHeights`, `RobotPitchRad`, and/or `RobotRollRad` remain stable and nonzero. + - `scripts/sim_nt_control.py` writes live DriverStation and joystick state through `/SimAgent` NT topics (bridge-gated). + - Use `$wpilog-decode` for boolean-window lookup. Compatibility command for auto preview exports: - ```sh - python3 .agents/skills/wpilog-decode/scripts/find_wpilog_window.py \ - --repo . \ - --log \ - --all-true /DriverStation/Autonomous \ - --all-true /DriverStation/Enabled \ - --duration - ``` + ```sh + python3 .agents/skills/wpilog-decode/scripts/find_wpilog_window.py \ + --repo . \ + --log \ + --all-true /DriverStation/Autonomous \ + --all-true /DriverStation/Enabled \ + --duration + ``` The decode scripts may create temporary Java helpers using the OS temp directory and compile them directly with the discovered WPILib JDK plus local WPILib jars. They do not edit robot source. diff --git a/.agents/skills/wpilog-decode/SKILL.md b/.agents/skills/wpilog-decode/SKILL.md index 3abd45e7..3ceb159a 100644 --- a/.agents/skills/wpilog-decode/SKILL.md +++ b/.agents/skills/wpilog-decode/SKILL.md @@ -1,9 +1,10 @@ --- + name: wpilog-decode description: "Use for WPILOG/DataLog inspection and decoding robot telemetry: listing topics, finding log windows, summarizing primitive values, decoding WPILib structs such as Pose2d/Rotation2d/Pose3d/SwerveModuleState, and exporting readable or JSON samples without running simulation." metadata: - short-description: Decode WPILOG telemetry ---- +short-description: Decode WPILOG telemetry +------------------------------------------ # WPILOG Decode @@ -19,50 +20,46 @@ metadata: - List topics: - ```sh - python3 .agents/skills/wpilog-decode/scripts/list_wpilog_topics.py \ - --repo . \ - --log \ - --filter - ``` - + ```sh + python3 .agents/skills/wpilog-decode/scripts/list_wpilog_topics.py \ + --repo . \ + --log \ + --filter + ``` - Summarize selected topics: - ```sh - python3 .agents/skills/wpilog-decode/scripts/read_wpilog_values.py \ - --repo . \ - --log \ - --topic /RealOutputs/Swerve/Odometry/Robot \ - --topic /Swerve/Module0/SteerPosition - ``` - + ```sh + python3 .agents/skills/wpilog-decode/scripts/read_wpilog_values.py \ + --repo . \ + --log \ + --topic /RealOutputs/Swerve/Odometry/Robot \ + --topic /Swerve/Module0/SteerPosition + ``` - Print JSON for scripts/comparisons: - ```sh - python3 .agents/skills/wpilog-decode/scripts/read_wpilog_values.py \ - --repo . \ - --log \ - --json \ - --samples 5 \ - --topic - ``` - + ```sh + python3 .agents/skills/wpilog-decode/scripts/read_wpilog_values.py \ + --repo . \ + --log \ + --json \ + --samples 5 \ + --topic + ``` - Find the newest sim log: - ```sh - python3 .agents/skills/wpilog-decode/scripts/find_latest_simlog.py . - ``` - + ```sh + python3 .agents/skills/wpilog-decode/scripts/find_latest_simlog.py . + ``` - Find a boolean-gated window, such as autonomous enabled: - ```sh - python3 .agents/skills/wpilog-decode/scripts/find_wpilog_window.py \ - --repo . \ - --log \ - --all-true /DriverStation/Autonomous \ - --all-true /DriverStation/Enabled \ - --duration - ``` + ```sh + python3 .agents/skills/wpilog-decode/scripts/find_wpilog_window.py \ + --repo . \ + --log \ + --all-true /DriverStation/Autonomous \ + --all-true /DriverStation/Enabled \ + --duration + ``` ## Decoded Types diff --git a/.agents/skills/wpilog-parser/SKILL.md b/.agents/skills/wpilog-parser/SKILL.md index 629808b6..22ea7219 100644 --- a/.agents/skills/wpilog-parser/SKILL.md +++ b/.agents/skills/wpilog-parser/SKILL.md @@ -1,8 +1,9 @@ --- + name: analyze-wpilog description: Analyze WPILOG log files from FRC robots using the wpilog-parser library with TypeScript. license: MIT ---- +------------ # wpilog-parser @@ -80,8 +81,8 @@ for (const record of decodeRecords(readRecords(bytes), { strict: true })) { When DriverStation logging is on, every WPILOG has these `boolean` entries: -| Entry | Meaning | -| ---------------- | ------------------------------------------------------------------- | +| Entry | Meaning | +|------------------|---------------------------------------------------------------------| | `/DS:enabled` | `true` while the robot is enabled (any mode). | | `/DS:autonomous` | `true` during autonomous. `false` means teleop (unless `/DS:test`). | | `/DS:test` | `true` during test mode. | diff --git a/WPILib-License.md b/WPILib-License.md index 645e5425..3aa24bed 100644 --- a/WPILib-License.md +++ b/WPILib-License.md @@ -3,14 +3,14 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of FIRST, WPILib, nor the names of other WPILib - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. +* Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +* Neither the name of FIRST, WPILib, nor the names of other WPILib +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY FIRST AND OTHER WPILIB CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED diff --git a/build.gradle b/build.gradle index 3e645baa..84a8ea78 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ plugins { id "java" id "edu.wpi.first.GradleRIO" version "2026.2.1" - id 'com.diffplug.spotless' version '6.12.0' + id 'com.diffplug.spotless' version '6.25.0' id "com.peterabeles.gversion" version "1.10" id "io.freefair.lombok" version "9.1.0" id "com.github.spotbugs" version "6.0.24" @@ -208,9 +208,18 @@ spotless { indentWithSpaces(2) endWithNewline() } + flexmark { + target fileTree('.') { + include '**/*.md' + exclude '**/build/**', '**/build-*/**' + } + flexmark() + trimTrailingWhitespace() + endWithNewline() + } format 'misc', { target fileTree('.') { - include '**/*.md', '**/.gitignore' + include '**/.gitignore' exclude '**/build/**', '**/build-*/**' } trimTrailingWhitespace() diff --git a/docs/dependencies/overview.md b/docs/dependencies/overview.md index 845c3afb..c0dc152c 100644 --- a/docs/dependencies/overview.md +++ b/docs/dependencies/overview.md @@ -8,13 +8,13 @@ This section walks through how each third-party library actually shows up in the Vendor JSONs live in [`vendordeps/`](../../vendordeps/) and pin the exact versions: -| Library | Version | Page | -| --- | --- | --- | -| WPILib (allwpilib + New Commands) | 2026 | [WPILib](wpilib.md) | -| CTRE Phoenix 6 | 26.3.0 | [Phoenix 6](phoenix6.md) | -| PathPlannerLib | 2026.1.2 | [PathPlanner](pathplanner.md) | -| DogLog | 2026.5.0 | [DogLog](doglog.md) | -| MapleSim (IronMaple) | 0.4.0-beta | [MapleSim](maple-sim.md) | +| Library | Version | Page | +|-----------------------------------|------------|-------------------------------| +| WPILib (allwpilib + New Commands) | 2026 | [WPILib](wpilib.md) | +| CTRE Phoenix 6 | 26.3.0 | [Phoenix 6](phoenix6.md) | +| PathPlannerLib | 2026.1.2 | [PathPlanner](pathplanner.md) | +| DogLog | 2026.5.0 | [DogLog](doglog.md) | +| MapleSim (IronMaple) | 0.4.0-beta | [MapleSim](maple-sim.md) | To bump a version, swap the JSON via WPILib VSCode's `Manage Vendor Libraries`, then `./gradlew build`. diff --git a/docs/frc-software-basics/logic-operators.md b/docs/frc-software-basics/logic-operators.md index a7e12860..63ea1d19 100644 --- a/docs/frc-software-basics/logic-operators.md +++ b/docs/frc-software-basics/logic-operators.md @@ -6,14 +6,14 @@ These compare two values and return a `boolean`. -| Operator | Meaning | -| --- | --- | -| `>` | greater than | -| `>=` | greater than or equal to | -| `<` | less than | -| `<=` | less than or equal to | -| `==` | equal to | -| `!=` | not equal to | +| Operator | Meaning | +|----------|--------------------------| +| `>` | greater than | +| `>=` | greater than or equal to | +| `<` | less than | +| `<=` | less than or equal to | +| `==` | equal to | +| `!=` | not equal to | `5 > 4` is `true`. `5 >= 6` is `false`. `5 != 5` is `false`. Those work exactly as you'd expect. diff --git a/docs/frc-software-basics/variables-arithmetic.md b/docs/frc-software-basics/variables-arithmetic.md index e1687cab..566faf66 100644 --- a/docs/frc-software-basics/variables-arithmetic.md +++ b/docs/frc-software-basics/variables-arithmetic.md @@ -22,13 +22,13 @@ int a = 3; // same problem The types you'll encounter most often in this codebase: -| Type | What it holds | Example | -| --- | --- | --- | -| `int` | whole numbers | `int canID = 8;` | -| `double` | decimal numbers | `double idlingRPM = 700;` | -| `boolean` | `true` or `false` | `boolean isAttached = true;` | -| `String` | text (not technically primitive, but used everywhere) | `String name = "IndexerBed";` | -| `byte` | small signed integer, −128 to 127 | rare in robot code | +| Type | What it holds | Example | +|-----------|-------------------------------------------------------|-------------------------------| +| `int` | whole numbers | `int canID = 8;` | +| `double` | decimal numbers | `double idlingRPM = 700;` | +| `boolean` | `true` or `false` | `boolean isAttached = true;` | +| `String` | text (not technically primitive, but used everywhere) | `String name = "IndexerBed";` | +| `byte` | small signed integer, −128 to 127 | rare in robot code | You'll also see `final` (the value can't be reassigned) and `static` (belongs to the class rather than a specific instance) used as modifiers. Both are covered in [Classes, Methods, and Objects](classes-methods-objects.md). @@ -46,13 +46,13 @@ All `double`s because RPM values have decimal precision. Changing them to `int` These require two operands — one on each side. -| Operator | Meaning | Example | -| --- | --- | --- | -| `+` | addition | `a + b` | -| `-` | subtraction | `a - b` | -| `*` | multiplication | `a * b` | -| `/` | division | `a / b` | -| `%` | modulus (remainder) | `a % b` | +| Operator | Meaning | Example | +|----------|---------------------|---------| +| `+` | addition | `a + b` | +| `-` | subtraction | `a - b` | +| `*` | multiplication | `a * b` | +| `/` | division | `a / b` | +| `%` | modulus (remainder) | `a % b` | A quick demonstration with concrete values: diff --git a/docs/other-guides/2026-season-specific.md b/docs/other-guides/2026-season-specific.md index bfc4d6c8..852feb8b 100644 --- a/docs/other-guides/2026-season-specific.md +++ b/docs/other-guides/2026-season-specific.md @@ -20,13 +20,13 @@ The full structural conventions live in [Class Generation](../coding-conventions We build multiple physical robots each season and run the same code on all of them. The `Rio.id` field, looked up from the RoboRIO serial number in `frc.spectrumLib.hardware.Rio`, decides which configuration is loaded at startup. All configs live under `src/main/java/frc/robot/configs`: -| Config | Bot | Use | -| --- | --- | --- | -| `FM2026` | Final Machine — the competition robot | Precise calibration, the bot we travel with. | -| `PM2026` | Practice Machine | Mirrors competition, minor wear-and-tear tweaks. | -| `XM2026` | Experimental Machine | In-season experimentation and prototyping. Encoder offsets and attachment flags vary. (Off-season work gets its own `OM` config.) | -| `AM2026` | Alpha Machine | Earlier prototype, used pre-build. | -| `PHOTON2026` | Photon's machine | The robot run by Photon, our sister team. | +| Config | Bot | Use | +|--------------|---------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------| +| `FM2026` | Final Machine — the competition robot | Precise calibration, the bot we travel with. | +| `PM2026` | Practice Machine | Mirrors competition, minor wear-and-tear tweaks. | +| `XM2026` | Experimental Machine | In-season experimentation and prototyping. Encoder offsets and attachment flags vary. (Off-season work gets its own `OM` config.) | +| `AM2026` | Alpha Machine | Earlier prototype, used pre-build. | +| `PHOTON2026` | Photon's machine | The robot run by Photon, our sister team. | Each config can mark a mechanism present or absent via `setAttached(boolean)` so a bot without the launcher doesn't try to initialize one. @@ -44,20 +44,20 @@ Swerve odometry and Limelight MegaTag readings feed a WPILib `SwerveDrivePoseEst These are the entries in `SuperStructure.WantedSuperState`, applied by `setWantedSuperState(...)`. Each one drives a coordinated setup across launcher, hood, fuel intake, indexer bed/tower, and intake extension. -| State | What it does | -| --- | --- | -| `IDLE` | Ready, neutral. Subsystems home. | -| `INTAKE_FUEL` | Active fuel collection — intake runs, bed indexes, extension extends. | -| `TRACK_TARGET` | Launcher + hood aim while the robot is free to drive. | -| `LAUNCH_WITH_SQUEEZE` | Aim + launch with the delayed-close "squeeze" sequence. | -| `LAUNCH_WITH_SQUEEZE_WITH_NO_DELAY` | Squeeze launch without the delayed close. | -| `LAUNCH_WITHOUT_SQUEEZE` | Aim + launch while the intake stays extended. | -| `LAUNCH_WITH_BRAKE` | Launch while holding the drivetrain in brake. | -| `AUTON_TRACK_TARGET` | Auton-mode aim. | -| `AUTON_INTAKE_FUEL` | Auton-mode fuel collection. | -| `UNJAM` | Clear jammed fuel from intake or indexer. | -| `EJECT` | Spit fuel back out. | -| `FORCE_HOME` | Drive every mechanism to its home position. | +| State | What it does | +|-------------------------------------|-----------------------------------------------------------------------| +| `IDLE` | Ready, neutral. Subsystems home. | +| `INTAKE_FUEL` | Active fuel collection — intake runs, bed indexes, extension extends. | +| `TRACK_TARGET` | Launcher + hood aim while the robot is free to drive. | +| `LAUNCH_WITH_SQUEEZE` | Aim + launch with the delayed-close "squeeze" sequence. | +| `LAUNCH_WITH_SQUEEZE_WITH_NO_DELAY` | Squeeze launch without the delayed close. | +| `LAUNCH_WITHOUT_SQUEEZE` | Aim + launch while the intake stays extended. | +| `LAUNCH_WITH_BRAKE` | Launch while holding the drivetrain in brake. | +| `AUTON_TRACK_TARGET` | Auton-mode aim. | +| `AUTON_INTAKE_FUEL` | Auton-mode fuel collection. | +| `UNJAM` | Clear jammed fuel from intake or indexer. | +| `EJECT` | Spit fuel back out. | +| `FORCE_HOME` | Drive every mechanism to its home position. | `CurrentSuperState` mirrors these — `handleStateTransition()` maps the wanted state to the current one each loop. diff --git a/docs/other-guides/shortcuts.md b/docs/other-guides/shortcuts.md index d29eafaa..cd3b02ef 100644 --- a/docs/other-guides/shortcuts.md +++ b/docs/other-guides/shortcuts.md @@ -6,33 +6,33 @@ A reference for the shortcuts and commands that come up often. If you're new, th ## VS Code -| Shortcut | What it does | -| --- | --- | -| `Tab` | Accept an inline Copilot suggestion. | -| `Ctrl+Right Arrow` | Accept the next word of a suggestion. | -| `F2` | Rename — renames all references to a variable, method, or class across the project. Use this instead of find-and-replace; it's scope-aware. | -| `Ctrl+/` | Toggle line comment on the selected text. | -| `Ctrl+Click` or `F12` | Go to definition — jumps to where a method or class is declared. | -| `Alt+Shift+F12` | Find all references — shows every call site for a symbol. | -| `Ctrl+P` | Quick open — fuzzy-search files by name. Faster than the Explorer for navigating a codebase. | -| `Ctrl+Shift+P` | Command Palette — run any VS Code or WPILib command by name. This is how you launch sim, clean the workspace, or deploy. | -| `Ctrl+`` ` `` ` | Toggle the integrated terminal. | -| `Ctrl+Shift+V` | Preview Markdown in a side panel — useful when editing docs. | -| `Shift+Alt+Down` | Duplicate the current line or selected block. | +| Shortcut | What it does | +|-----------------------|---------------------------------------------------------------------------------------------------------------------------------------------| +| `Tab` | Accept an inline Copilot suggestion. | +| `Ctrl+Right Arrow` | Accept the next word of a suggestion. | +| `F2` | Rename — renames all references to a variable, method, or class across the project. Use this instead of find-and-replace; it's scope-aware. | +| `Ctrl+/` | Toggle line comment on the selected text. | +| `Ctrl+Click` or `F12` | Go to definition — jumps to where a method or class is declared. | +| `Alt+Shift+F12` | Find all references — shows every call site for a symbol. | +| `Ctrl+P` | Quick open — fuzzy-search files by name. Faster than the Explorer for navigating a codebase. | +| `Ctrl+Shift+P` | Command Palette — run any VS Code or WPILib command by name. This is how you launch sim, clean the workspace, or deploy. | +| `Ctrl+`` ` `` ` | Toggle the integrated terminal. | +| `Ctrl+Shift+V` | Preview Markdown in a side panel — useful when editing docs. | +| `Shift+Alt+Down` | Duplicate the current line or selected block. | ## Multi-Cursor Editing Multi-cursor is one of the highest-value things to learn in VS Code. It lets you edit several places at once without regex. -| Shortcut | What it does | -| --- | --- | -| `Ctrl+D` | Select the next occurrence of the highlighted text and add a cursor there. Keep pressing to select more. | -| `Ctrl+U` | Undo the last `Ctrl+D` (deselect the most recently added cursor). | -| `Ctrl+Shift+L` | Select all occurrences of the highlighted text at once. | -| `Ctrl+Alt+Up/Down` | Add a cursor above or below the current line. | -| `Alt+Click` | Place a cursor at any clicked location. | -| `Middle Click + Drag` | Column select — places cursors on every line you drag across. | -| `Alt+Shift+Arrow Keys` | Expand or shrink the selection by word, line, or block. | +| Shortcut | What it does | +|------------------------|----------------------------------------------------------------------------------------------------------| +| `Ctrl+D` | Select the next occurrence of the highlighted text and add a cursor there. Keep pressing to select more. | +| `Ctrl+U` | Undo the last `Ctrl+D` (deselect the most recently added cursor). | +| `Ctrl+Shift+L` | Select all occurrences of the highlighted text at once. | +| `Ctrl+Alt+Up/Down` | Add a cursor above or below the current line. | +| `Alt+Click` | Place a cursor at any clicked location. | +| `Middle Click + Drag` | Column select — places cursors on every line you drag across. | +| `Alt+Shift+Arrow Keys` | Expand or shrink the selection by word, line, or block. | A common use: highlight `public`, then `Ctrl+Shift+L` to select every instance in a file, type `private` and you've renamed them all at once. @@ -40,13 +40,13 @@ A common use: highlight `public`, then `Ctrl+Shift+L` to select every instance i These are all available through `Ctrl+Shift+P`. The most useful ones: -| Command | What it does | -| --- | --- | -| `WPILib: Simulate Robot Code` | Build and launch the simulator. Equivalent to `./gradlew simulateJava`. | -| `WPILib: Deploy Robot Code` | Build and deploy to a connected RoboRIO. Equivalent to `./gradlew deploy`. | -| `WPILib: Build Robot Code` | Compile without deploying. Equivalent to `./gradlew build`. | +| Command | What it does | +|-----------------------------------------|----------------------------------------------------------------------------------------| +| `WPILib: Simulate Robot Code` | Build and launch the simulator. Equivalent to `./gradlew simulateJava`. | +| `WPILib: Deploy Robot Code` | Build and deploy to a connected RoboRIO. Equivalent to `./gradlew deploy`. | +| `WPILib: Build Robot Code` | Compile without deploying. Equivalent to `./gradlew build`. | | `Java: Clean Language Server Workspace` | Clear the Java language server cache. Use when IntelliSense is showing phantom errors. | -| `WPILib: Manage Vendor Libraries` | Add or update vendordep libraries (Phoenix 6, PathPlanner, etc.). | +| `WPILib: Manage Vendor Libraries` | Add or update vendordep libraries (Phoenix 6, PathPlanner, etc.). | Keyboard shortcuts for simulation and deploy (`F5`, `Shift+F5`) can be set up in VS Code's keybinding editor, but the Command Palette is reliable across any machine. diff --git a/docs/tools/auton.md b/docs/tools/auton.md index 226a5b75..9ea28706 100644 --- a/docs/tools/auton.md +++ b/docs/tools/auton.md @@ -18,12 +18,12 @@ Most of the routine logic lives in one file: [`frc.robot.auton.Auton`](../../src Every entry in the chooser is just a sequence of `SpectrumAuton(pathName, mirrored)` calls glued together with `launch()`. The naming pattern is `` where each letter is a goal column (T/B/D). `TBTB`, for example, runs Top → Bottom → Top → Bottom. Each routine has a Left and Right variant — `mirrored = true` flips poses across the field's midline so the same `.auto` file works from both starting positions. -| Group | Entries | Notes | -| --- | --- | --- | -| Headliners | `TBTB`, `TBTT`, `TTTT`, `BBBB` | Four-shot routines, all chained `SpectrumAuton + launch` | -| Optional | `Option TBT`, `Option BBB` | Insert an `OPTIONAL_DELAY` (1.0 s) after the first segment — used when a partner needs the lane to clear | -| 2nd Man | `2nd-TBTB`, `2nd-BBD` | Begin with `SECOND_MAN_DELAY` (1.0 s) so we're not in the way of an ally's first move | -| Fallback | `Do Nothing` | Default chooser entry — never let a missing selection mean an unscheduled robot | +| Group | Entries | Notes | +|------------|--------------------------------|----------------------------------------------------------------------------------------------------------| +| Headliners | `TBTB`, `TBTT`, `TTTT`, `BBBB` | Four-shot routines, all chained `SpectrumAuton + launch` | +| Optional | `Option TBT`, `Option BBB` | Insert an `OPTIONAL_DELAY` (1.0 s) after the first segment — used when a partner needs the lane to clear | +| 2nd Man | `2nd-TBTB`, `2nd-BBD` | Begin with `SECOND_MAN_DELAY` (1.0 s) so we're not in the way of an ally's first move | +| Fallback | `Do Nothing` | Default chooser entry — never let a missing selection mean an unscheduled robot | The `withName(...)` suffix `" - Left"` / `" - Right"` is significant: the field visualizer parses the suffix to decide whether to mirror the rendered pose. Don't drop it. diff --git a/docs/tools/gradle.md b/docs/tools/gradle.md index 1a38e3b4..21400171 100644 --- a/docs/tools/gradle.md +++ b/docs/tools/gradle.md @@ -8,18 +8,18 @@ The version is pinned in `gradle/wrapper/gradle-wrapper.properties`, and `./grad ## The Commands You'll Actually Run -| Command | What it does | -| --- | --- | -| `./gradlew build` | Compile, run Spotless, run SpotBugs, run tests, produce the deployable jar. | -| `./gradlew clean` | Delete `build/` so the next build is from scratch. | -| `./gradlew clean build` | Both of the above, useful when something stale is causing weird errors. | -| `./gradlew deploy` | Build and deploy to the connected roboRIO. Team number comes from `.wpilib/wpilib_preferences.json`. | -| `./gradlew simulateJava` | Launch the WPILib GUI simulator. (The VSCode `WPILib: Simulate Robot Code` command is usually faster.) | -| `./gradlew javadoc` | Generate JavaDoc HTML into `build/docs/javadoc/`. | +| Command | What it does | +|---------------------------|-------------------------------------------------------------------------------------------------------------------------| +| `./gradlew build` | Compile, run Spotless, run SpotBugs, run tests, produce the deployable jar. | +| `./gradlew clean` | Delete `build/` so the next build is from scratch. | +| `./gradlew clean build` | Both of the above, useful when something stale is causing weird errors. | +| `./gradlew deploy` | Build and deploy to the connected roboRIO. Team number comes from `.wpilib/wpilib_preferences.json`. | +| `./gradlew simulateJava` | Launch the WPILib GUI simulator. (The VSCode `WPILib: Simulate Robot Code` command is usually faster.) | +| `./gradlew javadoc` | Generate JavaDoc HTML into `build/docs/javadoc/`. | | `./gradlew spotlessApply` | Apply the AOSP code style across every `.java`, `.gradle`, `.xml`, and `.md` file. Runs automatically on `compileJava`. | -| `./gradlew spotlessCheck` | Verify formatting without rewriting — what CI runs. | -| `./gradlew spotbugsMain` | Run SpotBugs static analysis. The HTML report lands at `build/reports/spotbugs.html`. | -| `./gradlew tasks` | List every task, including ones not documented here. | +| `./gradlew spotlessCheck` | Verify formatting without rewriting — what CI runs. | +| `./gradlew spotbugsMain` | Run SpotBugs static analysis. The HTML report lands at `build/reports/spotbugs.html`. | +| `./gradlew tasks` | List every task, including ones not documented here. | You can chain them. `./gradlew clean build deploy` will clean, build, and deploy in one go. diff --git a/docs/tools/leds.md b/docs/tools/leds.md index 6c570937..5893c72c 100644 --- a/docs/tools/leds.md +++ b/docs/tools/leds.md @@ -18,20 +18,20 @@ The constructor takes a `Config` either by device id + LED count (it owns the CA `SpectrumLEDs` ships with pattern factories that return `CANdlePattern` objects (some backed by hardware CANdle animations, some by per-LED color writes): -| Method | What you get | -| --- | --- | -| `solid(color)` | A static color. | -| `blink(color, onTime)` | On for `onTime` seconds, off for the same. | -| `breathe(color, period)` | Smooth fade in/out across `period` seconds. | -| `rainbow()` / `scrollingRainbow()` | Full rainbow, optionally scrolling at 0.25 m/s along the strip. | -| `gradient(colors...)` | Continuous gradient between an arbitrary number of colors. | -| `stripe(percent, c1, c2)` | First `percent` of strip in `c1`, rest in `c2`. | -| `chase(color, percent, speed)` | A moving block of `color` covering `percent` of the strip, scrolling at `speed` Hz. | -| `bounce(color, duration)` | A lit cell with two trails of dimmer color bouncing across the strip. | +| Method | What you get | +|------------------------------------------------|-----------------------------------------------------------------------------------------| +| `solid(color)` | A static color. | +| `blink(color, onTime)` | On for `onTime` seconds, off for the same. | +| `breathe(color, period)` | Smooth fade in/out across `period` seconds. | +| `rainbow()` / `scrollingRainbow()` | Full rainbow, optionally scrolling at 0.25 m/s along the strip. | +| `gradient(colors...)` | Continuous gradient between an arbitrary number of colors. | +| `stripe(percent, c1, c2)` | First `percent` of strip in `c1`, rest in `c2`. | +| `chase(color, percent, speed)` | A moving block of `color` covering `percent` of the strip, scrolling at `speed` Hz. | +| `bounce(color, duration)` | A lit cell with two trails of dimmer color bouncing across the strip. | | `ombre(start, end)` / `wave(c1, c2, len, dur)` | Color transitions implemented inline because WPILib's built-ins don't quite cover them. | -| `countdown(startSupplier, duration)` | Strip starts full, turns off back-to-front over `duration`, color fades yellow → red. | -| `switchCountdown(startColor)` | 2026-specific: alliance-shift countdown that flips between alliance colors and purple. | -| `edges(color, length)` | `length` LEDs lit at each end, rest off. | +| `countdown(startSupplier, duration)` | Strip starts full, turns off back-to-front over `duration`, color fades yellow → red. | +| `switchCountdown(startColor)` | 2026-specific: alliance-shift countdown that flips between alliance colors and purple. | +| `edges(color, length)` | `length` LEDs lit at each end, rest off. | Hardware-animation patterns (blink, breathe, rainbow) are driven by the CANdle's own animation engine via Phoenix 6 controls (`StrobeAnimation`, `SingleFadeAnimation`, `RainbowAnimation`, …); the color/gradient patterns are written per-LED each loop. diff --git a/docs/tools/pid-tuning.md b/docs/tools/pid-tuning.md index 6d1b3aa5..2a6a1314 100644 --- a/docs/tools/pid-tuning.md +++ b/docs/tools/pid-tuning.md @@ -34,8 +34,8 @@ The pieces in motion: We run PID *on the motor controller*, not on the roboRIO. Phoenix 6 TalonFX motors do this natively, with up to three gain slots (`Slot0`, `Slot1`, `Slot2`). The [`Mechanism`](../../src/main/java/frc/spectrumLib/mechanism/Mechanism.java) wrapper exposes helpers for setting gains per slot (defaults to Slot 0): - mechanism.config.configPIDGains(kP, kI, kD); // slot 0 - mechanism.config.configPIDGains(slot, kP, kI, kD); // pick a slot (0/1/2) + mechanism.config.configPIDGains(kP, kI, kD); // slot 0 + mechanism.config.configPIDGains(slot, kP, kI, kD); // pick a slot (0/1/2) Defaults for each mechanism live in its inner `*Config` class (`LauncherConfig`, `HoodConfig`, etc.). To override per-robot, mutate them inside the matching `*2026.java` config before the subsystem is constructed. diff --git a/docs/tools/simulation.md b/docs/tools/simulation.md index e3a3cadd..2f88dabe 100644 --- a/docs/tools/simulation.md +++ b/docs/tools/simulation.md @@ -18,10 +18,10 @@ Both routes have `wpi.sim.addGui().defaultEnabled = true` and `wpi.sim.addDriver The pattern from existing subsystems: instantiate a `frc.spectrumLib.sim.ArmSim` / `LinearSim` / `RollerSim` in the subsystem's constructor, route it to update its angle/position/velocity from the motor's `getSimState()`, and append it onto `RobotSim.leftView`. The sim classes do the math to map motor rotations into the visualization. -| Helper | What it draws | -| --- | --- | -| `ArmSim` | A pivoting ligament — hood, shooter pivot, arm. | -| `LinearSim` | A telescoping/sliding ligament — elevator, intake extension. | +| Helper | What it draws | +|-------------|----------------------------------------------------------------------------------------------------------| +| `ArmSim` | A pivoting ligament — hood, shooter pivot, arm. | +| `LinearSim` | A telescoping/sliding ligament — elevator, intake extension. | | `RollerSim` | A spinning indicator with direction + relative speed — intake roller, indexer wheels, launcher flywheel. | These came from Team 604's sample project and were adapted; the principle of "always move the root/origin to change display position" (commented at the top of `RobotSim.java`) is the most useful thing to remember. diff --git a/docs/tools/vision.md b/docs/tools/vision.md index 7f597659..d033229f 100644 --- a/docs/tools/vision.md +++ b/docs/tools/vision.md @@ -8,11 +8,11 @@ The robot uses three Limelights for AprilTag-based pose estimation. Each one pub Three [Limelight 4](https://limelightvision.io)s, named for where they sit on the bot: -| Limelight | NT name | Notes | -| --- | --- | --- | -| Back | `limelight-back` | Wide rear view, mounted high. | -| Left | `limelight-left` | Side view for tags at oblique angles. | -| Right | `limelight-right` | Mirror of left. | +| Limelight | NT name | Notes | +|-----------|-------------------|---------------------------------------| +| Back | `limelight-back` | Wide rear view, mounted high. | +| Left | `limelight-left` | Side view for tags at oblique angles. | +| Right | `limelight-right` | Mirror of left. | The 3D mounting transforms are in [`Vision.VisionConfig`](../../src/main/java/frc/robot/subsystems/vision/Vision.java) — `withTranslation(x, y, z)` is robot-frame meters, `withRotation(roll, pitch, yaw)` is degrees. Update these when CAD changes; the MegaTag pose math is only as good as the camera-to-robot transform you give it. @@ -43,13 +43,13 @@ Each estimate goes through `getMT1VisionEstimate(...)` or `getMT2VisionEstimate( If a measurement survives, it's tagged with standard deviations based on confidence. The full ladder lives in the source, but the shape is: -| Situation | xy std | θ std (MT1) | -| --- | --- | --- | -| Stationary + large target | 0.1 m | 0.1 rad | -| Multi-tag + large target | 0.1 m | 0.1 rad | -| Multi-tag + medium target | 0.25 m | 8 rad | -| Close, large target | 0.5 m | huge (don't fuse) | -| Stable, low ambiguity | 1.5 m | huge | +| Situation | xy std | θ std (MT1) | +|---------------------------|--------|-------------------| +| Stationary + large target | 0.1 m | 0.1 rad | +| Multi-tag + large target | 0.1 m | 0.1 rad | +| Multi-tag + medium target | 0.25 m | 8 rad | +| Close, large target | 0.5 m | huge (don't fuse) | +| Stable, low ambiguity | 1.5 m | huge | `integrateSingleEstimate(...)` then calls `swerve.addVisionMeasurement(pose, timestamp, stdDevs)`. The pose estimator weighs that against odometry by the inverse of the stds — small std means "trust this a lot." diff --git a/src/main/java/frc/spectrumLib/README.md b/src/main/java/frc/spectrumLib/README.md index 51c305c8..7d2bad42 100644 --- a/src/main/java/frc/spectrumLib/README.md +++ b/src/main/java/frc/spectrumLib/README.md @@ -25,61 +25,66 @@ frc.spectrumLib ## Packages ### `framework` + Core structural interfaces and base classes. -| Class | Description | -|-------|-------------| +| Class | Description | +|-----------------|-----------------------------------------------------------------------------------------------------------------| | `SpectrumRobot` | Extends `TimedRobot`; silences joystick connection warnings and extends loop overrun watchdog timeout to 200 ms | | `SpectrumState` | Named boolean state backed by a WPILib `Trigger`; supports timed, toggled, and command-driven state transitions | --- ### `hardware` + Low-level hardware wrappers and robot identity constants. -| Class | Description | -|-------|-------------| -| `Rio` | Enum mapping RoboRIO serial numbers to robot identities; exposes `Rio.CANIVORE` and `Rio.RIO_CANBUS` bus name constants | -| `SpectrumCANcoder` | Configures a CANcoder and wires it into a `TalonFX` as Remote, Fused, or Sync feedback | -| `SpectrumCANcoderConfig` | Configuration holder for CANcoder offset, gear ratios, inversion, and attachment flag | -| `SpectrumServo` | PWM servo wrapper that also implements `Subsystem` | -| `TalonFXFactory` | Factory for creating `TalonFX` instances with consistent default configuration | +| Class | Description | +|--------------------------|-------------------------------------------------------------------------------------------------------------------------| +| `Rio` | Enum mapping RoboRIO serial numbers to robot identities; exposes `Rio.CANIVORE` and `Rio.RIO_CANBUS` bus name constants | +| `SpectrumCANcoder` | Configures a CANcoder and wires it into a `TalonFX` as Remote, Fused, or Sync feedback | +| `SpectrumCANcoderConfig` | Configuration holder for CANcoder offset, gear ratios, inversion, and attachment flag | +| `SpectrumServo` | PWM servo wrapper that also implements `Subsystem` | +| `TalonFXFactory` | Factory for creating `TalonFX` instances with consistent default configuration | --- ### `telemetry` + Logging, alerts, and runtime-tunable values. -| Class | Description | -|-------|-------------| -| `Telemetry` | DogLog-based logging system; provides `log()`, `print()`, and alert monitoring | +| Class | Description | +|-----------------|-------------------------------------------------------------------------------------------| +| `Telemetry` | DogLog-based logging system; provides `log()`, `print()`, and alert monitoring | | `BatteryLogger` | Accumulates per-subsystem current/power/energy each loop and logs totals via `logPower()` | -| `TuneValue` | SmartDashboard-backed tunable `double` for in-match parameter adjustment | +| `TuneValue` | SmartDashboard-backed tunable `double` for in-match parameter adjustment | --- ### `util` + General-purpose utilities, math, and data structures. -| Class | Description | -|-------|-------------| -| `CachedDouble` | Wraps a `DoubleSupplier` and caches its value once per scheduler iteration | -| `CanDeviceId` | Typed CAN device identifier (device number + bus name) | -| `Conversions` | Unit conversion helpers (rotations ↔ inches, RPM ↔ RPS, etc.) | -| `CrashTracker` | Logs uncaught exceptions to a file on the RIO for post-match debugging | -| `Curve` / `ExpCurve` | Exponential input curve with deadband and scalar for joystick shaping | -| `Network` | NetworkTables helper utilities | -| `Trio` | Generic three-element tuple | -| `Util` | Miscellaneous utilities; exposes `Util.teleop`, `Util.autoMode`, `Util.disabled` triggers | -| `exceptions/KillRobotException` | Thrown to trigger a controlled robot shutdown on fatal errors | +| Class | Description | +|---------------------------------|-------------------------------------------------------------------------------------------| +| `CachedDouble` | Wraps a `DoubleSupplier` and caches its value once per scheduler iteration | +| `CanDeviceId` | Typed CAN device identifier (device number + bus name) | +| `Conversions` | Unit conversion helpers (rotations ↔ inches, RPM ↔ RPS, etc.) | +| `CrashTracker` | Logs uncaught exceptions to a file on the RIO for post-match debugging | +| `Curve` / `ExpCurve` | Exponential input curve with deadband and scalar for joystick shaping | +| `Network` | NetworkTables helper utilities | +| `Trio` | Generic three-element tuple | +| `Util` | Miscellaneous utilities; exposes `Util.teleop`, `Util.autoMode`, `Util.disabled` triggers | +| `exceptions/KillRobotException` | Thrown to trigger a controlled robot shutdown on fatal errors | --- ### `mechanism` + Abstract base class for all TalonFX-driven mechanisms. -| Class | Description | -|-------|-------------| +| Class | Description | +|-------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `Mechanism` | Manages motor construction, follower configuration, control requests (voltage, velocity, motion magic, torque-FOC), sensor reads, soft limits, current limits, and simulation hooks. All hardware access is gated by `isAttached()`. | Extend `Mechanism` and call its protected setters from command `execute()` bodies. Inner class `Mechanism.Config` holds all TalonFX configuration and PID/FF gains. @@ -87,19 +92,21 @@ Extend `Mechanism` and call its protected setters from command `execute()` bodie --- ### `gamepads` + Xbox controller abstraction. -| Class | Description | -|-------|-------------| +| Class | Description | +|-----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `Gamepad` | Abstract class wrapping `CommandXboxController`; provides deadbanded/curved axis reads, bumper/trigger modifier combos, stick direction helpers, alliance-aware cardinals, and a `rumbleCommand()` factory | --- ### `leds` + CTRE CANdle LED subsystem with a pattern library. -| Class | Description | -|-------|-------------| +| Class | Description | +|----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `SpectrumLEDs` | Manages a shared CTRE CANdle with non-overlapping `startIdx`/`numLeds` ranges per instance; provides `solid()`, `blink()`, `breathe()`, `rainbow()`, `scrollingRainbow()`, `chase()`, `bounce()`, `fire()`, `rgbCycle()`, `stripe()`, `gradient()`, `edges()`, `ombre()`, `wave()`, `countdown()`, and `switchCountdown()` pattern factories | Supports multiple LED zones on a single CANdle and a priority system to prevent low-priority commands from overriding higher-priority ones. @@ -107,36 +114,39 @@ Supports multiple LED zones on a single CANdle and a priority system to prevent --- ### `sim` + Mechanism2d simulation helpers for visualizing robot mechanisms in DriverStation. -| Class | Description | -|-------|-------------| -| `ArmSim` / `ArmConfig` | Simulates a rotating arm | -| `RollerSim` / `RollerConfig` | Simulates a spinning roller/wheel | -| `LinearSim` / `LinearConfig` | Simulates a linear extension | -| `Mount` / `Mountable` | Attachment point system for mounting sims onto other sims | -| `Circle` | Utility for drawing circular shapes in Mechanism2d | +| Class | Description | +|------------------------------|-----------------------------------------------------------| +| `ArmSim` / `ArmConfig` | Simulates a rotating arm | +| `RollerSim` / `RollerConfig` | Simulates a spinning roller/wheel | +| `LinearSim` / `LinearConfig` | Simulates a linear extension | +| `Mount` / `Mountable` | Attachment point system for mounting sims onto other sims | +| `Circle` | Utility for drawing circular shapes in Mechanism2d | --- ### `swerve` + Swerve-specific utilities. -| Class | Description | -|-------|-------------| -| `MapleSimSwerveDrivetrain` | Maple-Sim simulation bridge for CTRE swerve | -| `SysID` | SysID characterization routine wrapper (translation, rotation, steer) | +| Class | Description | +|----------------------------|-----------------------------------------------------------------------| +| `MapleSimSwerveDrivetrain` | Maple-Sim simulation bridge for CTRE swerve | +| `SysID` | SysID characterization routine wrapper (translation, rotation, steer) | --- ### `vision` + Limelight vision utilities. -| Class | Description | -|-------|-------------| -| `Limelight` | Wrapper around `LimelightHelpers` with null-safe MegaTag1/MegaTag2 pose access, tag-count queries, and distance estimation | -| `LimelightHelpers` | Vendored Limelight utility library | -| `VisionLogger` | Logs vision pose estimates and tag data to telemetry | +| Class | Description | +|--------------------|----------------------------------------------------------------------------------------------------------------------------| +| `Limelight` | Wrapper around `LimelightHelpers` with null-safe MegaTag1/MegaTag2 pose access, tag-count queries, and distance estimation | +| `LimelightHelpers` | Vendored Limelight utility library | +| `VisionLogger` | Logs vision pose estimates and tag data to telemetry | --- From c40ca2c754b4fe912480c401591ebfc01ccb2f13 Mon Sep 17 00:00:00 2001 From: project516 <138796702+Project516@users.noreply.github.com> Date: Fri, 7 Aug 2026 09:29:42 -0500 Subject: [PATCH 3/3] Fix CodeRabbit review findings and preserve SKILL.md frontmatter - Restore standalone YAML frontmatter in all SKILL.md files (the Spotless flexmark pass in 4e8928c had expanded closing --- fences to long dashes, dropped folded description > indentation, and unindented metadata children). - Exclude .agents/skills/**/SKILL.md from the flexmark target so ./gradlew build no longer rewrites their YAML frontmatter. - Fix Telemetry package path in AGENTS.md (frc.spectrumLib.telemetry.Telemetry). - Add source/date provenance notes for skill policy and fork facts. --- .../skills/advantagekit-replay/SKILL.md.disabled | 2 ++ .agents/skills/advantagescope/SKILL.md | 7 ++++--- .agents/skills/coderabbitai-review/SKILL.md | 3 +-- .agents/skills/frc-code-review/SKILL.md | 11 +++++------ .agents/skills/frc-vision/SKILL.md | 15 +++++++-------- .agents/skills/live-robot-telemetry/SKILL.md | 5 ++--- .agents/skills/maple-sim/SKILL.md | 5 ++--- .agents/skills/wpilib-best-practices/SKILL.md | 11 +++++------ .agents/skills/wpilib-sim/SKILL.md | 5 ++--- .agents/skills/wpilog-decode/SKILL.md | 5 ++--- .agents/skills/wpilog-parser/SKILL.md | 3 +-- AGENTS.md | 4 ++-- build.gradle | 7 ++++++- 13 files changed, 41 insertions(+), 42 deletions(-) diff --git a/.agents/skills/advantagekit-replay/SKILL.md.disabled b/.agents/skills/advantagekit-replay/SKILL.md.disabled index 8b4c7ca2..81b969ba 100644 --- a/.agents/skills/advantagekit-replay/SKILL.md.disabled +++ b/.agents/skills/advantagekit-replay/SKILL.md.disabled @@ -5,6 +5,8 @@ description: "Use for AdvantageKit WPILOG replay workflows: pulling real robot l # AdvantageKit Replay +> Disabled for Spectrum 3847 — we do not use AdvantageKit (see `AGENTS.md`). Retained for reference from the original upstream/8044 workflow; verified 2026-08-07. + ## Core Rules - Use this skill when validating that real-robot AdvantageKit outputs can be disabled and regenerated from a WPILOG replay. diff --git a/.agents/skills/advantagescope/SKILL.md b/.agents/skills/advantagescope/SKILL.md index 8f82eca7..ffa3ab8f 100644 --- a/.agents/skills/advantagescope/SKILL.md +++ b/.agents/skills/advantagescope/SKILL.md @@ -1,13 +1,14 @@ --- - name: advantagescope description: "Use for AdvantageScope visualization automation: building/running our AdvantageScope fork (Spectrum 3847) or vanilla AdvantageScope, opening WPILOGs/DataLogs with layouts, using opt-in agent control/export hooks, capturing 2D/3D field screenshots or frame sequences, and falling back to vanilla AdvantageScope/manual inspection when hooks are unavailable." metadata: -short-description: Automate AdvantageScope visualization --------------------------------------------------------- + short-description: Automate AdvantageScope visualization +--- # AdvantageScope +> We maintain our own AdvantageScope fork; these workflow facts were verified against the Spectrum fork and robot repo 2026-08-07 (PR #132). + ## Core Rules - This skill is the robot-repo consumer workflow for AdvantageScope visualization. It should help agents discover robot logs/assets, generate layouts, locate our AdvantageScope fork or vanilla AdvantageScope, and export previews. diff --git a/.agents/skills/coderabbitai-review/SKILL.md b/.agents/skills/coderabbitai-review/SKILL.md index 61754576..f3c3d8fe 100644 --- a/.agents/skills/coderabbitai-review/SKILL.md +++ b/.agents/skills/coderabbitai-review/SKILL.md @@ -1,9 +1,8 @@ --- - name: coderabbitai-review description: Review an open PR with CodeRabbit — triage its comments, fix valid issues, push, and loop until the review approves. Use when a PR on this repo has a CodeRabbit review pending or needs one. license: MIT ------------- +--- # CodeRabbit PR Review Loop diff --git a/.agents/skills/frc-code-review/SKILL.md b/.agents/skills/frc-code-review/SKILL.md index 86df21dd..8e634866 100644 --- a/.agents/skills/frc-code-review/SKILL.md +++ b/.agents/skills/frc-code-review/SKILL.md @@ -1,12 +1,11 @@ --- - name: frc-code-review description: > -Structured code review for FRC robot Java code. Use when asked to review, audit, or critique robot -code, or when checking code before competition. Covers safety, WPILib best practices, performance, -robustness, and competition readiness. Triggers on: "review my robot code", "check this subsystem", -"is this code competition-ready", or "what's wrong with this command". ----------------------------------------------------------------------- + Structured code review for FRC robot Java code. Use when asked to review, audit, or critique robot + code, or when checking code before competition. Covers safety, WPILib best practices, performance, + robustness, and competition readiness. Triggers on: "review my robot code", "check this subsystem", + "is this code competition-ready", or "what's wrong with this command". +--- # FRC Code Review diff --git a/.agents/skills/frc-vision/SKILL.md b/.agents/skills/frc-vision/SKILL.md index 635c40d1..cc3754db 100644 --- a/.agents/skills/frc-vision/SKILL.md +++ b/.agents/skills/frc-vision/SKILL.md @@ -1,15 +1,14 @@ --- - name: frc-vision description: > -Spectrum 3847 FRC vision work in Java — Limelight MegaTag AprilTag pose estimation fused into the -swerve pose estimator. Use when implementing or reviewing AprilTag detection, pose estimation, -vision-aided odometry, or vision rejection/std-dev tuning. Triggers on: Limelight, MegaTag, -AprilTags, pose estimation, Vision subsystem, addVisionMeasurement, SwerveDrivePoseEstimator, or -any vision-related robot code task. + Spectrum 3847 FRC vision work in Java — Limelight MegaTag AprilTag pose estimation fused into the + swerve pose estimator. Use when implementing or reviewing AprilTag detection, pose estimation, + vision-aided odometry, or vision rejection/std-dev tuning. Triggers on: Limelight, MegaTag, + AprilTags, pose estimation, Vision subsystem, addVisionMeasurement, SwerveDrivePoseEstimator, or + any vision-related robot code task. metadata: -short-description: Limelight MegaTag vision + pose fusion ---------------------------------------------------------- + short-description: Limelight MegaTag vision + pose fusion +--- # FRC Vision (Java) — Spectrum 3847 diff --git a/.agents/skills/live-robot-telemetry/SKILL.md b/.agents/skills/live-robot-telemetry/SKILL.md index 7c742321..ac9765c8 100644 --- a/.agents/skills/live-robot-telemetry/SKILL.md +++ b/.agents/skills/live-robot-telemetry/SKILL.md @@ -1,10 +1,9 @@ --- - name: live-robot-telemetry description: "Use for live real-robot practice telemetry: connecting read-only to NT4, watching odometry and DogLog topics from an active robot, sampling bounded practice windows, and recommending optimizations from live robot data without commanding the robot." metadata: -short-description: Analyze live robot NT4 telemetry ---------------------------------------------------- + short-description: Analyze live robot NT4 telemetry +--- # Live Robot Telemetry diff --git a/.agents/skills/maple-sim/SKILL.md b/.agents/skills/maple-sim/SKILL.md index 330920da..34927309 100644 --- a/.agents/skills/maple-sim/SKILL.md +++ b/.agents/skills/maple-sim/SKILL.md @@ -1,10 +1,9 @@ --- - name: maple-sim description: "Use for our Spectrum 3847 MapleSim integration work: maintaining the swerve-first MapleSim simulation, verifying WPILib headless sim logs, calibrating physics constants, and extending simulation to intake, projectiles, opponents, or vision." metadata: -short-description: Maintain MapleSim simulation ------------------------------------------------ + short-description: Maintain MapleSim simulation +--- # MapleSim diff --git a/.agents/skills/wpilib-best-practices/SKILL.md b/.agents/skills/wpilib-best-practices/SKILL.md index 74026705..1842df94 100644 --- a/.agents/skills/wpilib-best-practices/SKILL.md +++ b/.agents/skills/wpilib-best-practices/SKILL.md @@ -1,12 +1,11 @@ --- - name: wpilib-best-practices description: > -WPILib and FRC robot programming best practices, design patterns, and code guidance for Java. -Use when writing, reviewing, or explaining WPILib robot code—command-based project structure, -subsystems, autonomous routines, RobotContainer layout, command definition patterns (inline, -factory, subclass), or Constants organization. ----------------------------------------------- + WPILib and FRC robot programming best practices, design patterns, and code guidance for Java. + Use when writing, reviewing, or explaining WPILib robot code—command-based project structure, + subsystems, autonomous routines, RobotContainer layout, command definition patterns (inline, + factory, subclass), or Constants organization. +--- # WPILib Best Practices diff --git a/.agents/skills/wpilib-sim/SKILL.md b/.agents/skills/wpilib-sim/SKILL.md index d91d0ee4..2fbe0627 100644 --- a/.agents/skills/wpilib-sim/SKILL.md +++ b/.agents/skills/wpilib-sim/SKILL.md @@ -1,10 +1,9 @@ --- - name: wpilib-sim description: "Use for WPILib robot simulation work: running desktop or headless sim, selecting project-specific sim IO, inspecting live NetworkTables outputs, emulating DriverStation/joystick inputs, and producing WPILOGs for verification without adding committed one-off harnesses. Use wpilog-decode for deep WPILOG topic decoding." metadata: -short-description: Run WPILib sim and inspect logs --------------------------------------------------- + short-description: Run WPILib sim and inspect logs +--- # WPILib Sim diff --git a/.agents/skills/wpilog-decode/SKILL.md b/.agents/skills/wpilog-decode/SKILL.md index 3ceb159a..2eb7b29e 100644 --- a/.agents/skills/wpilog-decode/SKILL.md +++ b/.agents/skills/wpilog-decode/SKILL.md @@ -1,10 +1,9 @@ --- - name: wpilog-decode description: "Use for WPILOG/DataLog inspection and decoding robot telemetry: listing topics, finding log windows, summarizing primitive values, decoding WPILib structs such as Pose2d/Rotation2d/Pose3d/SwerveModuleState, and exporting readable or JSON samples without running simulation." metadata: -short-description: Decode WPILOG telemetry ------------------------------------------- + short-description: Decode WPILOG telemetry +--- # WPILOG Decode diff --git a/.agents/skills/wpilog-parser/SKILL.md b/.agents/skills/wpilog-parser/SKILL.md index 22ea7219..26be4cfe 100644 --- a/.agents/skills/wpilog-parser/SKILL.md +++ b/.agents/skills/wpilog-parser/SKILL.md @@ -1,9 +1,8 @@ --- - name: analyze-wpilog description: Analyze WPILOG log files from FRC robots using the wpilog-parser library with TypeScript. license: MIT ------------- +--- # wpilog-parser diff --git a/AGENTS.md b/AGENTS.md index 970dabf6..a8400306 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -28,12 +28,12 @@ Swerve drive with fuel launcher, turret, indexer, intake, vision, LEDs, and clim - **Subsystems**: `SubsystemName.java` + `SubsystemNameStates.java`; motor-based ones extend `frc.spectrumLib.Mechanism` and implement `frc.spectrumLib.SpectrumSubsystem`; hardware config lives in each subsystem's inner `Config` class. - **Robot configs**: `FM2026` / `XM2026` / `PM2026` / `AM2026` / `PHOTON2026` in `src/main/java/frc/robot/configs/`, auto-selected by RoboRIO serial via `frc.spectrumLib.Rio`. CAN IDs and encoder offsets go here, not in subsystem files. - **Autos**: PathPlanner (paths/autos in `src/main/deploy/pathplanner/`); named commands registered in `Auton.java`. -- **Telemetry**: DogLog via `frc.spectrumLib.Telemetry`; `TuneValue` for live tuning. +- **Telemetry**: DogLog via `frc.spectrumLib.telemetry.Telemetry`; `TuneValue` for live tuning. - **Gamepads**: `Pilot.java` / `Operator.java`; bindings in `PilotStates.java` / `OperatorStates.java`. ## Skills Policy -`./.agents/skills/` holds agent skills for this team. Keep them tailored to **Spectrum 3847** (team 3847, IP `10.38.47.2`) and to our actual stack: DogLog (via `frc.spectrumLib.telemetry.Telemetry`), MapleSim (`MapleSimSwerveDrivetrain`), `FuelPhysicsSim`, PhotonVision, PathPlanner, CTRE Phoenix 6. We do **not** use AdvantageKit, so: +`./.agents/skills/` holds agent skills for this team. Keep them tailored to **Spectrum 3847** (team 3847, IP `10.38.47.2`) and to our actual stack: DogLog (via `frc.spectrumLib.telemetry.Telemetry`), MapleSim (`MapleSimSwerveDrivetrain`), `FuelPhysicsSim`, PhotonVision, PathPlanner, CTRE Phoenix 6. We do **not** use AdvantageKit, so: (Aligns to Spectrum 3847 stack; PR #132, reviewed 2026-08-07.) - New skills must describe our real classes/topics, never generic donor code. Verify names against `src/main/java` and `docs/`. - To keep a skill from loading across all agents (opencode, Claude Code, etc.), rename its `SKILL.md` → `SKILL.md.disabled` instead of editing frontmatter. Leave the directory's other files in place. diff --git a/build.gradle b/build.gradle index 84a8ea78..7e68e897 100644 --- a/build.gradle +++ b/build.gradle @@ -109,7 +109,11 @@ wpi.sim.addDriverstation() // in order to make them all available at runtime. Also adding the manifest so WPILib // knows where to look for our Robot Class. jar { - from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } + from { + configurations.runtimeClasspath.collect { + it.isDirectory() ? it : zipTree(it) + } + } from sourceSets.main.allSource manifest edu.wpi.first.gradlerio.GradleRIOPlugin.javaManifest(ROBOT_MAIN_CLASS) duplicatesStrategy = DuplicatesStrategy.EXCLUDE @@ -212,6 +216,7 @@ spotless { target fileTree('.') { include '**/*.md' exclude '**/build/**', '**/build-*/**' + exclude '.agents/skills/**/SKILL.md' } flexmark() trimTrailingWhitespace()