状況
私はしばらくの間、この問題に頭を悩ませてきました。基本的に、シミュレーションの各ステップで、設定された速度dr (ラジアン/秒)で目的の角度wr (ラジアン)に変更したい角度r (ラジアン)があります。したがって、ステップごとに新しい角度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