14

0 から x (1 次元でのオブジェクトの位置) までを時間の経過とともに補間するメソッドを作成しようとしています。最初は加速し、最後は減速 (イーズ アウト/イーズ イン) を使用しますおよび加速と減速の期間が提供されます。モーションは慣性効果を再現する必要があり、非線形部分のエルミート曲線を検討しています。

double Interpolate(
    double timeToAccel, double timeCruising, double timeToDecel,
    double finalPosition,
    double currentTime)
{
    //...
}

誰かがそれを行うコードの一部を教えてもらえますか? エルミート曲線を積分する方法がわからないため、加速部分または減速部分でどれだけ移動するかがわからず、直線の速度がどうなるかわかりません部分。

ありがとう。

私の質問を説明するための参照。

編集

  • 開始速度と終了速度は null で、現在の時刻もメソッドのパラメーターの一部です。署名を更新しました。
  • 基本的には、距離 d を一定の速度で移動することを想像すると、合計の持続時間が得られます。次に、同じ期間を維持しながら、加速フェーズと減速フェーズを追加します。したがって、決定する未知の新しい巡航速度が得られます (エルミート フェーズでは、置き換えられた線形フェーズよりも移動が少ないため)。おそらく、エルミート フェーズで失われる移動の量は、同じ期間の直線的な移動と比較して、曲線の上部と下部の領域の比率であり、専門家ではないアイデアにすぎません。

編集: Roman と Bob10 は、完全に機能するソリューションを提供しています。Roman のコードを実装しました。ありがとうございます!あなたの完璧なサポートと詳細な解決策に感謝します。長い検索と試行を節約できました。

4

2 に答える 2

22

まず、3 次エルミート スプライン関数を作成しましょう。

/*
  t  - in interval <0..1>
  p0 - Start position
  p1 - End position
  m0 - Start tangent
  m1 - End tangent
*/
double CubicHermite(double t, double p0, double p1, double m0, double m1) {
   t2 = t*t;
   t3 = t2*t;
   return (2*t3 - 3*t2 + 1)*p0 + (t3-2*t2+t)*m0 + (-2*t3+3*t2)*p1 + (t3-t2)*m1;
}

次に、イーズイン部分とイーズアウト部分の両方について、p0、p1、m0、および m1 を計算します。数学を書きやすくするために、いくつかの変数を追加しましょう。

double Interpolate(
    double timeToAccel, double timeCruising, double timeToDecel,
    double finalPosition,
    double currentTime) {

    double t1 = timeToAccel;
    double t2 = timeCruising;
    double t3 = timeToDecel;
    double x = finalPosition;
    double t = currentTime;

オブジェクトが加速を停止して減速を開始するときの位置を指定する必要があります。これらを好きなように指定して、スムーズな動きを生成することもできますが、ある程度「自然な」解決策が必要です。

巡航速度を としましょうv。巡航中、オブジェクトは距離を移動しますx2 = v * t2。ここで、オブジェクトが 0 から速度 v まで加速すると、距離 を移動しますx1 = v * t1 / 2。減速も同様x3 = v * t3 / 2。すべてをまとめる:

x1 + x2 + x3 = x

v * t1 / 2 + v * t2 + v * t3 / 2 = x

そこから、速度と距離を計算できます。

    double v = x / (t1/2 + t2 + t3/2);
    double x1 = v * t1 / 2;
    double x2 = v * t2;
    double x3 = v * t3 / 2;

すべてがわかったので、それを 3 次エルミート スプライン補間器に入力します。

    if(t <= t1) {
       // Acceleration
       return CubicHermite(t/t1, 0, x1, 0, v*t1);
    } else if(t <= t1+t2) {
       // Cruising
       return x1 + x2 * (t-t1) / t2;
    } else {
       // Deceleration
       return CubicHermite((t-t1-t2)/t3, x1+x2, x, v*t3, 0);
    }
}

これを Excel でテストしました。これは、同等の VBA コードです。境界条件にはゼロによる除算がいくつかあります。これに対する修正は、読者の演習として残します。


Public Function CubicHermite(t As Double, p0 As Double, p1 As Double, _
m0 As Double, m1 As Double) As Double
   t2 = t * t
   t3 = t2 * t
   CubicHermite = (2 * t3 - 3 * t2 + 1) * p0 + _
(t3 - 2 * t2 + t) * m0 + (-2 * t3 + 3 * t2) * p1 + (t3 - t2) * m1
End Function

Public Function Interpolate(t1 As Double, t2 As Double, t3 As Double, _
x As Double, t As Double) As Double
    Dim x1 As Double, x2 As Double, x3 As Double

    v = x / (t1 / 2 + t2 + t3 / 2)
    x1 = v * t1 / 2
    x2 = v * t2
    x3 = v * t3 / 2

    If (t <= t1) Then
       Interpolate = CubicHermite(t / t1, 0, x1, 0, v*t1)
    ElseIf t <= t1 + t2 Then
       Interpolate = x1 + x2 * (t - t1) / t2
    Else
       Interpolate = CubicHermite((t-t1-t2)/t3, x1+x2, x, v*t3, 0)
    End If
End Function
于 2010-07-29T22:52:53.020 に答える
8

これは、通常の一定の加速度を使用すると簡単です。次に問題は、適切な時間内に移動を完了するためにどの速度 (v) まで加速する必要があるかということです。これにより、その速度に到達するために必要な加速がわかります。

合計時間が t_t で加速時間が t_a の場合、2 つの加速部分と減速部分、および等速部分として移動距離が得られます。

x = 2*(a*t_a*t_a/2) + v*(t_t-2*t_a)

これは、v=a*t_a を下に置くことで加速度を求めることができます。

a = x/(t_a*(t_t - t_a))

これらの方程式の結果を使用してプロットする Python コードを次に示します。これは、方程式の使用方法と結果がどのように見えるかの両方を示しています。

from pylab import *

t_a, t_t, D = 3., 10., 1.  # input values

a = D/(t_a*(t_t - t_a))
segments = (t_a, a), (t_t-2*t_a, 0.), (t_a, -a)  # durations and accelerations for each segment

t0, x0, v0 = 0.0, 0.0, 0.0  #initial values for the segment
tdata, xdata = [], []
for t_segment, a in segments: # loop over the three segments
    times = arange(0, t_segment, .01)
    x = x0 + v0*times + .5*a*times*times
    xdata.append(x)
    tdata.append(times+t0)
    x0 = x[-1] # the last x calculated in the segment above
    v0 += a*t_segment
    t0 += t_segment

plot(tdata[0], xdata[0], 'r', tdata[1], xdata[1], 'r', tdata[2], xdata[2], 'r')
xlabel("time")
ylabel("position")
show()

代替テキスト

于 2010-07-30T05:09:30.590 に答える