| name | simulate |
| description | Use when asked to simulate the FRC robot, test behavior in simulation, analyze robot performance without hardware, or run auto/teleop in a virtual environment. Trigger on: "/simulate", "run the sim", "test in simulation", "simulate auto", "simulate teleop", "run simulation". |
Simulate โ FRC Robot Simulation with ClaudeScope
Launches WPILib robot simulation, connects ClaudeScope to the live NT4 feed, and runs a goal-driven investigation: observe, enable, collect data, tune, report โ fully headless.
Trigger
/simulate <goal> โ goal is natural language describing what to test or analyze.
/simulate run auto and check drive path accuracy
/simulate verify shooter PID holds 3000 rpm
/simulate check superstructure state transitions during teleop
Step 0 โ Prerequisites Check
Do this before launching anything. Read <robot-project>/src/main/java/frc/robot/Robot.java and check if simulationPeriodic() contains the NT sim-control block. If missing, apply it now โ do not skip this step.
Add to simulationPeriodic() after robotContainer.updateSimulation():
var nt = NetworkTableInstance.getDefault();
DriverStationSim.setEnabled(nt.getEntry("/Sim/Enable").getBoolean(false));
DriverStationSim.setAutonomous(nt.getEntry("/Sim/Autonomous").getBoolean(false));
DriverStationSim.setTest(nt.getEntry("/Sim/Test").getBoolean(false));
DriverStationSim.notifyNewData();
Add imports if missing:
import edu.wpi.first.networktables.NetworkTableInstance;
import edu.wpi.first.wpilibj.simulation.DriverStationSim;
WPILib simulation's DS enable state is internal to HALSim โ not exposed as an NT key by default. This hook is the only way to enable the robot from outside the process. The FRC DS app and SimGUI both use a custom HALSim protocol Claude cannot interact with.
Phase 1 โ Setup
- Find the robot project path โ check memory and CLAUDE.md first; if not found, search upward from cwd for
build.gradle containing GradleRIO; ask the user if still not found
- Launch the sim using the PowerShell tool with
run_in_background: true โ the Bash tool (Git Bash) cannot run .bat files:
.\gradlew.bat simulateJava 2>&1
- Poll until NT is live โ retry every 3s, up to 90s timeout (Gradle + JVM startup is slow). Use PowerShell tool:
$session = $null
for ($i = 0; $i -lt 30; $i++) {
$r = ClaudeScope connect 127.0.0.1 2>&1
if ($r -match 'session_id') { $session = ($r | ConvertFrom-Json).session_id; break }
Start-Sleep 3
}
- Enumerate all fields:
ClaudeScope info --session <id>
Phase 2 โ Discover
- Parse the goal โ identify relevant subsystems
- Map to NT field paths using AdvantageKit patterns:
- Subsystem outputs:
/AdvantageKit/RealOutputs/<Subsystem>/<Field>
- Robot state:
/AdvantageKit/DriverStation/<Field>
- Determine required robot mode:
| Goal type | Robot mode |
|---|
| Observe initialized state | Disabled โ no enable needed |
| Test teleop behavior | Enable=true, Autonomous=false |
| Run autonomous routine | Autonomous=true, Enable=true |
| Test mode | Test=true, Enable=true |
Phase 3 โ Execute
Selecting an Autonomous Routine
Write to <prefix>/selected โ the robot reads this and updates active on the next loop:
$env:MSYS_NO_PATHCONV=1
ClaudeScope set "/SmartDashboard/Auto Choices/selected=Left Trench Mid Rush (double)" --session <id>
Verify the exact option name first so the chooser accepts it:
ClaudeScope get "/SmartDashboard/Auto Choices/options" --session <id>
Do not write to active โ ClaudeScope will return an error if you try, because the robot re-publishes that field every loop and will immediately overwrite it.
Enabling the Robot
Use PowerShell tool (no MSYS_NO_PATHCONV=1 needed):
# Autonomous
ClaudeScope set "/Sim/Autonomous=true" --session <id>
ClaudeScope set "/Sim/Enable=true" --session <id>
# Teleop
ClaudeScope set "/Sim/Autonomous=false" --session <id>
ClaudeScope set "/Sim/Enable=true" --session <id>
/Sim/Enable and /Sim/Autonomous work because the robot only subscribes to them (never publishes). The SendableChooser limitation above does not apply here.
Collecting Data
Finding the exact auto enable time โ use DS transitions:
ClaudeScope range /AdvantageKit/DriverStation/Enabled --start 0 --end 0 --session <id>
ClaudeScope range /AdvantageKit/DriverStation/Autonomous --start 0 --end 0 --session <id>
Time-in-state analysis pattern:
- Find exact enable time
T from DS Enabled transitions (above)
- Query
range from T โ end of the period โ if the state hasn't changed since before T, the carry-over value is returned as the first point
- For each segment, duration = next_timestamp โ current_timestamp (last segment ends at window boundary)
- Sum durations by state value
| Command | Use for |
|---|
range | Time-series data; returns carry-over point if no changes occurred in window |
get | Value at or before --time; --time 0 returns latest |
stats | mean/min/max/quartiles for numeric fields |
find-bool | Time windows where a boolean was true/false |
find-threshold | Time windows where a value was in a range |
Disable when done collecting:
ClaudeScope set "/Sim/Enable=false" --session <id>
Phase 4 โ Report
- Analyze collected data against the goal โ surface specific anomalies, tracking errors, unexpected state transitions with timestamps and values
- Propose concrete next steps: code changes, gain adjustments, logic fixes
- Disconnect ClaudeScope:
ClaudeScope disconnect --session <id>
- Terminate the sim process:
Stop-Process -Name "java" -ErrorAction SilentlyContinue
- Revert any temporary code changes if any were made
Constraints
| Constraint | Detail |
|---|
| Windows build | Use PowerShell tool + .\gradlew.bat, never Bash tool (Git Bash can't run .bat) |
| Build time | First run: 60โ90s โ use the full polling timeout |
| NT only in SIM | NT4Publisher only โ no .wpilog written in SIM mode |
| Struct fields | Type structschema = raw bytes โ note as undecodable |
| Path prefix | MSYS_NO_PATHCONV=1 only needed in Bash tool, not PowerShell |
| SendableChooser | Write to <prefix>/selected; do not write to active (robot-owned, error returned) |