前輪の向きと速度から自転車の向きを計算する


10

ステアリングを追加しようとしているシンプルなトップダウンバイクゲームがあります。前輪のヘディングを使用して、バイクのヘディングと速度を決定する方法を教えてください。

void Update () 
{
    //Get input from user Vertical: 0 to 1, Horizontal -1 to 1
    float forwardInput = Input.GetAxis("Vertical");
    float sidewaysInput = Input.GetAxis("Horizontal") * m_steeringAmount;

    // Turn front wheel
    m_frontWheelTransform.localEulerAngles = new Vector3(0, sidewaysInput, 90);

    // get speed and drag
    float   speed           = m_velocity.magnitude;
    Vector3 forwardDrag     = -m_forwardDragConstant * m_velocity * speed;

    // calculate acceleration 
    float engineForce       = forwardInput * m_enginePower;
    Vector3 forwardTraction = transform.forward * engineForce;
    Vector3 forwrdForce     = forwardTraction + forwardDrag;
    Vector3 acceleration    = forwrdForce / m_mass;

    // update velocity and position
    m_velocity += acceleration * Time.deltaTime;
    transform.localPosition += m_velocity * Time.deltaTime;
}

私は前輪と後輪に自転車の速度を適用し、それらの位置の違いを使用して自転車の向きを決定しようとしましたが、前方にドラッグすると混乱します。

madshogoコメントに基づいて編集

ここに画像の説明を入力してください


今はスマートフォンを使用しているので、簡単に答えます。車輪は自転車が通る架空の円に接しているため、自転車が曲がります。円の中心は、各ホイールに直交する線の交点です。車輪が両方とも直線である(自転車が回転していない)場合、これらの線は無限にパスを横切り(それらは平行です)、無限の半径の円、つまりA線になります。最終的に、これにより、自転車が従うべき軌道(円)またはその曲率のうち、ニーズに合った方が得られます。
jrsala

答えmadshogoをありがとう。追加した図を見て、それが正しいかどうか教えてください。赤い線は自転車の方位です。乾杯
user346443

あら、前輪が図面の円に接していない。私の頭では、両方の車輪が接しています。それはいくつかのことを変えます。
jrsala 2012

自転車の物理学に関するウィキペディアのページを見ましたか?これには、傾きを考慮した回転半径の有用な式があります。
sam hocevar

回答:


3

さて、私は結果で戻ってきました!

アニメバイク

私は2つのアプローチを試しました:

  • 固体力学を使用して、車輪の中心の動きを支配する微分方程式を導き出します。システム「バイク」の入力は後輪のトルクと前輪の角度であり、出力は中心の運動学です車輪の。しかし、私はあきらめました、それは大変でした!

  • 後輪が前輪をまっすぐにせずに前輪を「押し」、幾何学的な観点から何が起こるかを推測しようとします。この方法では、実際に微分方程式を得ることができる無限小増分の方程式(下記参照)が直接得られます。この最初の方程式を操作してODEを取得することは試みていませんが、固体力学を使用してまったく同じODEを取得できたと思います。ちょうどいい感じです。

表記と仮説:

私たちは、基底ベクトルexeyを持つ平面にいます。

Aは後輪の中央です。Bは前輪の中央です。自転車の長さLは、ABの間の距離です。eyとベクトルABの間の角度はφです。ABと前輪の間の角度はθです。

直感的な根拠:

ある瞬間tでA(t)の速度V(t)ABと同一直線上にあると仮定します。したがって、微小なタイムステップdtの場合、

A(t + dt)= A(t)+ V(t).dt

また、時間tで前輪がドリフトしない、つまりBの速度が前輪の方向と同一直線上にある、つまりABと角度θを形成するとします。ABとの角度θを形成する単位ベクトル、つまり前輪と同じ方向の単位ベクトルと呼びます。

したがって、t + dtで

B(t + dt)= B(t)+λ.Uθ

自転車の長さLが保存されるような特定の実際の正のλの場合

距離(A(t + dt)、B(t + dt))= L

計算:

この最後の方程式は、

norm²(B(t)+λ.Uθ-A(t)-V(t).dt)=L²

しかし、B(t)は、定義により、A(t)+L.Uφであるため、λは次の式を満たす必要があります。

norm²(L.Uφ+λ.Uθ-V(t).dt)=L²

もちろん、バイクが正のyを向いているときも問題は同じなので、解はφから独立しています。したがって、Rを角度-φの回転行列と呼ぶ場合、λは次の正の解でなければなりません。

norm²(L.ey; +λ.Uθ-RV(t).dt)=L²

我々が呼び出した場合、いくつかの計算をした後、VのノルムVを、あなたが得ます

λ= L.(sqrt(1-(sin(θ)。(1-v.dt / L))²)-cos(θ))+ v.dt.cos(θ)

上記のアニメーションを取得するために使用した疑似コードは次のとおりです(を使用する代わりに、u = U(θ+φ)を使用した方が簡単だったためです)。

// I start at i=1 because i=0 contains the initial values
for (int i=1; i<=N; i++)
{
    // the array in which I stored the successive A points
    Aarray[i] = Aarray[i-1] + dt*V;
    float lambda = L*( sqrt(1 - (sin(theta)*(1-v*dt/L))**2) - cos(theta) )
                   + cos(theta)*v*dt;
    // the array in which I stored the successive B points
    Barray[i] = Barray[i-1] + lambda*u;
    // the AB vector normalized
    AiBiUnit = (Barray[i] - Aarray[i])/L;
    // Refreshing the velocity of A
    V = v*AiBiUnit;
    // Refreshing u.
    // u is indeed a unit vector separated from AiBiUnit by an angle theta,
    // so you get it by rotating the newly computed AiBiUnit by an angle
    // of +theta:
    u = AiBiUnit.rotate(theta);
}

何度も繰り返したり、ステアリング角度を大きくしたりすると、軌道は円になり、まとまりがあると思います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.