Suppose we would like to compute the orientation of something (e.g., the hand of a clock) after travelling a long angular distance.
The most straightforward (i.e., easiest to think about for me) way to normalize an angle of arbitrary size is to use two loops:
//input: [-inf ... inf), output [-pi ... pi)
double output = input;
while(output >= M_PI){ output -= 2.0*M_PI; }
while(output < -M_PI){ output += 2.0*M_PI; }
If you want a different range, note that only the comparison changes, not the addition/substraction:
It seems more mathmatical to do it with fmod
. However, as with integer modulo, the output range of fmod(x, threshold) is ( -threshold … threshold ), which makes things unintuitive (for me at least). It can’t be used to correctly confine the range directly to [ -pi … pi ), because the input values will always keep their sign. Thus pi+1 will be 1 and -pi-1 will be -1, which is not what we want (-pi + 1 and pi - 1 respectively). So my solution is to use fmod to shrink the range to ( -2pi … 2pi ) and then do the equivalent of one iteration of one of the above loops:
//input: [-inf ... inf), output [0 ... 2pi)
double output = fmod(input, 2.0*M_PI);
if(output < 0.0){ output += 2.0*M_PI; }
For the -pi to pi range, the fmod call needs to stay the same, but the range adjustment changes:
//input: [-inf ... inf), output [-pi ... pi)
double output = fmod(input, 2.0*PI);
if(output < -PI){ output += 2.0*PI; }
if(output > PI){ output -= 2.0*PI; }
When taking the difference between two (normalized) orientation angles, one gets one of two results, the clockwise or counter-clockwise angle. Most often I am interested only in the absolute deviation, i.e. the smaller of the two as a positive value.
The difference of two orientations can cover a range of 4 pi, e.g., when the orientations are given from -pi to pi, the minimum difference is (-pi - pi) = -2pi, the maximum (pi - -pi) = 2pi.
There are multiple ways to get the smaller angle in a regular range of 2pi, e.g.:
//smaller angle difference
//inputs: [-pi ... pi), output [-pi ... pi)
double angle_diff = std::abs(angle1 - angle2); //angle_diff: 0 - 2PI
//larger angle always is > PI, smaller is < PI. If the larger was computed, compute the smaller
if(angle_diff > M_PI){ angle_diff = 2.0*M_PI - angle_diff; }