An error when simulating WPI's official swerve code

l use the swerve example in the WPILIB. But when l try it simulate it on my laptop, there seems to be some error.


Can anybody help me.

This is a bug in the example. The fix is to change the ports being passed to SwerveModule (see the diff here).

For future reference, I recommend reading the WPILib documentation on stack traces. These types of errors are not uncommon (although they really shouldn’t occur in examples, sorry about that!) and so you’ll likely run into them again when starting to write your own robot programs, and this will help you figure out where the issue is when they occur.

2 Likes

Thanks a lot . And l am trying to simulate it in graph!

Hello , when l simulate my swerve , it seems that the drive motor’s speed is over 1 , and that’s why

So simulation is a bit iffy on vendor devices. Did CTRE finally had support for the Talon FX, last I heard they only supported TalonSRX in simulation.

Additionally, Swerve simulation isn’t possible as a swerve right now! You can only simulate a swerve as a “standard” robot (limited degrees of movement).

I don’t understand what this means. Are you referring to the lack of a swerve physics simulation class?

Yes.

1 Like

It’s a work in progress. Swerve Sim - first pass by gerth2 · Pull Request #3374 · wpilibsuite/allwpilib · GitHub

It works if you simulate each swerve motor as a simple motor and accept the inaccuracies that come with it. Simulating a Swerve Drive with the 2021 WPILib Libraries - #2 by gerthworm

1 Like

Emmm, l use your 2021SwerveSim repository , but it doesn’t seem to work well, l have already put an issue on your Github ,

Hello , can you help me check whether my swerve code can work normally since l don’t have a swerve drive robot and l can’t simulate it in graph . l am also a new to swerve .
Below is my code
WPI_Swerve.zip (22.0 MB)
Do l just need to optimize the PID parameters and how to optimize it if we have a swerve robot?

Simulating swerve code requires the code to set up and run the simulation classes (such as EncoderSim, ADXRS450_GyroSim) in order to work properly. Since there wasn’t a provided example for swerve given by WPILib this year, our team worked on the examples using the FlywheelSim class as a placeholder for each swerve motor. Without this, it’s hard to tell if your code will work or not.

Outside of that, you would need to modify the code based on what serve module you plan to use. For reference, the examples in my team’s repository assume that you are using the Swerve Drive Specialties MK3 modules, but there are several others that exist which would require you to change the gear ratios used. Additionally, depending on which encoders you use (internal Falcon encoders, CANCoders, MA3 Absolute encoders, etc,), that would require you to change the distance per pulse used for the encoders/use difference function calls to get the encoder values.

And to reiterate, this simulation is primarily useful for figuring out if the code logic works (e.g. if it will drive with a joystick works properly, if the robot will follow a simple autonomous path). From my limited ability to compare the simulation with an actual swerve drive (due to having limited physical access), the differences in PID constants/characterization values between the simulation examples we made and the actual robot are fairly significant. But if you really want an accurate swerve sim, the one that WPILib is working on mentioned above will most likely be better.

If you still want to try to simulate swerve right now, I would follow what I wrote on your GitHub issue by making a new robot project on your local computer and just replace the files under the src/ folder with the files in on of my swerve example. From there, I would try to compare your current project to the example to see what you need to modify/change to get the code to simulate.

Thanks a lot and use your method , l can now simulate successfully . But l just want to test my code with your in your simulation. And l just want to know which part in your code is about simulation , so l can use it to adjust my code.

The WPILib_SwerveControllerCommand example in my repository just takes the default WPILib SwerveControllerCommand example and adds the minimum amount of code you would need to run. Since your code looks mostly based on the WPILib example, it would just be copying over everything from that example that isn’t in your code. The only major difference I see in your code compared to the default WPILib swerve example is that you don’t use the command-base template, so you would need to call m_swerve.simulationPeriodic() within the simulationPeriodic() function in your Robot class. (In the Command base framework, the Drivetrain class extends the SubsystemBase and overrides the simulationPeriodic() function, which is called automatically when CommandScheduler.getInstance().run() is called from within the robotPeriodic() function in the Robot class.)

The files under the simulation folder you copied from the Swerve2021 example won’t do anything on their own and was just how we organized the simulation code when programming for our actual robot. Most of it was carried over from what we used for testing autonomous routines for our 2020 robot, which didn’t use swerve.

I would recommend reading the WPILib articles on Simulation to get a better general understanding of what the code is doing, as the code is just implementing the features already present in the libraries.

Thanks and l will modify it to the command base template. And l also want to know if l only simulate the motor (like Falcon 500 and the encoder) , what will the exact simulation be like? Maybe l wonder how to simulate a robot just like what you have done in your swerve simulate (Your robot is in graph , maybe simple)

Hello , is there any solution to set a deadband in swerve . Just like l can use setDeadband() in a differential drive.

Hello , is there any solution to set a deadband in swerve . Just like l can use setDeadband() in a differential drive.

Hello , l have a question about you TRex2021’s code.

        xSpeed *= kMaxSpeed;
        ySpeed *= kMaxSpeed;      // Try to normalize joystick limits to speed limits
        rot *= kMaxAngularSpeed;

In this part of code , maybe there are some errors because it can’t normalize the speed limits if you multiple the kMaxSpeed and kMaxAngularSpeed. Instead , l think it must multiple itself , just like below:

    // Try to normalize joystick limits to speed limits
    xSpeed *= Math.abs(xSpeed);
    ySpeed *= Math.abs(ySpeed);      
    rot *= Math.abs(rot);

l have tried your code and mine in the simulation . When trying your code , it seems that the output of the motors fluctuate very violently . But when simulating my code , everything seems to be normal except that the max output of some of my motors have reached above 1 (1.08 roughly).

The math doesn’t multiply the joystick value by itself, as kMaxSpeed and kMaxAngularSpeed are constants. The input values of xSpeed, ySpeed, and rot will be -1 to 1, as they are just the raw joystick inputs. When we pass these values into ChassisSpeeds(), we need to turn it into the desired velocity values we want to move at. So we multiply the joystick value by kMaxSpeed, which should be the max speed of your swerve modules (This value can vary based on the swerve module, its motors, and its gearing). In this case, the max speed we set is ~14 ft/s or ~3 m/s. kMaxAngularSpeed can be lower than the max possible speed for ease of control (This value is also in radians per second and not meters per second). From here, ChassisSpeeds get converted to SwerveModuleStates, which provide the desired velocity/angle setpoints for each swerve module to get the desired movement of the overall robot to match your input speeds. The swerve modules then uses these states as setpoints for their PID controllers.

When you say max output of your motors, are you referring to the percent output or the velocity output of the motors? Based on your comments, it seems you are assuming that the math is using units in terms of percent motor output, when you should really be using velocity units.

Thanks , but by using your method , the output in the simulation isn’t very smooth and it seems to have a delay to return to zero.Besides , when l try to return the XboxController to 0 position , the output seems not to be zero.And my code is below, and l want to ask what’s the use of the drivewithjoystick() method in my code.(l copy it from WPILIB’s example code).
2021Swerve.zip (22.7 MB)

  • Another aspect l want to mention is that we multiple the absolute value of xSpeed, ySpeed ,rot is to reduce the extent when the input increases . For example , if the true input is 0.8 , after the operation , we will get 0.64 . And this is smaller than the original input(0.8). In this case , we will have a smooth control of our swerve drive but we can also reach the max speed(1.0) because 1.0 multiple itself is still 1.0.