文責:遠藤理平
公開日:2017年03月10日
最終更新日:2017年03月10日
本項は「physics.js」を用いて物理シミュレーションを行うための手順をチュートリアル形式で紹介する記事です。 最新版「physics.js」(リビジョン14、2017年03月03日現在)をここからダウンロードしてください。以下はチュートリアルの目次です。
前項「球体を床面に衝突させよう!」では、相互作用として重力+床面との衝突を導入する方法を解説しました。
本項ではじめて回転運動を導入します。図1は回転運動する球体を床面に衝突させた結果です。初期状態として、速度は0としつつ角速度(回転を表すベクトル量)を与えています。並進運動に加え、回転運動を考慮した衝突に対する力学的エネルギー保存則を課してシミュレーションした結果ですが、(自分にとっては)想定外の運動をします。この運動についての考察は後述します。
本シミュレーションでは運動の様子をわかりやすくするための要素を2つ追加しています。1つ目は初期状態の力学的エネルギーからのズレを表す数値テキスト、2つ目は3次元オブジェクトの姿勢をわかりやすくするためのローカル座標系の表示です。実装方法は後述します。
物理シミュレーションは有限桁しか取り扱うことのできない数値計算によってニュートンの方程式を解くことで実行します。そのため物理シミュレーションには正確な結果からの誤差が必ず含まれるわけですが、その正確性は本来ならば保存する量の変化をモニタリングすることで確かめることができます。
本シミュレーションの場合、力学的エネルギーが保存するはずなので、この量が時間とともにどの程度ずれたかをモニタリングすればよく、画面右上に表示しています。
本シミュレーションでは、力学的エネルギーの変化は10^{-14}程度ですが、JavaScriptの実数(倍精度)の有効桁数は15桁なので、計算誤差はほとんど丸め誤差(有効桁の最後の桁の四捨五入)程度であることがわかります。
角速度とは1秒間あたりの回転角度で定義されます。通常、角度の単位は1回転を2πとする弧度法[rad]を用います。また、回転の向きまで含めた量として角速度ベクトルが用いられます。角速度ベクトルの向きを回転軸として、角速度ベクトルの大きさ(絶対値)が角速度に対応します。
physics.jsでは3次元オブジェクトの生成時にomegaプロパティに角速度ベクトルを与えることで回転運動をさせることができます。
//////////////////////////////////////////////////////////////////// // 球オブジェクトの準備 PHYSICS.physLab.ball = new PHYSICS.Sphere({ (省略) omega: { x: 0, y: 5, z: 0 }, //角速度ベクトル (省略) //ローカル座標系可視化関連パラメータ localAxis : { enabled : true, //ローカル座標系可視化の有無 visible : true, //表示・非表示の指定 size : 2, //軸の長さ dashSize : 0.05, //点線の線の長さ gapSize : 0.05, //点線の空白の長さ colors : [ 0xFF0000, 0x00FF00, 0x0000FF] //軸の配色 } }); //球オブジェクトを登場 PHYSICS.physLab.objects.push( PHYSICS.physLab.ball ); //////////////////////////////////////////////////////////////////// // 床オブジェクトの準備 PHYSICS.physLab.floor = new PHYSICS.Floor({ ~ 省略 ~ }); //床オブジェクトを登場 PHYSICS.physLab.objects.push( PHYSICS.physLab.floor ); //////////////////////////////////////////////////////////////////// // 相互作用の準備 //////////////////////////////////////////////////////////////////// //重力の設定 PHYSICS.physLab.setInteraction( ~省略~ ); //球体と床面との衝突の設定 PHYSICS.physLab.setInteraction( PHYSICS.physLab.floor, //床面オブジェクト PHYSICS.physLab.ball, //球オブジェクト PHYSICS.SolidCollision, //衝突力の定義 { Er : 1.0, //並進反発係数 Et : 1.0, //回転反発係数 } ); //仮想物理実験室のスタートメソッドの実行 PHYSICS.physLab.startLab();
3次元オブジェクトのローカル座標系に関するプロパティはlocalAxisプロパティにまとめられています。 速度ベクトルや軌跡などと同様、利用する場合にはenabledプロパティをtrueとし、表示と非表示はvisibleプロパティで切り替えることができます。その他にも長さや点線の間隔、線色を指定することができます。
図1の弾性衝突の場合との比較として、並進反発係数と回転反発係数をともに0.8と与えたときの結果を以下に示します。10回弱跳ね返った後に、床面上を転がるように進んでいます。
図1のシミュレーションは、回転運動を含めた力学的エネルギー保存則を課した場合の床面との衝突結果ですが、ちょっと想定外でした。このことについて考察します。
1回目の衝突までは回転しながら重力によって下向きに落下します。そして球体は回転の加わった床面との衝突のために推進力を得るところまでは想定通りですが、回転は逆回転になっています。
さらに2回目の衝突時に回転の速さ(角速度)は逆回転から初期状態に戻って、球体はそのまま真上に運動して、初期状態と同じ高さまで戻っています。
反対に考えて、回転運動を含めて周期的な運動をする球体は必ず力学的エネルギー保存則を満たしているはずです。
このように考えれば、球体の回転が1回目の衝突で逆回転にならなければ、1回目の衝突で生まれた並進運動を2回目の衝突で打ち消すことはできないことも理解できます。
ここでは示しませんが、回転を含めた力学的エネルギー保存則を課して導出した計算アルゴリズムは一択です。つまり、重力に対して水平な床面との衝突の場合、「力学的エネルギー保存則」=「周期的運動」が必要十分条件であることが言えることになります。
並進運動(回転運動が無い場合)の反発係数は2つの物体の衝突前後の相対速度の比で定義されることは、前項で解説したとおりです。 並進運動に加えて回転運動が存在する場合には、並進運動の反発係数と同様に回転に関する反発係数も定義することができます。 具体的な定義式は示しませんが、physics.jsでは衝突前後の衝突点の速度の比で定義し、回転反発係数と呼ぶことにします。並進運動の反発係数を「1」とした場合、「1」で回転を含めた力学的エネルギー保存則を満たす弾性衝突、「0」で回転に無関係な弾性衝突、それ以外で非弾性衝突となります。