Gyro and PID control problem

We are trying to make out robot run a nice straight line in auto .So we choose the gyro and PID . But I seems it has some problem with it with Kp=0.3~1.It never work and is always unexpected. Is there any way to solve it?

If your PIDInput is the gyro angle in degrees, that kP seems fairly high. It should probably be below 0.1. A simple way of thinking about it is that if your error is 1 unit, your output will be equal to your kP. (e.g. if your kP = 0.3 and your error is 3 degrees, the output will set the turning rate to 0.9. Way too fast for such a small error)

I would also suggest having a kD of 0 for this as you start the loop with zero error and a kI somewhere in the neighborhood of 1/10th the kP value. Additionally, make sure you either zero your gyro when you begin the pid loop or set the set point of the loop to the gyro’s current value when the loop begins. For our team, we have the kP = 0.05 and kI = 0.001 but those values will be different for you.

I am assuming here that you are running some version of differential drive and have the output of the PID loop setting the rotation rate -1.0 to 1.0]. I’m not sure what unexpected results you are seeing so it’s hard to know what your problem is.

If you’re having trouble with the PID loop, you can use a more simple approach and record the current angle and multiply it by a kP value when setting the motor values. Just tune the kP until the robot drives as straight as possible and this should work well for most short distances.

Pseudocode:

changeHeading = currentHeading - startingHeading;
left_vel = forward_vel + (changeHeading * kP);
right_vel = forward_vel - (changeHeading * kP);

Your PID loop takes a variable and compares it to what you want that variable to be. It creates an output value from this error, which is used to steer your robot.

Two common problems I’ve encountered are:

  1. Forgetting to reset the gyro before you run your code. Otherwise your values may not line up with what you expect.
  2. The gyro returns a value from 0 to 360. This means if you start at angle 0, but turn left, the value may change from 0 to 359. Your PID loop now thinks your error is 359, when it should be a value of 1 degree. I’ve attached a function getAngleDifference which might help.

@Override
public double getAngle() {
double angle = -super.getAngle() % 360;
return (angle < 0) ? angle + 360 : angle;
}

public double getAngleDifference(double targetAngle) {
	double currentAngle = getAngle();
	double difference = targetAngle - currentAngle;

	if (difference &gt; 180) {
		difference -= 360;
	} else if (difference &lt; -180) {
		difference += 360;
	}

	return difference;
}