PID Control - Talon SRX not going backward

We have a 4-CIM differential drive with Grayhill encoders feeding into the TalonSRXs. We created a DriveDistance command which takes an input parameter as follows:

public DriveDistance(double offsetInches, double tolerance, double angleTolerance) {
  this.offsetInches = offsetInches;
  this.tolerance = tolerance;
  this.angleTolerance = angleTolerance;

tolerance is used in the isFinished() method to determine if we drove far enough. angleTolerance will be a future enhancement is is not currently used.

Our execute() method includes


The PIDDrive method is as follows:

public void PIDDrive(double dist) {

leftMaster.set(ControlMode.Position, dist * 1024.0 / RobotMap.WHEEL_CIRCUMFERENCE);
rightMaster.set(ControlMode.Position, dist * 1024.0 / RobotMap.WHEEL_CIRCUMFERENCE);


If we pass in “36” for offsetInches, it drive forward 36 inches. But if we pass in “-36”, it still drives forward 36 inches.

Since it drives forward correctly, we’re pretty sure we have the encoders in phase with the talons.

Any suggestions on why it doesn’t seem to recognize the negative sign?

Thanks for the help.

Instead of using a negative number, use SetPosition to set your encoder to 36, and change your setpoint to 0.

Can you post your PID tuning? I think that the F value is for one direction movement only, but I could be wrong.

This is incorrect. kF, like the other closed-loop gains, works for both positive and negative setpoints.

I would recommend doing a self-test (in the web-interface) of one of your master motor controllers both when setting a positive setpoint and when setting a negative setpoint.

Comparing the two self-tests will allow you to confirm that the setpoints are being set properly and what your output should be.

Our Lead Programmer was able to get around this by passing the negative of the requested distance to the left side PID (TalonSRX in position mode) and positive to the right side.

But it only works if we do this as an autonomousCommand in autonomousInit() and then wait until teleopInit() to cancel the autonomous command and then construct a new DifferentialDrive passing in a SpeedControllerGroup for the left side and one for the right side. Then our standard arcade drive X_Box controller works fine in teleop.

If we construct the DifferentialDrive in RobotInit(), the autonomousCommand doesn’t work. It only drives very briefly and then stops.

Does anybody know what a SpeedControllerGroup does to the TalonSRXs in that group or what DifferentialDrive does to the SpeedControllerGroups that are passed in?

One would have thought that a SpeedControllerGroup would automatically set the second (and third if present) SpeedController to slave of the first and that DifferentialDrive would have inverted one side, but that doesn’t appear to be the case. But one or both are apparently doing something to our TalonSRX configuration since it changes the behavior of the TalonSRXs in PositionMode.

Any insight would be appreciated. Our goal, of course, is to configure the drive train once in RobotInit() and use the same configuration throughout for either PID driving or joystick driving. The idea of changing the configuration in teleopInit() really bugs me and, to be fair, it also bugs our Lead Programmer. He’s just trying to get something to work.

I haven’t spent a lot of time on it, but I noticed that if we created a DifferentialDrive object that we would have problems using the closed loop control in AUTO. I am thinking that the DifferentialDrive turns on the motor safety enable. I believe if you don’t update the DifferentialDrive with a new value repeatedly it will shut down the motor controllers.

What I found was happening during AUTO was that the motors were turning on an off continually. Setting the motor safety to false solved this. Whether it is safe or not is another question right now.

Another thing I found is that DifferentialDrive handles a lot of the book keeping for the motor direction. I had to manually set the motor invert on the right side of the robot while using AUTO and the closed loop control.

My big problem was that I thought if I inverted the master motor the slave motor would also invert. I spent a lot of time having the motors fight against each other until I figured that out.