月面着陸(万有引力・ケプラーの法則) 第一回

~プログラムによる万有引力の再現~

※ブラウザはChromeを使用します。他のブラウザでの動作は確認していません。

1.HTML作成

img

月の周辺を二つの人工物が周回しているイメージです
ボールの重量は極めて小さいという設定にして、月がボールに引かれる力や、ボール同士が引き合う力は無視します

▲TOP

2.プログラム解説

(1)main関数

function main()
{
    for( var i=0 ; i<2 ; i++ )
    {
	Ball[i] = new CBall(i);
    }

    timer_update = 0;
    form_changed = false;

    $("#step0").click( OnStep );
    $("#pause0").click( OnPause );
    $("#play0").click( OnPlay );
    $("form").change( function(){   form_changed = true;    }	);
}		
		    

グローバル変数の初期化とイベントハンドラの登録を行っています

  • Ball は二つのボールの位置情報の管理、画面表示の更新等を行うクラスです
  • timer_update はアニメーション処理を止める際に必要な タイマーの識別子です
  • form_changed は 表の数値が手動で変更されたかどうかのフラグです

(2)OnPlay関数

function OnPlay(){
    SetConsole( false , false , true );
    ReadData();
    timer_update = setInterval( Update , TIME_STEP );
}
		    
  • SetConsole関数は 一時停止、コマ送り、再生 の3つのボタンの表示状態を管理する関数です
    この場合は 再生ボタンが光っている状態にしています
  • ReadData関数は 画面下部のフォームから位置、速度情報を読み込む関数です
    関数内で form_changedフラグをチェックして 変更があった場合のみデータを更新しています
  • setInterval( 関数 , 呼び出し間隔 );
    これ以降、この関数で登録されたUpdateが、一定間隔ごとに呼び出され、アニメーション処理がはじまります
    戻り値はタイマーの識別子になっているので timer_update 変数に格納しておきます

(3)Update関数

function Update(){
    for( var i=0 ; i<2 ; i++ )
    {
	Ball[i].Update();
    }
}			
		    

これが1/60秒ごとに呼び出される関数です
やっていることはボール2つ分のUpdate関数を呼んでいるだけです

(4)CBall::Update関数

CBall.prototype = {
    ...
    Update: function(){
	this.Move();
	this.UpdateView();
	this.UpdateData();
    },
    Move:   function(){
	var r = Math.sqrt( this.P[0] * this.P[0] + this.P[1] * this.P[1] );
	this.V[0] -= GRAVITY * this.P[0] / Math.pow( r , 3 );
	this.V[1] -= GRAVITY * this.P[1] / Math.pow( r , 3 );

	this.P[0] += this.V[0];
	this.P[1] += this.V[1];
    },
    UpdateView:	function(){
	this.target.css("left",this.P[0] + OFFSET_POS[0] );
	this.target.css("top",this.P[1] + OFFSET_POS[1] );
    },
    UpdateData:	function(){
	var sel = "#b0"+this.id+"_data";
	$(sel+" .px input").val( Number(this.P[0]).toFixed(2) );
	$(sel+" .py input").val( Number(this.P[1]).toFixed(2) );

	$(sel+" .vx input").val( Number(this.V[0]).toFixed(2) );
	$(sel+" .vy input").val( Number(this.V[1]).toFixed(2) );
	
	var pa = Math.sqrt( this.P[0]*this.P[0] + this.P[1] * this.P[1] );
	var va = Math.sqrt( this.V[0]*this.V[0] + this.V[1] * this.V[1] );
	
	$(sel+" .pa").text( Number(pa).toFixed(2) );
	$(sel+" .va").text( Number(va).toFixed(2) );
	$(sel+" .pv").text( Number(pa*va).toFixed(2) );
    }
		    
  • Move関数では位置情報を元に重力の影響を算出 速度を変更させた後
    位置情報を更新しています
    距離の二乗に反比例した大きさで、月の方向に引き寄せる力が加わっているのを確認して下さい
  • UpdateView関数では 画面上部のボールの表示位置を更新しています
  • UpdateData関数では 画面下部の表の数値データを更新しています

(5)OnPause関数

function OnPause(){
    SetConsole( true , false , false );

    if( timer_update )
    {
	clearTimeout( timer_update );
	timer_update = 0;
    }
}			
		    

clearTimeout関数に OnPlayで取得した timer_update を渡すことで
アニメーション処理を停止しています

▲TOP

3.ケプラーの法則の観察

img

第一法則 惑星は太陽をひとつの焦点とする楕円軌道上を動く

初期位置や速度をいろいろと変更して、ボールの軌道が様々な楕円を描くことを確認しましょう
ただし、初期速度が大きすぎると楕円軌道に乗らず、遥か彼方まで吹き飛んで戻ってきません
これがいわゆる第二宇宙速度突破です

第二法則 惑星と太陽とを結ぶ線分が単位時間に描く面積は一定である

これはボールの速度と月からの距離の積が一定の値を取る ということです
この法則のチェックのために 画面下の数値データ一覧に「距離×速度」という項目を作ってあります
楕円軌道に乗っているボールでは、この数値が(おおむね)一定になっていることを確認して下さい

第三法則 惑星の公転周期の2乗は軌道の長半径の3乗に比例する

公転周期が2倍になる2つの円軌道のサンプルを用意しました
これらの軌道半径の3乗の比率が1:4になっていることを確認して下さい

▲TOP