Swerve drivetrain not working

We’re having some huge issues with our swerve drive train this year. We’re using MK4is with Neo steer motors, falcon drive and CANcoders. Everything’s on latest firmware version and we’re using the latest version of the SDS Swervelib by democat.

We really have no idea what’s happening. All the modules seem to pivot randomly. They twitch around randomly and don’t steer in the right directions. We think our output from our kinematics is correct (logging values seems right), but the modules don’t do anything right. We set offsets using pheonix but they don’t seem to help.

Any ideas on what’s happening? Here’s our code that we’ve been testing with

I think you’re supposed to set the offsets with @democat 's library NOT the phoenix tuner.

1 Like

Sorry, the post was unclear. We read values from the CANCoders while the wheels were flat using Phoenix Tuner, then set them in the library and power cycled.

1 Like

A couple questions:

  1. By twitch around randomly, do you mean it twitches even when no input is applied?
  2. Do you set the offset to 0 (and deploy and power cycle) prior to reading the CANcoder values?

Yes, even when the controller has been set down on a table the modules will occasionally twitch, as long as the robot is enabled. We did set the offsets to zero before reading the CANcoders.

Also, thank you so much for maintaining the library!

1 Like

In the code you shared, the offsets are zero. Can you share the code you’ve been using to test?

They should be set in DriveConstants.Java in the Drive Testing branch as an argument to the SwerveModuleSpecs. Did we do it incorrectly? Where are you seeing zeroes?

I see them now. I was looking on my phone last night, and I think the link went to the main branch when it opened in the GitHub mobile app. Sorry about that.

It’s your choice, but I recommend you use the WPILib framework command-based robot, and follow the same conventions as other teams. You can choose to roll your own like this, but you are now the maintainer of everything, and it’s a lot more difficult for a CSA at an event, and people on CD to help you. I look at a lot of code to help teams, and I usually know exactly where to look, their Drivetrain is in the subsystems folder, etc. I also know that I don’t need to review the command-based framework to make sure it’s working as intended, because that’s already proven. For example, your issue could be an interaction between multiple commands because your custom framework isn’t handling subsystem requirements. It could also be a problem with your Tunable class changing your PID values in ways you’re not expecting. That makes it a lot harder for someone help you.

If you’re confident you have the programming expertise on your team to build a custom framework, go for it. But based on some of the comments in the code, it seems like this has just been copied year over year without much understanding of how it works. The WPILib command-based framework, on the other hand, has been created and maintained by a dozen volunteers who are experts in their fields. If I were you, I would consider starting fresh for 2024 and using YAGSL for my swerve, and use WPILib’s command-based framework.

That aside, here are some things I found:

  1. You may want to review your gyro code. NavX values need to be inverted, or the getRotation2d() or getRotation3d() methods should be used, since they handle this for you. The NavX returns rotation in CW+, but WPILib expects CCW+.
  2. NavX rotation is continuous. You may want to use Math.IEEERemainder to bring it into range (-180, 180]
    Here’s you code:
public Rotation2d getRotation2d()
{
    return Rotation2d.fromDegrees(360 - (navx.getAngle() - zeroOffset) + addition); //TODO: this is dumb
}

Here’s a suggestion:

public Rotation2d getRotation2d()
{
    return Rotation2d.fromDegrees(Math.IEEEremainder(gyro.getAngle(), 360.0d) * -1.0d);
}
  1. You might want to review this method, depending what you’re using it for. It won’t return rotation within the unit circle WPILib uses, with a range of (-180, 180].
/**
* Get the rotation of the robot within the unit circle.
*/
public Rotation2d getRobotRotationInCircle() {
    return Rotation2d.fromRadians(getRobotRotation().getRadians() % (2*Math.PI));
}
  1. There are many layers of abstraction on your Joystick input, so I’m not able to understand what it’s doing. The comment in the code makes you think you’re in the same boat. In any case, X, Y, and rotation need to be inverted. Look at this draft documentation page for some guidance.
drivetrain.setInput(
    JoystickInput.getRight(driverController, false, true), //TODO do these inverts need to be set to true or false? Last year x was set to true for both remotes
    JoystickInput.getLeft(driverController, false, true)
);