检测 180 度旋转时出现问题

发布于 2024-10-21 14:54:10 字数 468 浏览 1 评论 0原文

我有一个算法可以计算物体旋转的量。

它计算 -180 到 180 度之间的值来处理顺时针和逆时针。然而,当旋转约为 180 度时,由于舍入,在比较形状的不同部分时,最终会检测到 -180 度和 180 度旋转的混合,具体取决于舍入发生的方式,这会使实际旋转产生相当大的偏差。答案是使用绝对值,但这最终会破坏旋转方向。

这是代码

 double newAngle = objOneAngle - objTwoAngle;
 if (newAngle< -180)
     newAngle += 360;
 else if (newAngle > 180)
     newAngle -= 360;

对于增强上述代码以处理 180 度旋转的最佳方法有什么想法吗?

编辑: 我想到的最明显的方法是将正值和负值分开,然后根据大小或其他一些指标选择最佳的集合,但一定有一个更简单更优雅的解决方案吗?

I have an algorithm that calculates the amount an object has rotated.

It calculates between -180 and 180 degrees to deal with both clockwise and anticlockwise. However when the rotation is just about 180 degrees, due to rounding it ends up detecting a mix of -180 and 180 degree rotations when comparing different parts of the shape, depending on how rounding occurs this throws the actual rotation out by quite a bit. The answer to this would be to use the absolute value however this ends up breaks rotation direction.

Here is the code

 double newAngle = objOneAngle - objTwoAngle;
 if (newAngle< -180)
     newAngle += 360;
 else if (newAngle > 180)
     newAngle -= 360;

Any thoughts on the best way to enhance the above code to deal with 180 degree rotations?

EDIT:
The most obvious method that comes to mind is to split up the positive and negative values, and then choose the best set, based on size or some other metric, but there must be a simpler more elegant solution?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

空宴 2024-10-28 14:54:10

测量某些旋转角度稍大于 180 度和某些旋转角度稍小一点本身应该不成问题。我怀疑真正的问题在于如何组合来自“形状的不同部分”的这些旋转。例如,如果您对旋转进行平均,那么这将给出绝对疯狂的结果。您可以采取以下三种方法。

(1) 以某种不受差异困扰的方式计算“典型旋转”数字:例如,随机选择一个旋转。 (如果其中一些可能出现严重错误,您可以采取更可靠的措施。)现在调整所有旋转,使“典型”旋转为零:

for (i=0; i<nSamples; ++i) {
  rotations[i] -= typicalRotation;
  if (rotations[i]<-180) rotations[i] += 360;
  else if (rotations[i]>180) rotations[i] -= 360;
}

现在平均这些 (或者做任何你正在用它们做的事情),然后通过反向执行相同的操作来纠正。

(2) 与(1)相同,但要么按原样旋转,要么在加工前后全部调整180°。例如,通过计算 -90 到 +90 之间的旋转并查看它们是多于还是少于所有旋转的一半来选择要执行的操作。

(3) 不是平均旋转角度,而是计算每个角度(cos theta、sin theta)并平均那些。然后使用 atan2 将平均值转换回角度。 (这个想法是,角度是圆上“真正”的点,所以最好使用这些点而不是角度。当你这样做时,-180 度和 +180 度之间的歧义就会消失。

)你所做的实际上是平均,我最喜欢的是 3。你的里程可能会有所不同。

Measuring some rotations as a little more than 180 degrees and some as a little less shouldn't be a problem in itself. I suspect the real problem lies in how you're combining these rotations from "different parts of the shape". For instance, if you are averaging the rotations then this will give absolutely crazy results. Here are three approaches you can take.

(1) Compute a "typical rotation" figure in some way that isn't bothered by the discrepancy: for instance, just pick one of the rotations at random. (If it's possible for a few of them to be badly wrong, there are more robust things you can do.) Now adjust all your rotations so that the "typical" one goes to zero:

for (i=0; i<nSamples; ++i) {
  rotations[i] -= typicalRotation;
  if (rotations[i]<-180) rotations[i] += 360;
  else if (rotations[i]>180) rotations[i] -= 360;
}

Now average these (or do whatever sort of thing you're doing with them), and then correct by doing the same operation in reverse.

(2) As for (1), but either use the rotations as they stand or adjust them all by 180deg before and after processing. Choose which to do by, for instance, counting rotations between -90 and +90 and seeing whether they're more or less than half of all your rotations.

(3) Instead of averaging rotation angles, for each angle compute (cos theta, sin theta) and average those. Then use atan2 to convert the average back into an angle. (The idea is that angles are "really" points on a circle, so it's better to work with these points rather than with the angles. When you do this, the ambiguity between -180 and +180 degrees just goes away.)

If what you're doing really is averaging, my favourite of these is 3. Your mileage may vary.

丢了幸福的猪 2024-10-28 14:54:10

处理浮点比较中的舍入误差的常用方法是添加一个小的容差:

double newAngle = objOneAngle - objTwoAngle;
if (newAngle < -180.000001)
    newAngle += 360;
else if (newAngle > 180.000001)
    newAngle -= 360;

这样足够接近 180 的值就不会被修改。

The usual way to deal with rounding errors in floating point comparisons is to add a small tolerance:

double newAngle = objOneAngle - objTwoAngle;
if (newAngle < -180.000001)
    newAngle += 360;
else if (newAngle > 180.000001)
    newAngle -= 360;

This way values close enough to 180 are not modified.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文