# How do I convert an Angle to the range [-pi,pi]?

This topic is 2040 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

An arbitrary positive or negative Angle. I am using C++.

##### Share on other sites
From what? What's wrong with angle = 1.23456?

##### Share on other sites
pi being 3.14, 1.23456 is a valid angle.
I have an exponential Model f(x) that for a Speed x gives f(x) the Maximum absolute Value of the Angle you can turn at that Speed. f(x) is in the range[0,pi].
I also use the inverse function i(y). That given an Angle y gives you the Maximum Speed at which you can turn y radians.
If y is not in the range [0,pi], i(y) will make no sense.

##### Share on other sites
If you just want to convert radians into a range, you can either wrap or clamp. Presumably you want to wrap (So that 2*pi == 0), in which case use fmod

[Edited by - Evil Steve on March 31, 2010 9:34:19 AM]

##### Share on other sites
Quote:
 Original post by Evil SteveIf you just want to convert radians into a range, you can either wrap or clamp. Presumably you want to clamp wrap (So that 2*pi == 0), in which case use fmod

corrected?

##### Share on other sites
Quote:
Original post by phresnel
Quote:
 Original post by Evil SteveIf you just want to convert radians into a range, you can either wrap or clamp. Presumably you want to clamp wrap (So that 2*pi == 0), in which case use fmod

corrected?
Whoops, fixed [smile]

##### Share on other sites
Yes I want to wrap. So when an Angle becomes 3.15 I want it to be -3.13 .
I found a good Solution:
If x is any Angle positive or Negative then
x = ::atan2 ( ::sin ( x ), ::cos ( x ) ) ;

will be between -pi and pi. Not as efficient as fmod() but more compact.

##### Share on other sites
I'll note that fmod is pretty slow, and so is atan2(sin, cos). I find that most of the time I need to rewrap angles, it occurs in situations where I know that I will only need to either add of subtract 2*pi once from my angle to get one in the range I want -- and I find that this code is noticeably faster. It's basically a specialization of fmod for when you know something additional about its input:

const inline double rewrapAngleRestricted(const double angle)// This function takes an angle in the range [-3*pi, 3*pi] and// wraps it to the range [-pi, pi].{  if(angle > pi)    return angle - TWO_PI;  else if(angle < -pi)    return angle + TWO_PI;}

You'd need to be careful to package this up in a way that makes sure that external code doesn't see these restrictions though; otherwise your code could get pretty brittle. One way to do this is to have an "angle" class that does this stuff automatically.

##### Share on other sites
I use the same for warping as Emergent suggests (in other situations too).
In most cases, it's enough, since you cannot increment/decrement with a value that's comparable to the interval.
If there's a little chance for a bigger increment to occur, then you could use a loop (a clever loop, which I can't think of now...).

Or use the slower method:
angle += increment;if( increment > interval || increment < -interval )   angle = slow_wrap(angle);else   angle = fast_wrap(angle);
Sorry, I came up with this at the moment, can be totally stupid...

EDIT: wrap or warp? My English is *sigh*

##### Share on other sites
As has been mentioned in this forum many times, you can probably do whatever you are doing without using angles. Representing a 2D heading as a unit vector often results in code that is much cleaner (fewer corner cases to consider) and faster to execute.

If you are familiar with complex numbers, you can also think of that 2D unit vector as a complex number, since multiplying by it results in the correct rotation.

• 9
• 13
• 41
• 15
• 13