I think it depends what you are trying to do. When the desired motion is to turn in place THEN drive somewhere, we're pretty happy to let the turn in place motion overshoot or undershoot as the drive motion should straighten it out (so long as the turn controller is running in parallel with the "drive straight" controller).
If you are trying to turn in place then shoot a ball or a frisbee, I think a bunch of your issues can be taken out by an I term that only applies at low error. Basically:
Code:
out = err*kp + (err-last_err)*kd;
if (err < 5 degrees) {
sum += err;
out += sum*ki;
} else {
sum = 0;
}
To tune this controller, increase KP until the robot is just overshooting, then increase KD until it stops a bit faster with less overshoot. At this point you should settle within a few degrees of your target and you can increase KI (this should be an order of magnitude or 2 smaller than KP) until it snaps into place.