PID and Analog Feedback Encoder That Wraps


Have a TalonSRX attached to an absolute encoder (am-2899) defined as such:

_talon.configSelectedFeedbackSensor(FeedbackDevice.Analog, PIDLOOP_IDX, TIMEOUT_MS);
_talon.configSetParameter(ParamEnum.eFeedbackNotContinuous, 0, 0, 0, 0); // wrap the position (1023 -> 0)

PID is working as expected, but there is one thing that I’d like to change.

When the encoder is at 1000 (out of 1023) and we set it to 0, it will take the long way back around to 0. In other words, it will revolve -1000 instead of “knowing” that it could have just gone +24 and wrapped to 0.

Is this something the SRX PID algorithm could be adjusted for or is this something that I have to handle a different way. IIRC PIDCommand does the short trip when I used it in a different context. Maybe I’m not thinking about this correctly… :confused:


I’d raise a flag with Omar at CTRE about this. I’d also like to see wrapping being handled natively.

You can always check your current position and set the new target equal to 360 or 0, whichever is closer. The easiest way to do that would be to check
current_pos modulo ticks_per_rotation
and see if that’s bigger than half a rotation. If it is, make
your target. That will make your target equal to the closest multiple of 360. Of course, add your target onto that if your target is greater than 0.

Always check the github.

I will have to play around now you generated some question. Can you configure a encoder to reset each rotation or will you return a value of 720 after two rotations?

We currently run a PIDcommand to spin our robot to heading. An incomplete snip shown sets the PIDController().setContinuous(true)

public Drive_Turn_To_Setpoint_InTeleop(double x, double y, double setpoint) {
        super("turnController", kP, kI, kD, 0.02);
        getPIDController().setInputRange(-180.0f,  180.0f);
        getPIDController().setOutputRange(-0.75, 0.75);
        m_x = x;
    	m_y = y;
        m_setpoint = setpoint;

When we command a heading it all way takes the most direct path. If we are at 89 deg and command -90 it goes through 0, If we are at 91 deg it will go through 180. We are using a NavX gyro and believe the .getAngle() already returns the modulo of the rotation since reset.

[strike]Looks like CTRE needs to implement a set feedback as setContinuous. Maybe also set feedback as linear (ex drive trains) or rotational (ex shooter turret with 360 dof)[/strike]

Looks like they do

     * Disables wrapping the position. If the signal goes from 1023 to 0 a motor 
     * controller will by default go to 1024. If wrapping the position is disabled,
     * it will go to 0;

configFeedbackNotContinuous(boolean feedbackNotContinuous, int timeoutMs)

Thanks for the reply.

I’m a little new to some of this so bear with me. Even if I know the shortest path, you still have to deal with encoder clicks. With PID, I don’t know how to say “hey, go from where you are at position 1000 to position 0, but increase your values to get there” (i.e. 1000-> 1023 -> 0) Seems like all I have is a set position function and it does the rest.

That’s interesting. The version of CTRE-phoenix-java i’m using ( doesn’t have that function. Also the docs seem to point to using eFeedbackNotContinuous (see section in the software reference manual). More digging to do I guess.