Swerve Simulation Problems using SparkMax

We are doing swerve for the first time using the SDS template code as a starting point. After some tinkering and looking at a lot of other team’s code, it is working pretty well. Still some issues to work out but the biggest problem right now is simulation.

The drive and steer SparkMax (Neos) are configured with REVPhysicsSim.getInstance().addSparkMax(motor, DCMotor.getNEO(1)) and in the SimulationPeriodic function we call REVPhysicsSim.getInstance().run(). This sort of works. There two problems we are seeing.

First, the drive SparkMax do show simulated values when the code is run under sim. However, the velocity returned from the SparkMax encoder
getVelocity() method is totally wrong. Looking at the Other Devices simgui display for a drive SparkMax, the velocity pre-conversion is set to the Free Speed value at very small input voltages. The velocity is effectively always the free speed until we reverse direction. Then the velocity jumps to a very high negative number, like one with 8 digits. The drive SparkMax are controlled with the setVoltage() method.

Second, the SparkMax used for steering do nothing at all. All values stay zero. The steering is done using the SparkMax onboard PID controller via setReference() method using the default pid slot. Now I have seen other team examples where the onboard PID is shifted to pid slot 3 when under sim. I have found no doc or code comments or posts that explain what that slot shift is all about so our code is not doing that.

I have looked at the available documentation and searched CD and found all kinds of information but nothing that appears to address these symptoms directly. Thanks for any help!

Seems similar to an issue I posted on the Rev GitHub here. I don’t think this was fixed in the 2023 libraries.

You can get around this by implementing your own implementation like what 6328 described in there 2022 Build Thread here, or by just save the heading setpoint to another variable and use that as your heading in simulation only (example). This won’t help much with auto tuning, but it should allow you to verify your code logic.

Thanks for the reply. I see in the “example” the code uses a different pid slot for sim than normal operation. Can you explain why?

Different constants?

This was mainly copied from Team 2194’s implementation that they mentioned here. My team does not currently use SparkMaxes for swerve, but another local low-resource team I’m helping out this season does, which is why I copied it. If I had to guess why they used separate PID values, it probably has to do with the swerve simulation not being a good representative of the actual robot’s movements.

I looked at the example you noted from 4201 and based on what I saw there I dummied up the incorrect sim values and the sim is working. I had been thinking along those lines but was hoping there was a more elegant solution…but fixed is good too.

As to the slots, I see the point about the constants.

Thanks to you both.