動くビリヤード ボールのダイナミクスのモデル化
この例では、連続時間の行列変数を使用してビリヤード ゲームのオープニング ショットをモデル化する方法を説明します。モデルの Stateflow® チャートは、大量の不連続点をもつハイブリッド システムのダイナミクスをシミュレートします。詳細については、Stateflow の連続時間モデルを参照してください。
シミュレーションを開始すると、MATLAB® ユーザー インターフェイス (UI) には、三角形の枠に 15 個のビリヤード ボールが配置されたビリヤード テーブルが表示されます。次に、キュー ボールの最初の位置と速度を選択することを求めるプロンプトが UI に表示されます。キュー ボールが放たれると、高速で衝突し続けるビリヤード ボールの動きが UI によってアニメーション化されます。
モデルは次のもので構成されています。
Stateflow チャート Init。関数
sf_pool_plotter.m
を呼び出し、UI からの入力に基づいてキュー ボールの位置と速度を初期化します。Stateflow チャート Pool。各ビリヤード ボールの 2 次元のダイナミクスを計算します。
MATLAB Function ブロック Plot。関数
sf_pool_plotter.m
を呼び出し、シミュレーション中のビリヤード ボールの動きをアニメーション化します。Scope ブロック Vel。オープニング ショット中の各ビリヤード ボールの速度を表示します。
連続時間ダイナミクスの計算
ビリヤード ボールのダイナミクスを表すため、Pool チャートはいくつかの仮定を行います。
連続時間変数
システムの状態がボールの位置と速度によって完全に記述されるよう、チャートはボールのスピンを無視します。各ボールが単位質量をもつと仮定されるので、その位置と速度は次の微分方程式系によって記述されます。
ここで と は、ビリヤード テーブルとの摩擦による力と、他のボールとの衝突によって発生する力です。
ボールの位置と速度を追跡するため、チャートは 16 行 2 列の行列のペアを連続時間変数 p
と v
に保存します。各行列で、 行は ボールの 2 次元の位置または速度を表します。
摩擦モデル
各ボールに作用する摩擦力を計算するため、チャートは MATLAB 関数 frictionForce
を呼び出します。この関数は簡略化された摩擦モデルを実装します。摩擦はそれぞれの動くボールに対し、動きの反対方向に一定の力で作用します。摩擦は静止しているボールには作用しないので、各ボールへの摩擦力は本質的にモーダルです。
ここで は摩擦係数、 は重力加速度です。
衝突ダイナミクス
ボール間の衝突によって起きる相互作用を特定するため、チャートは MATLAB 関数 interactionForce
を呼び出します。この関数は 2 つのボールが互いに接触するときの単純な復元力モデルを実装します。 と のボール間の相互作用力はモーダルです。
ここで、
は各ボールの半径。
および は弾性定数。
は 2 つのボールの中心の相対距離。
は 2 つのボールの相対速度。
ボールは 2 次元で自由に移動するため、チャートは 16 行 16 列の boolean 行列 ball_interaction
を使用してすべての潜在的な衝突を考慮します。たとえば、 と のボールが接触している場合、ball_interaction(i,j)
の値は true
です。それ以外の場合、この値は false
です。衝突は本来対称なので、チャートは行列の上三角部分のみを使用します。
MATLAB 関数での行列計算の実行
ビリヤード ボールの 2 次元ダイナミクスを計算するため、Pool チャートは行列計算を実行するいくつかの MATLAB 関数を呼び出します。
initBalls
は、ビリヤード テーブル上の各ボールの位置と速度を初期化します。frictionForce
は、各ボールにかかる摩擦力を計算します。interactionForce
は、各ボールにかかる相互作用力を計算します。isAnyBallGoingToStop
は、いずれかのボールが動きを止めると1
の値を返します。それ以外の場合、関数は0
の値を返します。hasBallInteractionChanged
は、いずれかのボールの相互作用が変化すると1
の値を返します。それ以外の場合、関数は0
の値を返します。isAnyBallNewlyPocketed
は、いずれかのボールがポケットに落ちると1
の値を返します。それ以外の場合、関数は0
の値を返します。isAnyBallOutOfBounds
は、いずれかのボールがビリヤード テーブルの境界の外にある場合にtrue
の値を返します。それ以外の場合、関数はfalse
の値を返します。nearHole
は、ボールがビリヤード テーブルのポケットの近くにある場合にtrue
の値を返します。それ以外の場合、関数はfalse
の値を返します。getBallInteraction
は、いずれかのボールが互いに接触しているかどうかを指定する boolean 行列を返します。updateStopFlags
は、どのボールの動きが止まったかを追跡し、ベクトルstopped
に結果を保存します。pocketNewBalls
は、ポケットに入った各ボールの速度を0
に設定します。resetBallsPosAndVel
は、ビリヤード テーブルの境界の外にあるすべてのボールの位置と速度をリセットします。
シミュレーション結果の表示
シミュレーションの開始に際し、UI にはビリヤード テーブルと、15 個のビリヤード ボールが台の片側に並んで表示されます。キュー ボールの最初の位置を指定するには、ビリヤード テーブルの任意の場所をクリックします。
突き玉の最初の速度を指定するには、ビリヤード テーブルの別の場所をクリックします。
モデルはシステムのダイナミクスをシミュレートして、ビリヤード ボールの動きをアニメーション化します。
シミュレーションを停止するには、UI を閉じます。