MAXswerve issues with pigeon2"

Hello everyone,

I’m a member of a rookie team, and I’m working on programming a robot that uses the MAXSwerve drivetrain in Java. I’ve successfully implemented the Pigeon2 IMU in my code, but I’m facing an issue where the robot doesn’t exhibit the expected swerve behavior.

Currently, the robot can move forward, backward, and rotate. However, it doesn’t perform true swerve dynamics, like moving forward while simultaneously rotating on its axis (for example, translating and rotating at the same time). Instead, it seems like the robot is relying more on the RoboRIO’s internal IMU, even though I’ve integrated the Pigeon2 into the code.

From what I can tell, the Pigeon2 is functioning correctly, but the robot’s control doesn’t seem to reflect proper swerve movement. Could someone help me troubleshoot this issue or point me in the right direction? I suspect I might be missing something in the implementation of field-oriented control or gyro settings.
Here’s the link to the code on GitHub: GitHub - G8d8i/MAXSwerve_Pigeon2: his is the initial version of the program development for the control of an FRC robot, which uses the MAXswerve as its drivetrain. The Pigeon 2 has been implemented to work as the IMU. The base code is based on the REV Robotics example..

Any advice or examples of how I can ensure the Pigeon2 is properly utilized for swerve drive would be greatly appreciated!

Thank you in advance!

Hey there!

From the code, it doesn’t look like it’s using the roboRIO internal IMU at any point.

I believe this is an issue with the way the Pigeon returns a yaw value. Basically, the gyroscope will return a yaw in degrees anywhere between -368640.0 to 368639.99. This means that as the robot keeps turning, the angle will continue adding up. While the swerve subsystem is looking for a robot orientation using a Rotation2D with values between 0 and 360 degrees, you are providing it values way out of that range.

This can be fixed by simply applying a modulus to your heading value wherever it is used in the code:

Rotation2d.fromDegrees(pidgey.getYaw().refresh().getValue() % 360.0);

This limits the possible output range to [0,360), which should allow the MaxSwerve to drive in a field-oriented manner.

1 Like

What do you mean by “the robot’s control doesn’t seem to reflect proper swerve movement” ?

Thank you very much for your help, aaditsangvikar!

I followed your guidance and implemented the suggested modifications throughout the code that uses Rotation2d. However, the problem persists: I still can’t execute translation and rotation simultaneously. Do you have any more tips that could help me?

Hello AvocadoPeel,

How are you?

When I say that the swerve movement isn’t adequate, I’m referring to the fact that I can’t perform the translation and rotation maneuver simultaneously. In other words, I would like the robot to move while rotating around its own axis. Do you have any tips that could help me?

when you try to perform translation and rotation simultaneously, what exactly happens? does it just only perform one of them? or does something else happen?

I cloned the github repo and added a basic simulation, it looks like something really funky is happening with the desired module states, I think it has something to do with the way you’re using m_chassisAngularOffset and the swerve module state optimization.

Issues like this are what waste 70-80% of my time during the season. I love it! :cry:

Does your robot have an 11" wheel base with 2.25" wheels? That is small. The standard wheels are closer to 3". And most wheel bases are >18.5".

How is your Pigeon mounted? Is it flat and upright? Or is in mounted face down, under the robot? If it is upright the Pigeon yaw value is negated. We did this `Rotation2d.fromDegrees(-m_gyro.getAngle())', for example. But making sure it is CCW+.

Also, you are current limiting the NEOs to 20 amps, which is sort of low.

Hello everyone!

I apologize for my absence, but I’ve been conducting some tests based on the suggestions you all provided.

The good news is that I managed to solve the issue! The solution was simply setting the fieldRelative variable to true. After doing this, the robot was able to perform both translation and rotation movements simultaneously, gaining the full dynamic behavior of the SWERVE system.

Does this make sense to you? In my mind, the robot should move the same way regardless of the field reference.

Do you also use this variable set to true? My drivers are struggling to adapt to this new control mode. Do you have any tips to help with this transition?

Thanks in advance!

Field (relative) centric versus robot centric are two different operating paradigms in swerve. Typically teams will bind these modes to a button and toggle between them. Here is a helpful image to explain the difference :

heres how your modules need to move for the robot chassis to move in different ways it should :

Hopefully these images help you understand the underlying mechanics of how swerve works.

1 Like

Thank you very much, Aopalka! I completely understand how it works now!

I would also like to thank everyone for their contributions!

Problem solved, and I’ll continue with my studies!

1 Like