情况
一段时间以来,我一直在努力解决这个问题。基本上,我有一个角度r (弧度),我想在模拟的每个步骤中以设定的速度dr (弧度/秒)将其更改为所需的角度wr (弧度) 。因此,我需要对于每一步,我都有一个新的角度nr,其中nr = r + dr * dt和dt是自上一步以来的增量时间。
角度在空间 [-pi, pi] 中,增量角度由最短的转弯方式决定。对于每一步,增量角度被添加到当前旋转,包装到 [-pi, pi] 并存储为新角度。
由于我的步数没有无限精确,我显然会 - 实际上 - 永远不会直接达到所需的角度,因此我需要找到达到所需旋转的时间 -并交叉- 然后停止旋转并设置角度到所需的角度。在伪代码中:
if rotationSpeed!= 0
angle = WrapRotation(angle + rotationSpeed * deltaTime)
if desiredAngle has been reached or crossed
angle = desiredAngle
rotationSpeed = 0
问题
在几乎所有情况下,这很容易做到,但是当您的角度足够高或足够低(接近 -pi 或 pi)并且新角度带您越过“边界”时,可以说,事情变得复杂了。我所有的尝试都未能涵盖当前、先前和所需轮换的所有可能情况。所以我问你是否碰巧知道解决方案?
如果需要,我在下面附上了我的代码(C#):
// Sets the desired rotation and rotation speed in radians/second:
public void SetRotation(float rotation, float speed)
{
desiredRotation = MathHelper.WrapAngle(rotation);
if (desiredRotation != this.rotation)
{
// Determine the shortest way to turn (indicated by the sign of speed)
float a = desiredRotation - this.rotation;
if (a > Math.PI) a -= 2 * (float)Math.PI;
if (a < -Math.PI) a += 2 * (float)Math.PI;
desiredRotationSpeed = a < 0 ? -speed : speed;
}
}
// Update is called per each step. Takes in the amount of seconds since the last call.
public void Update(float seconds)
{
/* Other stuff */
if (desiredRotationSpeed != 0)
{
float delta = desiredRotationSpeed * seconds;
rotation = MathHelper.WrapAngle(rotation + delta);
if( /* This is the part I'm struggling with. */ )
{
desiredRotationSpeed = 0f;
rotation = desiredRotation;
}
}
/* Other stuff */
}
在正常情况下(非循环行为),以下工作:
if (Math.Abs(value - desiredValue) < Math.Abs(deltaValue))
/* Desired has been reached. Do stuff! */
所以要澄清。我想找出何时达到所需的角度(并且由于精度而超过),以便我可以将当前角度设置为所需的角度,并停止旋转。
非常感谢你的帮助!我有一种感觉,这真的有一个简单的解决方案!:3