SDS MK4 SysID - Rotational

I’m using SysID to get feedforward values for the SDS MK4 and the values popping out of the tests are not making sense.

CANcoder port is correct, motor port is correct. Did this on two different modules and same result. One full rotation reports the encoder detected ~0.5 radians.



I’m still not getting any other results. I must be missing something here, but I’ve looked through my settings multiple times, I keep seeing the exact same value for one rotation, “0.5…” radians

Can anyone take a look at this and see if I am setting this up wrong? I see no reason this shouldn’t output correct results.

It looks like you’re trying to characterize the swerve rotation motor. I don’t think many people bother to do that. Our team started with the kP that was in the SDS swerve-template and plugged that into our thetaController. If I recall correctly it’s in the range of kP = 2.0 to 3.0. Adjust as needed. zero kI and zero kD.

If you do use SysID, you should use the onboard TalonFX encoder as that is what is used for controlling the serve module orientation. The CANCoder is just used to get an accurate start angle, not for controlling PID positional control. In fact that might be your problem right there if the gear ratio between the CANcoder and the swerve module aren’t the same on Mk4s. I’m thinking they aren’t.

So this is constructor of my SwerveModule class. How do i take absolute position of the CANcoders, then swap to the integrated encoders? That is what is messing me up a bit.

I know how to access the encoders of the TalonFX and use them everywhere else, but switching from one to another, is confusing me. Or as you say “CANCoder is just used to get an accurate start angle”…how do I code that?

 public SwerveModule(
  int driveMotorChannel,
  int turningMotorChannel,
  int turningEncoderPorts,
  double angleZero) {

// Initialize the motors
m_driveMotor = new WPI_TalonFX(driveMotorChannel);
m_turningMotor = new WPI_TalonFX(turningMotorChannel);

// Configure current lmits for motors - prevents disabling/brownout
m_driveMotor.configSupplyCurrentLimit(new SupplyCurrentLimitConfiguration(true, 30, 35, 0.5));
m_driveMotor.configSupplyCurrentLimit(new SupplyCurrentLimitConfiguration(true, 30, 35, 0.5), 100);

// Configure the encoders for both motors

m_driveMotor.configSelectedFeedbackSensor(TalonFXFeedbackDevice.IntegratedSensor, 0, 0);
this.m_turnEncoder = new CANCoder(turningEncoderPorts);
this.m_turnEncoder.configMagnetOffset(-1 * angleZero);
this.m_turnEncoder.setStatusFramePeriod(CANCoderStatusFrame.SensorData, 10, 100);

m_turningMotor.setStatusFramePeriod(StatusFrameEnhanced.Status_3_Quadrature, 255);
m_turningMotor.setStatusFramePeriod(StatusFrameEnhanced.Status_2_Feedback0, 255);
m_turningMotor.setStatusFramePeriod(StatusFrameEnhanced.Status_1_General, 255);

m_turningPIDController.enableContinuousInput(-Math.PI, Math.PI);


We do this, maybe a good hint for you. We use the cancoder for angle and not the FX builtin.
We also set all configs in code to make sure they weren’t accidentally changed elsewhere.

public void resetEncoders()
public double getTurningEncoderPosition()
    return turnEncoder.getAbsolutePosition(); 
CANCoderConfiguration CANCoderConfigs = new CANCoderConfiguration();
CANCoderConfigs.velocityMeasurementPeriod = SensorVelocityMeasPeriod.Period_100Ms;
CANCoderConfigs.velocityMeasurementWindow = 64;
CANCoderConfigs.absoluteSensorRange = AbsoluteSensorRange.Unsigned_0_to_360;
CANCoderConfigs.sensorDirection = false; // CCW
CANCoderConfigs.initializationStrategy = SensorInitializationStrategy.BootToAbsolutePosition; // error on get "On boot up, set position to zero.";
CANCoderConfigs.sensorCoefficient = 0.087890625; // 4096 ticks to degrees
CANCoderConfigs.unitString = "degrees";
CANCoderConfigs.sensorTimeBase = SensorTimeBase.PerSecond;
CANCoderConfigs.customParam0 = 0;
CANCoderConfigs.customParam1 = 0;
CANCoderConfigs.magnetOffsetDegrees = turnEncoderOffset;

Our team opted to use the Swerve Drive Specialties swerve-lib with our SDS modules. Setup was pretty easy.

It was a little work to add odometry and path following. Here is a link to our off season project with odometry and path following. This branch has a few other things going on, primary a copy of 6391 fork of the swerve lib that was ported to 2022 WPIlib. Swerve-lib is now supports 2022 WPIlib directly.

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.