以参考圆方式将弧度转换为度数
Converting radians to degrees in a reference-circle manner
上下文:我正在用 C 为机器人创建一个地图重新规划器,它应该根据哪些红外传感器获得高读数,将环境中的障碍物添加到地图上。
为此,我需要检查机器人在 IRL 与内部地图(指向北方)中的定位方式。但出于某种原因,我有时会在转换中得到负值。知道我做错了什么吗?
永远不应该有任何负值。允许的值应介于 0-360 之间。到目前为止,我有时会得到负值。
#define PI 3.14159265358979323846264338327950
#define DEG(x) (x*57.2957795130823208767981548141)
代码:
float currentRot = now.th; //current rotation-reading in RAD from function.
if(currentRot > PI){ //normalize values
currentRot = currentRot - 2 * PI;
}
if(currentRot < -PI){
currentRot = currentRot + 2 * PI;
}
currentRot = fmod(currentRot,PI*2); //convert into RAD-modular
currentRot = DEG(currentRot); //convert to degrees
你知道我做错了什么吗?
这里:
if(currentRot > PI){ //normalize values
currentRot = currentRot - 2 * PI;
}
if(currentRot < -PI){
currentRot = currentRot + 2 * PI;
}
你尝试标准化为 -π < currentRot
< π,然后你这样做:
currentRot = fmod(currentRot,PI*2);
which "Returns the floating-point remainder of numer/denom" (ref),意思就是结果的符号一样.
这并不能确保禁止负值。我的意思是你的范围不是从 0 开始的。
π 不能精确地表示为 float
,因此任何 mod-ding 与 fmod(currentRot,PI*2);
或比较 if(currentRot > PI){
可能无法提供边缘情况的预期结果.
请注意 currentRot = currentRot + 2 * PI;
是 (foat) + (double)
并转换为 float
。这种转换的边缘是避免轻微负面结果的问题。最好避免将 float
和 double
数学混合用于此敏感转换。
即使有 @M Oehm 的好评,不精确 PI
和混合 float/double
数学也会导致负值 currentRot
。
相反,先将弧度转换为度,然后 mod。
float RadianToDegree(float r);
float d = (float)(PI/180.0) * r;
d = fmodf(d, 360.0f);
if (d < 0.0f) d += 360.0f;
return d;
}
结果将为 [0.0 - 360.0](含)。
Mod-ding by 360 预计不会招致 round-off error.
将 fmodf()
与 float
结合使用,将 fmod()
与 double
结合使用以避免不必要的转换。
在更高层次上,"The allowed values should lie between 0-360" 牺牲精度的目标。考虑 -180 - +180 之间的主要范围。
上下文:我正在用 C 为机器人创建一个地图重新规划器,它应该根据哪些红外传感器获得高读数,将环境中的障碍物添加到地图上。
为此,我需要检查机器人在 IRL 与内部地图(指向北方)中的定位方式。但出于某种原因,我有时会在转换中得到负值。知道我做错了什么吗?
永远不应该有任何负值。允许的值应介于 0-360 之间。到目前为止,我有时会得到负值。
#define PI 3.14159265358979323846264338327950
#define DEG(x) (x*57.2957795130823208767981548141)
代码:
float currentRot = now.th; //current rotation-reading in RAD from function.
if(currentRot > PI){ //normalize values
currentRot = currentRot - 2 * PI;
}
if(currentRot < -PI){
currentRot = currentRot + 2 * PI;
}
currentRot = fmod(currentRot,PI*2); //convert into RAD-modular
currentRot = DEG(currentRot); //convert to degrees
你知道我做错了什么吗?
这里:
if(currentRot > PI){ //normalize values
currentRot = currentRot - 2 * PI;
}
if(currentRot < -PI){
currentRot = currentRot + 2 * PI;
}
你尝试标准化为 -π < currentRot
< π,然后你这样做:
currentRot = fmod(currentRot,PI*2);
which "Returns the floating-point remainder of numer/denom" (ref),意思就是结果的符号一样.
这并不能确保禁止负值。我的意思是你的范围不是从 0 开始的。
π 不能精确地表示为 float
,因此任何 mod-ding 与 fmod(currentRot,PI*2);
或比较 if(currentRot > PI){
可能无法提供边缘情况的预期结果.
请注意 currentRot = currentRot + 2 * PI;
是 (foat) + (double)
并转换为 float
。这种转换的边缘是避免轻微负面结果的问题。最好避免将 float
和 double
数学混合用于此敏感转换。
即使有 @M Oehm 的好评,不精确 PI
和混合 float/double
数学也会导致负值 currentRot
。
相反,先将弧度转换为度,然后 mod。
float RadianToDegree(float r);
float d = (float)(PI/180.0) * r;
d = fmodf(d, 360.0f);
if (d < 0.0f) d += 360.0f;
return d;
}
结果将为 [0.0 - 360.0](含)。
Mod-ding by 360 预计不会招致 round-off error.
将 fmodf()
与 float
结合使用,将 fmod()
与 double
结合使用以避免不必要的转换。
在更高层次上,"The allowed values should lie between 0-360" 牺牲精度的目标。考虑 -180 - +180 之间的主要范围。