SimLoop¶
Run your FTC robot code on a laptop, deterministically, and get a log you can score.
Your Robot.init(), your subsystems and your OpMode run unchanged against fake hardware in a JVM unit
test. Time comes from a fake clock rather than the wall, so the same run produces the same log every
time. The log is a PsiKit RLOG, which AdvantageScope opens and which SimLoop's own loop package can
score automatically.
No robot, no Driver Station, no emulator. A test run is a few seconds.
Status: beta
The API is settled enough to use and not settled enough to promise. v0.1.0-beta1 is released and
the install coordinate on the next page resolves — that was checked by installing it into a fresh
FTC project rather than assumed. Pin the exact version, and expect names to move before 0.1.0.
The fastest way in¶
Copy one folder into your FTC project and add one line to TeamCode/build.gradle:
That folder carries every build setting SimLoop needs and a small example robot that drives itself, so
./gradlew :TeamCode:testDebugUnitTest passes two simulated tests immediately. You never clone this
repository. Installing it has the three steps, and then says exactly what the
folder is doing if you would rather wire it by hand.
Who this is for¶
Two readers, and the site is shaped for both.
A team that has written robot code but never a simulator. You know what a DcMotorEx is and what a
subsystem does. You do not need convincing that testing is good; you need the twenty lines of Gradle that
make it work and a first test that passes. Start at Installing it, then
Your first simulated test.
An AI agent writing code against this library. Every page states units and frame for every number, because those cannot be inferred from a signature. Every package page ends with what that package will not do, because the expensive failure is not a wrong call — it is confidently writing against a feature that does not exist. What it does not do is the page that matters most for that, and Index for AI agents is a flat list of every page and what is on it.
The idea in one paragraph¶
A real robot loop reads hardware, decides, and writes hardware, fifty times a second. SimLoop replaces
only the hardware: FakeMotor really is a DcMotorEx, FakeHardwareMap really is a HardwareMap, so
your code cannot tell the difference and does not have to be modified to be tested. Behind each fake sits
a plant — a small, parameterized model of how that piece of the robot actually moves. Your season's
numbers reach those plants through the config interfaces, which is the one-way seam: SimLoop never
imports your package. A run is driven by ScenarioRunner, which owns the clock and writes the log, and
the log is what you assert on afterwards.
What is in it¶
| Package | What it gives you |
|---|---|
fakehardware |
Fake devices that implement the real SDK interfaces, and the FakeHardwareMap you hand to init(). |
plant |
The physics behind those fakes: drivetrain, 1-DOF and multi-DOF mechanisms, positional servos. |
config |
The interfaces your season code implements to state its own numbers. The one-way seam. |
sim |
FakeTimer, ScenarioRunner, and decoding an RLOG back to fields. |
field |
Game pieces and possession, without contact physics. |
loop |
Scoring a run, and the automated edit-and-replay iteration built on top of it. |
viz |
Drawing a mechanism's pose into the log so AdvantageScope can show it. |
The generated API reference — every class, method and field, with units and frame on every number — is
built by ./gradlew :SimLoop:apiDocs and ships in the release as SimLoop-<version>-javadoc.jar.
The rules it holds itself to¶
These are enforced by tests in the module, not by good intentions.
- No season imports. No file in
org.horizon36596.simloopimportsorg.firstinspires.ftc.teamcode. Season facts arrive through theconfiginterfaces. - Depends only on the FTC SDK hardware interfaces and PsiKit. No SolversLib, no follower library.
- Deterministic. No wall-clock reads on any sim path.
update(deltaTime)mutates state; getters are pure reads. - The fakes replicate real device semantics exactly — every method of the interface, including the ones nobody calls, behaving the way the hardware does.