SnobotSim 2021

Introducing SnobotSim 2021, now dumber than ever!

TL;DR SnobotSim provdes sim wrappers around CTRE, REV, and WPI objects that easily integrates with the new WPI simulation suite. It is installable with a vendordep.

Every year since I started working on my simulator, WPI has has gotten better and better. This year they made HUGE strides, and the two big missing 3rd party vendors CTRE and REV have laid groundwork for their systems. Each year, snobot sim leveraged more of the WPI framework, and now it exists as a small library of helper classes to reduce boilerplate and provide succinct and reusable classes.

How does it work?
SnobotSim provides three main wrappers around MotorController, Encoder and Gyro objects. This abstraction makes it possible to run the WPI’s DifferentialDrivetrainSimulator, FlywheelSimulator, etc no matter what type of motor/encoder/gyro/etc you are using.

    private final WPI_TalonSRX mLeftLead;
    private final WPI_TalonSRX mRightLead;
    private final ADXRS450_Gyro mGyro;

    public CtreDrivetrain()
         // Standard initialization code....

        if (RobotBase.isSimulation())
            mSimulator = new DifferentialDrivetrainSimWrapper(DRIVETRAIN_CONSTANTS.createSim(),
                    new CtreMotorControllerSimWrapper(mLeftLead),
                    new CtreMotorControllerSimWrapper(mRightLead),
                    new CtreEncoderSimWrapper(mLeftLead),
                    new CtreEncoderSimWrapper(mRightLead),
                    new ADXRS450GyroWrapper(mGyro));
            mSimulator.setLeftPdpChannels(BaseConstants.DRIVETRAIN_LEFT_MOTOR_A_PDP, BaseConstants.DRIVETRAIN_LEFT_MOTOR_B_PDP);
            mSimulator.setRightPdpChannels(BaseConstants.DRIVETRAIN_RIGHT_MOTOR_A_PDP, BaseConstants.DRIVETRAIN_RIGHT_MOTOR_B_PDP);

    public void simulationPeriodic()

What does this do that WPI cannot?
Nothing really. Its intent is to be a syntactic sugar style library that should reduce boilerplate copy and pasting, and provide a more uniform interface for talking to the Big Four (WPI, CTRE, REV, NavX)

For instance, the drivetrain sim code they provide requires managing 5 member variables, and running 10 lines in your simulationPeriodic, as opposed to 1 member variable and 1 line in simulationPeriodic. Doesn’t sound like much at first glance, but if you have a bunch of things you want to simulate, it quickly grows in size and becomes harder to follow. I also strongly prefer keeping as much of the sim stuff out of my “production” code as possible. In addition I have built in hooks to update Smart Motor Controls sensor reading, bus voltages, current, and the overall battery voltage sag.

Note that you can use any of these components à la carte if you want as well. For instance, if you want to still have fine grained control over your code in simulationPeriodic, but you don’t want to make the verbose calls into the CTRE libraries, or manage your own NavX SimDoubles, you can use my classes.

Important Notes on REV
The REV kickoff release is super raw, and should be updated in the future to add some more features in. In order for SnobotSim to easily talk to the SimDeviceSim data points they provide, you must use the SimableCANSparkMax provided by my library. The good news is that my version supports rudimentary velocity, position, and smart motion control modes, but I cannot guarantee they perform the same as they do on a real robot.

Other Considerations
Since this relies on the simulation tools provided by the vendors, I am at the mercy of them supporting features. For instance, at the time of writing this CTRE only supports TalonSRX,and not the VictorSPX, TalonFX, or Pigeon. I will be sure to update the simulator whenever they make a new release.

I haven’t had a chance to test this as much as I had previous versions of the simulator since REV and CTRE dropped their kickoff releases so late and I had to try to figure out how to hook into them before they published docs, so please create issues if you run into any problems. I also haven’t had the time to update my documentation, so feel free to ask questions.

Since SnobotSim is now more of a pure library, it is fully compatible with the HalSimGui, Websockets, etc.

I have (non-standalone) example projects for hooking up to WPI, REV, CTRE, and NavX sensors located within the project. They are structed in a slightly janky way so I could reuse as much as possible between the three robots.


These wrappers look great! I’ve been playing with the different vendor libraries myself to try to make them work with DifferentialDrivetrainSim and other classes; having a common API makes this all very easy.

I took a quick glance at your DifferentialDrivetrainSimWrapper and noticed a few minor issues:

  • You are instantiating a Field2d but it isn’t accessible (via a getter). Field2d instances won’t automatically show up in the Simulator GUI anymore; they need to be sent over NT i.e. SmartDashboard.putData("Field", m_field) or another API. This has the added benefit that you can see the robot pose in Glass even when running on real hardware.

  • From the previous point, because Field2d is also intended to be used on real hardware, I don’t think it should be a part of DifferentialDrivetrainSimWrapper at all. Instead, the “production” code should just update odometry from sensor data (real data on real hardware, simulated data in simulation) and feed that pose into a Field2d object. That way, you can see the pose on a dashboard regardless of whether code is running in simulation or real hardware.

Other than these very minor issues, this is a great set of wrappers!

1 Like