なぜ蓄積を統合するのですか?


14

私は物理学をDIYする方法を学び始めており、最も基本的なレベルで統合を実装することについて質問があります(つまり、これはオイラー対RK4の質問ではありません)。

私が遭遇するほとんどすべての例にintegrate()は、最後の更新以降のタイムステップを取得し、最後の更新以降の加速度(および/または速度および/または位置)を更新する関数があります。

最も単純な形式: position += velocity * deltaTime

ただし、関数を変更するだけで簡単に取得できるのに、なぜこのように蓄積されるのかわかりません。たとえばgetPosition = makeNewFunction()、のシグネチャを持つ何かを返す可能性がTime -> Positionあり、その関数の内部動作は適切な数式を介して生成されます。

そうすれば、蓄積はありません...位置を取得する必要があるときはいつでも、現在の時間でその関数を呼び出します。

私の初心者の理解では、これは蓄積から生じるエラーも回避するということです...それではなぜこれが機能しないのですか、何が欠けていますか?

(私このアイデアの概念の基本的な証明をまとめましたが、同時にいくつかの他のこともテストしているため、最もクリーンな例ではありません:https : //github.com/dakom/ball-bounce-frp

編集1:コメントで述べたように、加速の変更についてはまだ学んでいないこと、または加速度を一定にするよりも高次の積分を必要とするジャークやその他のことを扱ったことを指摘することはおそらく重要です。

EDIT 2:ここでのアイデアのいくつかの基本的なサンプルコードで、擬似JavaScriptシンタックス-ノートgetKinematicPositionされ、部分的に適用され、それはちょうど時間の新機能戻っているので- >位置を:

私はここでの位置に固執していますが、それは他の何かかもしれませんgetVelocity

getKinematicPosition = initialVelocity => acceleration => time => 
  ((.5 *acceleration) * (time * time)) + (initialVelocity * time);

getPosition = getKinematicPosition ([0,0,0]) (GRAVITY);

onTick = totalTime => {
   position = getPosition (totalTime);
   onCollision = () => {
     getPosition = changeTheFunction(totalTime);
     //changeTheFunction uses totalTime to base updates from 0
     //it could use getKinematicPosition or something else entirely
   }
}

1
速度/加速度が一定でない場合、関数は何をしますか?
リネイス

何も思いつきません!:Dそれが理由である場合-たとえば、まだ加速を変更していない場合、これが答えとしてどこで壊れるかについてのより完全な説明を本当に感謝します(そうでなければ、この機能的な道を行き行き行き止まりにぶつかる!)
davidkomer

6
あなたのオブジェクトが円を描くだけなら、プレーヤーが押しているボックスの場合はどうでしょうか?getPosition(now + 100)を呼び出すと、プレーヤーがプッシュを停止する時期を知るために未来が予測されますか?getPosition(now-1000)を呼び出すとき、過去を記憶する必要がありますか?
user253751

回答:


34

...その関数の内部動作は、適切な数式を介して生成されます...

これは特定のクラスの問題で機能し、検索するキーフレーズは閉じた形式のソリューションです。たとえば、Kerbal Space Programでは、軌道上の宇宙船の動きはこの方法で計算されます。残念ながら、ほとんどの自明でない問題(たとえば、宇宙船の大気圏への再突入)には、既知の閉じた形式の解決策がありません。したがって、数学的に単純な数値近似の必要性(つまり、integrate()長期にわたる)。


ああ...すごい!少し時間があれば-この機能的なアプローチを目指して、それを機能させる方法がわからない場合(たとえば、閉じていないフォームの問題を処理している場合や私はそれを1に変える方法がわかりません)?私のようなそれは数学1収まるので、関数を生成するというアイデア:1 -が、私はいつも必然的に行き止まりを打つだろうならば、それはないかもしれない価値を、それ...
davidkomer

8
@davidkomerなぜ関数を生成し続けたいのですか?これを実行できる場合は、軌道全体を事前に計算して記録することができます!もちろん、人々はすでにこれを行っています。アニメーションと呼ばれ、微妙な部分があります。
Joker_vD

関数は、ランタイムダイナミクスに基づいて変化します。たとえば、FRPボールバウンスを参照してください
davidkomer

実際に、ユーザーがランダムに制御する移動オブジェクトを使用して、その例をポンのようなものに更新する必要があります
...-davidkomer

10

アプローチの問題は、オブジェクトの履歴がないことです。ある方向に移動すると位置を計算できますが、何かを叩いて跳ね返るとどうなりますか?
前回の既知の位置から蓄積した場合、衝撃に対処してそこから先に進むことができます。最初から計算しようとすると、毎回影響を再計算するか、新しい開始位置として設定する必要があります。

あなたの例は、レースゲームを思い出させました。(位置が物理エンジンによって制御されるかどうかはわかりませんが、説明するのにうまくいくと思い
ます)車で運転する場合、加速と減速ができます。あなたの車の速度プロファイルが最初から今までどのように見えたか知らずに、あなたの位置を計算することはできません。距離の累積は、開始から現在までのすべてのフレームでの速度を保存するよりもはるかに簡単です。

免責事項:私は今までにゲームの物理学を書いていません。それがまさに問題の見方です。

編集:
この図では、値が時間とともにどのように変化するかを見ることができます。
赤=加速(加速からスローダウンまで)
緑=速度(起動から停止まで)
青=あなたが行った方法

合計速度は、開始点から実際のログ記録までの加速度の積分です。(線と軸の間の領域)
方法は速度の積分です。
加速度の値がわかっている場合は、他の値を計算できます。しかし、私が間違っていなければ、積分はPCでの累積によっても計算されます。そして、すべての加速度値を保存しておくと、オーバーヘッドが大きくなります。
さらに、フレームごとに計算するには多すぎます。

加速度/速度/走行時間図

ペイントスキルは素晴らしいです。;)

編集2:
この例は直線運動用です。方向を変えると、これはさらに難しくなります。


「または、新しい開始位置として設定します。」はい。
davidkomer

新しい位置を設定することはおそらく問題ではありません。車の部品を編集しました
リネイス

1
車のゲームでは、加速はさらに複雑になると思います。おそらくジャンプとスパイクがあり、速度に依存する可能性があります。(たとえば、車が最高速度に近づくと、加速度は0に減少します。)
jpmc26

3
@davidkomerは(あなたが望んでいない限り)車に煩わされることさえありません、基本的なプラットフォーマーが行います。スーパーマリオブラザーズでmario.getPosition(Time)はどのように機能しますか?
user253751

8

ただし、関数を変更することで簡単に取得できるのに、なぜこのように蓄積されるのかわかりません。例:getPosition = makeNewFunction()これは、Time-> Positionのシグネチャを持つ何かを返すことができ、その関数の内部動作は適切な数式を介して生成されます。

あなたはできる!

分析的または閉じた形式のソリューションを使用して呼び出されます。時間の経過とともに蓄積される丸め誤差は存在しないため、より正確であるという利点があります。

ただし、これは事前にそのような閉じたフォームを知っている場合にのみ機能します。ゲームの場合、これは非常に頻繁に当てはまりません。

プレイヤーの動きは不規則で、事前に計算された機能に入れることはできません。プレーヤーは、速度と方向を頻繁に変更できます。

NPCは、閉じた形式のソリューションを潜在的に利用できますが、実際にはNPCが時々利用します。ただし、これには他にもいくつかの欠点があります。シンプルなレースゲームを考えてください。車両が別の車両と衝突するたびに、機能を変更する必要があります。たぶん、車は地下によってはより速く動きます。このような閉じた形式のソリューションを見つけることは非常に困難です。実際、そのような閉じたフォームを見つけることが不可能であるか、または単純に実行不可能であるほど複雑である場合が多くあります。

閉じた形式のソリューションを使用する素晴らしい例は、Kerbal Space Programです。ロケットが軌道上にあり、推力を受けていない場合、KSPは「軌道に乗せる」可能性があります。軌道は2体システムで事前に決定されており、周期的です。ロケットがそれ以上推力を加えない限り、ロケットがどこにあるか既に知っていて、あなたは単にそれを呼ぶことができますgetPositionAtTime(t)(それは正確にそれと名付けられませんが、あなたはアイデアを得ます)。

ただし、実際には、段階的な統合を使用する方がはるかに実用的です。しかし、閉じた形式のソリューションが存在し、計算が簡単な状況を見つけたら、それを試してください!使用しない理由ありません

たとえば、キャラクターが大砲を狙っている場合、閉形式のソリューションを使用して、キャノンボールの予想されるインパクトポイントを簡単に表示できます。また、ゲームでキャノンボールのコースを変更できない場合(風がない場合など)、キャノンボールを移動するために使用することもできます。その場合、キャノンボールのパスに移動する障害物に特別な注意を払う必要があることに注意してください。

同様の状況がたくさんあります。ラウンドベースのゲームを構築している場合、RTSゲームを構築するときよりもはるかに多くの閉形式のソリューションが利用できる可能性が高くなります。たとえば、そのパスに)。

段階的統合の数値的不正確性に対処する手法があることに注意してください。たとえば、累積されたエラーを追跡し、修正用語を適用してエラーを抑制できます(例:Kahan Summation)


8

単純なバウンドするボールの場合、閉じたフォームのソリューションを思い付くのは簡単です。ただし、より複雑なシステムでは、常微分方程式(ODE)を解く必要があります。 数値ソルバーは、最も単純なケースを除くすべてを処理する必要があります。

実際、数値ODEソルバーには明示的と暗黙的の2つのクラスがあります。明示的なソルバーは次の状態の閉形式近似を提供しますが、暗黙的なソルバーは方程式を解く必要があります。 バウンドするボールについて説明するのは、知っているかどうかにかかわらず、実際には暗黙的なODEソルバーです。

暗黙的なソルバーには、はるかに大きなタイムステップを使用できるという利点があります。バウンドボールアルゴリズムの場合、タイムステップは、少なくとも次の衝突(関数が変更される)までの期間と同じ長さにすることができます。これにより、プログラムをはるかに高速に実行できます。ただし、一般に、関心のあるODEに対する適切な暗黙の解決策を常に見つけることはできません。見つけることができない場合、明示的な統合に頼ります。

明示的な統合で私が見る大きな利点は、落とし穴がよく知られていることです。60年代の教科書を開いて、特定の統合手法で発生する小さな癖について知る必要があるすべてを読むことができます。したがって、開発者はこれらのスキルを一度学習すれば、再び学習する必要はありません。暗黙的な統合を行う場合、各ユースケースはわずかに異なり、落とし穴もわずかに異なります。あるタスクから学んだことを次のタスクに適用するのは少し難しいです。


1

pos(t)= v(t)* t

pos(0)= 0およびv(t)= kの場合のみ機能します

初期条件と速度関数全体の知識がなければ、位置を時間に関連付けることはできません。そのため、方程式は積分の近似値になります

pos(t)= 0からtまでのv(t)dtの積分

編集_________

コメントごとに少し証拠があります(pos(0)= 0と仮定)

let v(t)= 4

eqn 1:pos(t)= 4 * t(正しい)

eqn 2:pos(t)= c + 4 * t 0からt = 4 * t(正しい)

let v(t)= 2 * t

eqn 1:pos(t)= 2 * t ^ 2(間違っている)

eqn 2:0からt = t ^ 2までのpos(t)= c + t ^ 2(正しい)

あなたの方程式はすでに一定の加速を考慮していることを追加する必要があります(つまり、方程式はeqn 2であり、v(t)= v0 + a * tであり、積分の限界はt0とtです)。初期位置、初期速度、および加速度は一定のままです。

EDIT2 ________

また、初期位置、初期速度、初期加速度、および一定のジャークで位置を計算できることも追加する必要があります。言い換えれば、位置対時間を表すeqn 2に基づいて、速度、ジャーク、次に来るものなどに微分することで位置と時間を表す関数を作成できますが、方程式は次の場合にのみ正確になりますv(t)はそのようにモデル化できます。速度、加速度、一定のジャークなどだけでv(t)をモデル化できない場合は、バウンド、空気抵抗、風などが発生するときに発生する傾向があるeqn 2の近似値に戻る必要があります。


定数。それは単にv(t)が時間とともに変化してはならないことを意味します
Kyy13

私はこれと一緒に座って、なぜそれが本当なのかを解明する必要があります...今のところ賛成です:)それが物事を変える場合の質問にコードサンプルを投稿しました
-davidkomer

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