Best PID profile for in-place turns?

I think you’re misunderstanding. The point is you need to compensate for this at a lower level, in your swerve module drive motor PID, by adding a kS there, rather than at a higher level in a gyro based PID.

2 Likes

I agree with them; that’s what you should start with. If your rotation PID does respond to minor errors, it should be the problem of the feed-forward.

However, I think 0.5 degrees is still too small a tolerance.

If what you are saying is true, decreasing the error tolerance from 3 degrees to 0.5 degrees would only reduce the aiming error from 10 degrees to 7.5 degrees, which has no significant impact on your shots’ accuracy. Instead, it could hurt your shots’ accuracy since the chassis might oscillate if the tolerance is too low. The rotation returned from the vision is always jumping in a range of ±1 degrees. As a result, your chassis will be shaking all the time to try to correct the error.

My point was - we’re trying to avoid getting into the individual motor control by using the SwerveDrivetrain classes provided by CTR that you get from Phoenix Tuner X SwerveBuilder. Basically those hide the control of the individual swerve modules and only ask you to supply their configuration in an object constructed like this:

      public static final SwerveModuleConstantsFactory ConstantCreator = new SwerveModuleConstantsFactory()
          .withDriveMotorGearRatio(kDriveGearRatio)
          .withSteerMotorGearRatio(kSteerGearRatio)
          .withWheelRadius(kWheelRadiusInches)
          .withSlipCurrent(kSlipCurrentA)
          .withSteerMotorGains(steerGains)
          .withDriveMotorGains(driveGains)
          .withSteerMotorClosedLoopOutput(steerClosedLoopOutput)
          .withDriveMotorClosedLoopOutput(driveClosedLoopOutput)
          .withSpeedAt12VoltsMps(kSpeedAt12VoltsMps)
          .withSteerInertia(kSteerInertia)
          .withDriveInertia(kDriveInertia)
          .withSteerFrictionVoltage(kSteerFrictionVoltage)
          .withDriveFrictionVoltage(kDriveFrictionVoltage)
          .withFeedbackSource(SteerFeedbackType.FusedCANcoder)
          .withCouplingGearRatio(kCoupleRatio)
          .withDriveMotorInitialConfigs(driveInitialConfigs)
          .withSteerMotorInitialConfigs(steerInitialConfigs)
          .withCANcoderInitialConfigs(cancoderInitialConfigs);

I do see, however, the kDriveFrictionVoltage there, and will need to evaluate whether I just need to change it. It’s set to 0.25 right now,and that should have fit 0.02 minimum joystick input. But I guess I may need to increase it.

Actually to avoid jitter we do not provide dynamic correction after the angle is measured. Meaning - once it’s measured, we do not correct it while turning based on camera until the correcting move is done. Most of the time it’s sufficient.

1 Like

You don’t need to manually control the individual motors to add a kS. You can set the kS for the drive motors in the driveGains and switch the drive motors to use PID instead of open-loop control using the SwerveRequest’s DriveRequestType. Note that if you’re currently controlling the robot using open-loop control for the drive motors, it will drive a bit differently using PID, and you will need to tune the other PID gains (namely kP, kS, and kV).

3 Likes

Gottha, that would prevent jitter. But still, that also means much of your aiming errors do not come from the 3 degrees tolerance.

Thanks for pointing to the example!! I will take a look at that.

Question - why the Phoenix X generates Voltage-based open loop vs PID driving from the configurator? Is it because the open loop does not need to be characterized separately? And you’re right - the kS is set to 0 in the example (we did that as well in our code - as it came out of the configurator)

However, we ran the robot through the characterization separately. So, we got some values we can try using.

The swerve requests default to open-loop voltage both because it doesn’t require any additional tuning and because many teams prefer it for teleop control. When using closed-loop control for the drive motors, even a small change in the velocity request can result in a large (but brief) acceleration to get there, as the PID tries to close the velocity error as fast as it can. This is desirable for autonomous control, but it may not match the driver’s preferences for teleop control.

2 Likes

Is it possible to do a dynamic change from one more to the other and back?

Since the DriveRequestType is just another parameter of the swerve requests (like VelocityX or VelocityY), you can set up your code to swap between closed-loop and open-loop control if you’d like. However, most teams stick to one of the two for a given SwerveRequest object, as they just stick with whichever the drivers prefer.

So, as an update - we tried to use the software PID on the chassis without going to the lower level.

It appears we’re actually fairly successful in achieving 1 degree tolerance within the first 30 minutes or so of the calibration process on degree range between 5 and 25 degree turns, which is pretty typical when needing to adjust heading to turn to target.

We had to end when we needed to end our session today. however, it appears it will be possible to calibrate the PID within half-degree tolerance.
We set trapezoid profile, and adjusted the P and max speed/acceleration values experimentally. It appears that for best results the P and/or max V and A as well as min omega would need to change a little on the trapezoid profile, depending on the angle of turn. Right now I can get 1 degree tolerance more than 60% of the time with both small and large angles, but with the slightly different numbers. The worst precision I get is 2 degrees on 20-30 degree turns. My 5-dgree turns are under 1 degree of tolerance. I have not experimented yet with smaller degrees.
The code is in the same place, if you want to take a look. We will continue the calibration this coming week.

1 Like

Congratulations on your success! I will definetly take a look at your code. Thanks! :grinning:

It seems I did not indicate a link to our code for this. So, here it is:

It’s in the TurnToRelativeAngleSoftwarePIDCommand

2 Likes