在 C++ 代码中处理 Angle Wrap
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11498169/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Dealing with Angle Wrap in c++ code
提问by Fantastic Mr Fox
Is there a way to safety and simply deal with angle wrap with the minimum number of case statements.
有没有一种安全的方法,只需用最少的 case 语句处理角度包裹。
Angle wrap occurs when using a particular representation for angle (either 0-360 deg or -180 - 180 deg (or equivalent in radians)) and you wrap over the angle. For example say you have an angle of -170, and you subtract 50 deg. You mathematically add up to -220 but should actually be +140 deg.
当使用特定的角度表示(0-360 度或 -180 - 180 度(或等效的弧度))并且您在角度上进行环绕时,会发生角度环绕。例如,假设您的角度为 -170,然后减去 50 度。你在数学上加起来是 -220,但实际上应该是 +140 度。
Obviously you can check for this using:
显然,您可以使用以下方法检查:
if (deg < -180) { 180 - abs(deg + 180); }
or similar. But firstly you need multitudes of checks and secondly it doesn't work if you wrap twice.
或类似。但首先你需要多次检查,其次如果你包装两次就行不通了。
The second case where this is prevalent is in the interpolation between two angles.
第二种普遍存在的情况是两个角度之间的插值。
For Example, say I have an angle of -170 deg and 160 deg and I want halfway in between them. A common way to do this is ang1 + 0.5(ang2-ang1)
but in the example i have provided it will cause the angle to be -5 deg when it should be 175.
例如,假设我有一个 -170 度和 160 度的角度,我想要在它们之间的中间。一种常见的方法是,ang1 + 0.5(ang2-ang1)
但在我提供的示例中,它会导致角度为 -5 度,而应该是 175 度。
Is there a common way to handle angle wrap in these scenarios?
在这些情况下是否有处理角度包裹的通用方法?
回答by Mysticial
For completeness I'll include both [0, 360)
and [-180, 180)
normalizations.
为了完整起见,我将同时包含[0, 360)
和[-180, 180)
规范化。
You will need #include <math.h>
.
您将需要#include <math.h>
.
Normalize to [0,360)
:
标准化为[0,360)
:
double constrainAngle(double x){
x = fmod(x,360);
if (x < 0)
x += 360;
return x;
}
Normalize to [-180,180)
:
标准化为[-180,180)
:
double constrainAngle(double x){
x = fmod(x + 180,360);
if (x < 0)
x += 360;
return x - 180;
}
The pattern should be easy enough to recognize to generalize to radians.
该模式应该足够容易识别以推广到弧度。
Angle Bisection:
角平分:
double angleDiff(double a,double b){
double dif = fmod(b - a + 180,360);
if (dif < 0)
dif += 360;
return dif - 180;
}
double bisectAngle(double a,double b){
return constrainAngle(a + angleDiff(a,b) * 0.5);
}
This should bisect an angle on the "smaller" side. (warning: not fully tested)
这应该在“较小”的一侧平分一个角度。(警告:未完全测试)
回答by dmuir
I find using remainder()
from the math library is convenient. Given an angle a
, to constrain it to -180, 180 you can just do:
我发现使用remainder()
数学库很方便。给定一个角度a
,要将其限制为 -180, 180,您可以执行以下操作:
remainder(a, 360.0);
and change the 360.0
to 2.0 * M_PI
for radians
并更改360.0
到2.0 * M_PI
的弧度
回答by Fantastic Mr Fox
So if figured out a way to effectively do what i want using Mystical's approach to constraining the Angle. Here it is:
所以,如果想出一种方法来有效地做我想做的事情,使用 Mystical 的方法来约束角度。这里是:
This seems to work with any example i can think of.
这似乎适用于我能想到的任何示例。
回答by Charles Beattie
Normalise an angle to range [-180, 180)
将角度归一化到范围 [-180, 180)
deg -= 360. * std::floor((deg + 180.) * (1. / 360.));
Normalise an angle to range [0, 360)
将角度归一化到范围 [0, 360)
deg -= 360. * std::floor(deg * (1. / 360.));
Examples:
例子:
deg = -90
-> [0, 360)
:
deg = -90
-> [0, 360)
:
deg -= 360. * std::floor(-90 / 360.);
deg -= 360. * -1;
deg = 270
deg = 270
-> [-180, 180)
:
deg = 270
-> [-180, 180)
:
deg -= 360. * std::floor((deg + 180.) / 360.);
deg -= 360. * std::floor(480. / 360.);
deg -= 360. * 1.;
deg = -90;
回答by Hymanal
Map angle(+PI ~ -PI) to signed int value (or short value):
将角度(+PI ~ -PI)映射到有符号整数值(或短值):
angle_signed_short = angle_float / PI * 0x7FFFF;
Then you can add or sub value as normal. Then map back:
然后你可以像往常一样添加或子值。然后映射回来:
angle_float = angle_signed_short * PI / 0x7FFFF;