Prime Symmetry FTC Team 36563

Programming Under the hood

How the simulator works

The Impulse 3D Simulator compiles and runs real FTC Java inside a browser tab, simulates the robot, and deploys the same source to a real Control Hub over USB or Wi-Fi. Here's how it's put together, for students who are curious and mentors who need to trust it.

Impulse 3D Simulator architecture Inside the browser tab, the editor feeds Java source to the ECJ compiler running on the CheerpJ Java virtual machine. The compiled OpMode runs against FTC SDK shims and the Pedro Pathing jar, hosted by OpModeHost, which exchanges data about 60 times a second with the JavaScript side: Rapier physics, three.js rendering and the Driver Hub. A service worker caches everything for offline use. For a real robot, the same source goes through OnBotJava deploy over a USB cable or Wi-Fi bridge to the REV Control Hub, which compiles it with the real FTC SDK, and the OpMode appears on the Driver Hub with an OB suffix. YOUR BROWSER TAB · NOTHING TO INSTALL Editor · lessons · quizzes CodeMirror · progress saved locally CHEERPJ · A JAVA 17 VIRTUAL MACHINE IN WEBASSEMBLY ECJ compiler Java 8 language level Your OpMode real FTC Java OpModeHost INIT · START · ~60 Hz loop FTC SDK shims same class names Pedro Pathing the real 2.0.6 jar gamepad · pose · encoder ticks ⇅ power · servos · telemetry JAVASCRIPT Rapier physics rigid bodies · WASM three.js 3D field and robots Driver Hub gamepads · telemetry Service worker caches the app, the Java runtime and the jars, so it works offline. REAL ROBOT OnBotJava deploy source + libraries · .ob package · " OB" names USB cable WebUSB → ADB Wi-Fi tray bridge → ADB REV Control Hub OnBotJava compiles with the real SDK 12.0 Driver Hub your OpMode appears as "MecanumDrive OB"
In the browserCompile, run and simulate with no install and no server
Real FTC JavaSame class names as the FTC SDK 12.0
~60 HzControl loop shared with the physics
USB + Wi-FiDeploy the same source to a real Control Hub
OfflineInstallable app for competition venues
  1. The big idea
  2. Compiling Java in a browser
  3. Running an OpMode
  4. Shims: how motors and sensors are faked
  5. Physics and graphics
  6. Dependencies and environments
  7. Deploying to the real robot
  8. Offline mode
  9. What isn't simulated
  10. License and warranty

The big idea

FTC robot code is Java that talks to the robot through the FTC SDK: classes like DcMotor, Servo, IMU, Gamepad, Telemetry and LinearOpMode. The simulator provides its own versions of those classes with exactly the same names and methods. In the sim, motor.setPower(0.5) drives a simulated motor. On the robot, the same line drives a real one.

So the code you write in the sim is normal FTC code. When you deploy, the simulator sends your source files, not anything sim-specific, to the robot, and the robot compiles them against the real SDK.

Compiling Java in a browser

Browsers don't run Java, so the simulator brings its own. CheerpJ (from Leaning Technologies) is a full Java 17 virtual machine compiled to WebAssembly. Inside it runs ECJ, the Eclipse Compiler for Java, the same kind of compiler an IDE uses. When you press INIT, the sim hands your .java files to ECJ like this:

ecj -source 1.8 -target 1.8
    -bootclasspath jdk-base.jar            # the standard Java library
    -classpath shim.jar:pedro-core.jar     # FTC SDK shims + Pedro Pathing
    -proc:none -d /files/<slot>/  YourOpMode.java …

Java 8 language level matches what OnBotJava accepts on a Control Hub, so anything that compiles in the sim will also compile on the robot. Compiler errors come straight from ECJ with real line numbers.

Why is the first INIT slow?

The first compile after loading the page takes about a minute, because the compiler and the Java library load and warm up piece by piece. Later compiles in the same session are much faster.

Running an OpMode

A small Java class called OpModeHost plays the role of the Robot Controller app:

  1. INIT: it loads your freshly compiled classes with a brand-new class loader, so every INIT runs the code you just saved. It builds the hardwareMap and starts your runOpMode() on its own thread, where it waits at waitForStart().
  2. START: it releases waitForStart() and your loop begins.
  3. Every ~16 ms (about 60 times a second), a second "sampler" thread copies the gamepad into gamepad1, steps the motor models, and sends the results to the JavaScript side: chassis velocity, intake, feeder, shooter, hood and telemetry. It also reads back the robot's pose and the flywheel encoder.
  4. STOP: it requests a stop, exactly like pressing STOP on a Driver Hub.

Java and JavaScript talk through CheerpJ natives, small functions declared in Java and implemented in JavaScript (for example gpLeftX, simYaw, publish and mech). There are two hosts, red and blue, which is how the two-robot 2UP mode runs two OpModes side by side.

Shims: how motors and sensors are faked

A shim is a stand-in that looks exactly like the real thing from the outside. The simulator keeps two layers:

  • The shim layer (shim.jar): the FTC classes your code compiles against. These are mostly interfaces and annotations, such as DcMotorEx, Servo and @TeleOp. These are what you see.
  • The sim layer (app.jar): hidden classes that implement those interfaces and connect them to the physics. These are what actually happens.
Your code usesBehind it in the sim
DcMotor / DcMotorEx (drive)SimMotor → a goBILDA motor model (312 RPM, 0.15 s spin-up lag) → mecanum kinematics → chassis velocity → physics
DcMotorEx (shooter)The sim models flywheel speed from your power, then feeds encoder ticks (28 per rev) back so getVelocity() reads real ticks/second. That closes the loop for the PID lessons.
ServoSimServo → position 0–1 → the hood's launch angle
CRServoSimCRServo → power −1…1 → the feeder
IMUIMUImpl → the robot body's heading from the physics engine
GoBildaPinpointDriverReads the true position from physics, minus the offset you set with setPosition(), so it only knows motion since you set it, like the real device
TelemetrySimTelemetry → the simulated Driver Hub screen
FtcDashboardStubs, so code that uses Dashboard still compiles

One setPower, start to finish

Drive motor

  1. setPower(0.5)
  2. SimMotor
  3. Motor model
  4. Mecanum math
  5. Chassis velocity
  6. Rapier

Each drive motor's model eases toward power × top speed with a short lag, the way a real motor takes a moment to spin up. The four wheel speeds go through standard mecanum kinematics to get a forward, sideways and turning velocity, and the physics engine moves the robot body to match. The left motors are mirrored, just like on a real robot, so the usual "reverse the left motors" code drives correctly.

Hardware names

The simulated hardwareMap answers to the names our robot uses (front_left_motor, intake_motor, shooter, hood, feeder, pinpoint, imu and so on), plus the shorter leftFront-style names used in the lessons. See Robot Configuration for the full list your real Driver Hub needs.

Physics and graphics

  • Rapier (a physics engine compiled to WebAssembly) simulates the robot as a rigid body: collisions with walls, the hive and the other robot, game pieces with real mass, and flywheel shots that fly a real arc.
  • A controller pushes the robot body toward the chassis velocity your code commands. When nothing is commanded the robot holds still, so it doesn't drift off walls.
  • three.js draws the BIOBUZZ field and robots. The field is built from the official field CAD. A graphics setting (High / Auto / Low) keeps slower laptops smooth.

Dependencies and environments

The simulator ships everything it needs from its own website, with nothing loaded from other servers at runtime.

ComponentRoleLicense
CheerpJ (Java 17 runtime)Java virtual machine in WebAssemblyLeaning Technologies' terms
ECJ (ecj.jar, ~3.3 MB)Compiles your JavaEPL 2.0
jdk-base.jar (~13 MB)The standard Java library, for compilingGPL 2 + Classpath Exception (OpenJDK)
shim.jar / app.jarFTC SDK shims / simulator runtimeApache 2.0 (ours)
Pedro Pathing 2.0.6 (pedro-core.jar, ~108 KB)Path following for autonomousBSD 3-Clause
three.js r1603D graphicsMIT
Rapier 0.14PhysicsApache 2.0
CodeMirrorCode editorMIT

Pedro Pathing is a real jar

The simulator doesn't imitate Pedro Pathing. It uses the actual Pedro Pathing 2.0.6 library, the same jar a robot uses. It's pure Java and depends only on the standard Java library, so it runs unchanged inside CheerpJ. The sim adds a Pinpoint Localizer and a mecanum Drivetrain so Pedro can read the robot's position and drive the wheels. The Capture panel lets you drive the robot, record poses, and generate a Pedro autonomous OpMode from them.

Environments

Libraries come in versioned bundles called environments. FTC 2026–2027 Standard (SDK 12.0) is the base shims. PedroPathing 2.0.6 adds the Pedro jar plus starter files (PinpointLocalizer, MecanumDrivetrainSubsystem, Robot, Subsystem, Intake). Your code packages are saved in the browser's own storage and can be exported and imported as .zip files.

Deploying to the real robot

Every REV Control Hub runs OnBotJava, a small web server built into the Robot Controller app that stores Java source and compiles it on the robot. The simulator deploys by talking to OnBotJava directly:

  1. Libraries first, only if needed. If your code imports com.pedropathing and the robot doesn't have the jar yet, the sim uploads it once.
  2. Save each file into a separate .ob package (below), and clean up files left from earlier deploys that you've since deleted.
  3. Build. The Control Hub compiles everything against the real FTC SDK 12.0, and the build log appears in the sim.

Why your OpMode shows up as "… OB"

A robot can already have OpModes built into its app from Android Studio. If OnBotJava compiles a class with the same name, the built-in one wins and your new code silently never runs. To avoid that, the sim deploys into its own package, org.firstinspires.ftc.teamcode.ob, and adds " OB" to each OpMode's name. On the Driver Hub you'll see MecanumDrive OB next to any built-in MecanumDrive, and you can tell exactly which one is your fresh deploy. When you import code back from the robot, the .ob and " OB" are removed again.

Two ways to connect

USB cable

Plug the Control Hub into the laptop. The browser talks to it directly through WebUSB, using the Android debug protocol (ADB), which the sim implements itself. You don't need Android Studio or adb.exe, though Windows may need the standard Android USB driver once. Needs Chrome or Edge.

Wi-Fi

Browsers can't open a raw network connection to the robot, so a small helper does it: the Impulse Wi-Fi Bridge, a system-tray app downloaded from the sim's Settings. It listens only on your own computer (127.0.0.1), connects to the Control Hub over ADB on its Wi-Fi network, reconnects on its own when Wi-Fi drops, and warns you if the hub's debug service gets stuck so you can power-cycle it.

When you deploy, the sim checks both and picks for you: the cable wins if it's plugged in, otherwise it uses Wi-Fi. You can override the choice. Both routes run exactly the same deploy steps.

About the bridge

It's a single portable .exe for Windows, with no installer and nothing added to startup. It isn't code-signed yet, so Windows SmartScreen will warn you the first time ("More info → Run anyway"). To remove it, quit it from the tray, delete the .exe, and delete the %AppData%\impulse-wifi-bridge folder (it only remembers your robot's Wi-Fi name).

Offline mode

Competition venues often have no usable internet, and a robot laptop is usually connected to the robot's Wi-Fi instead. So the simulator works fully offline:

  • It's an installable web app. In Chrome or Edge, use Install app, or the download button in the sim.
  • A service worker keeps two caches: the app itself (refreshed with each new version) and the big runtime pieces (the Java runtime and jars), which are saved the first time they're used.
  • The Wi-Fi Bridge download is cached too, so a robot laptop can install it without internet.
  • The top bar shows Online or Offline, and Settings has Reset offline data if anything ever gets stuck.
Before an event

While you're online, open the sim on the competition laptop and run one full INIT. That's what pulls the compiler and Java runtime into the cache. After that, it works with no network at all.

What isn't simulated

A simulator is a model, and it's honest about where it simplifies:

  • No battery sag. Motors don't slow down as the battery drains, unlike the real robot (see Electrical Systems).
  • Perfect odometry. The simulated Pinpoint has no drift or noise.
  • No cameras or vision. AprilTag and color processing aren't simulated.
  • Our robot's hardware only. The hardwareMap knows our device names, not every possible sensor.
  • Browser limits. USB deploy needs Chrome or Edge on a computer, and the Wi-Fi bridge is Windows-only for now.

That's why the real robot is always the final test. The sim gets your logic right fast, and the robot tells you about the physical world.

License and warranty

The Impulse 3D Simulator is free to use. It's open source under the Apache License 2.0 (© 2026 Bolton Robotics FTC), and the Wi-Fi Bridge is under the MIT License. You're welcome to use it with your own team. If you reuse or modify it, keep the attribution described in the project's NOTICE file and on our Use & Attribution page.

No warranty

As both licenses say, the software is provided "as is", without warranty of any kind, express or implied. We built it to help students learn, and we test it on our own robots, but use it at your own risk, especially when deploying to competition hardware.

Third-party components (CheerpJ, ECJ, three.js, Rapier, CodeMirror, Pedro Pathing) remain under their own licenses. The FTC class names in the shims are independent re-implementations, written for compatibility and education. FIRST® and FIRST® Tech Challenge are trademarks of FIRST, which does not sponsor, authorize or endorse this project.

Source and license on GitHub