以参考圆方式将弧度转换为度数

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。这种转换的边缘是避免轻微负面结果的问题。最好避免将 floatdouble 数学混合用于此敏感转换。


即使有 @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 之间的主要范围。