Unexplainable Motor behaviour, Asymmetric PID Error

I’m working on a PID control system for the robot that uses PID to accurately maintain an encoder rate based on joystick inputs, but there’s a really strange issue with one of the motors. Note: Im coding it in java through vscode

@Override

  public void execute() {

TargetLeftRate = (speedy.getAsDouble() - speedx.getAsDouble())*Constants.maxWheelRate;

TargetRightRate = (speedy.getAsDouble() + speedx.getAsDouble())*Constants.maxWheelRate;


TargetLeftRate = Math.max(-Constants.maxWheelRate, Math.min(Constants.maxWheelRate, TargetLeftRate));

TargetRightRate = Math.max(-Constants.maxWheelRate, Math.min(Constants.maxWheelRate, TargetRightRate));


leftPID.setSetpoint(TargetLeftRate);

rightPID.setSetpoint(TargetRightRate);


if (Math.abs(TargetLeftRate) - Math.abs(m_drive.getLeftEncoderRate()) < 10) {

leftSpeed = leftSpeed + leftPID.calculate(m_drive.getLeftEncoderRate());

    } else{

leftSpeed = TargetLeftRate/Math.abs(TargetLeftRate);

    }


if (Math.abs(TargetRightRate) - Math.abs(m_drive.getRightEncoderRate()) < 10) {

rightSpeed = rightSpeed + rightPID.calculate(m_drive.getRightEncoderRate());

    } else{

rightSpeed = TargetRightRate/Math.abs(TargetRightRate);

    }




m_drive.tankDrive(leftSpeed,rightSpeed);


SmartDashboard.putNumber("DrivePID/LeftEncoderRate", m_drive.getLeftEncoderRate());

SmartDashboard.putNumber("DrivePID/RightEncoderRate", m_drive.getRightEncoderRate());

SmartDashboard.putNumber("DrivePID/TargetLeftRate", TargetLeftRate);

SmartDashboard.putNumber("DrivePID/TargetRightRate", TargetRightRate);

SmartDashboard.putBoolean("DrivePID/PIDinUse?", Math.abs(TargetLeftRate) - Math.abs(m_drive.getLeftEncoderRate()) < 5);

SmartDashboard.putNumber("DrivePID/LeftPID", leftPID.calculate(m_drive.getLeftEncoderRate()));

SmartDashboard.putNumber("DrivePID/RightPID", rightPID.calculate(m_drive.getRightEncoderRate()));

  }




// Called once the command ends or is interrupted.

  @Override

public void end(boolean interrupted) {

m_drive.tankDrive(0, 0);

  }

For testing, I’ve suspended the robot so that both wheels are spinning freely.

When I run the code, the right wheel consistently tracks well and maintains low error in all cases. But the left wheel behaves differently depending on direction:

When both wheels rotate in the same direction, the left wheel also maintains low error.

When the wheels rotate in opposite directions (e.g., turning in place), the left wheel shows significantly higher error.

So essentially, the issue only appears when the left motor is running in the opposite direction to the right motor.

I’m trying to figure out what could cause this kind of asymmetric behavior, whether it’s related to PID tuning, motor characteristics, encoder feedback, or something else in the control logic.

Any ideas or things I should check would be appreciated.

Two thoughts.
1 - problems with negative numbers. Your if statement should probably be the absolute of the subtracted value, not the absolute of each value subtracted.
Should (-100 - 100) be 0 or -200?

2 - When ever you are not within 10 of the target rate you are going back to driving the motors at 100%. Why not let the PID adjusted rate continue to drive you closer to your goal?

Hello, thanks for the insight,
I had actually kept it like that on purpose, since I wanted the motors to run at full power whenever they’re not within a close range of the target setpoint.

And by subtracting the absolutee values instead of the absolute of the differencee, the acceptable range is such that if the current rate is greater than the setpoint, it won’t cause issues. For example, if the setpoint was 10, and currently the motor was running at 16, if I used the absolute of the subtracted value, then the PID wouldnt engage and the motor would run at full speed, since it thinks it needs to go faster to reach the setpoint.