動くビリヤード ボールのダイナミクスのモデル化
この例では、連続時間の行列変数を使用してビリヤード ゲームのオープニング ショットをモデル化する方法を説明します。モデルの 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 を閉じます。