Normalize angle range

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:

    while(output >= 2.0*M_PI){ output -= 2.0*M_PI; }
    while(output <  0.0)     { output += 2.0*M_PI; }

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; }

Computing the difference between two angles

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; }


Home