アットウィキロゴ

実験:野球ボールの軌道計算

next up previous 次へ: レポートに関して 上へ: 実験1:C++/Octaveによる微分方程式の数値解法 戻る: 例題

実験:野球ボールの軌道計算

前節までで学習したオイラー法を用いて,ピッチャーが投げた野球ボールを打者が打った時のボールの軌道を計算するプログラムをC++言語を用いて作成しよう.

まず,ボールの運動に関する基礎方程式を説明する.運動を記述するには,投射物の位置ベクトル  r(t) と速度ベクトル  v(t) を計算する必要がある.この運動方程式は, \displaystyle \frac{dv}{dt} = \frac{1}{m}F_{a}(v) - g \hat{y}; \hspace{10mm} \frac{dr}{dt} = v (14)

となる.ただし, m は投射物の質量,  F_{a}(v) は空気抵抗による力, g は重力加速度, \hat{y} は鉛直方向の単位ベクトルである.実際の空気抵抗の計算は非常に複雑になるので,ここでは次の近似式を用いることとする. \displaystyle F_{a} = - \frac{1}{2}C_{d} \rho A \vert v\vert v (15)

ここで, C_{d} は抵抗計数, \rho は空気の密度, A は投射物の横断面積である.

空気抵抗を無視できる場合,運動方程式は以下の方法で解析的に解くことができる. \displaystyle r(t) = r_{1} + v_{1}t - \frac{1}{2}g t^{2} \hat{y} (16)

ただし,  r_{1}\equiv r(t=0) v_{1}\equiv v(t=0) は位置と速度の初期値である.

以下にプログラムの概要をまとめる.

\begin{itembox}[c]{プログラム概要} \begin{itemize} \item ボールの初期位置 $$r_{1... ...�屬鯢充┐垢襦\item ボールの軌道をグラフ表示する. \end{itemize}\end{itembox}

#include "NumMeth.h"

void main() {

 //* ボールの初期位置及び初期速度を設定する.
 double y1, speed, theta;
 double r1[2+1], v1[2+1], r[2+1], v[2+1], accel[2+1]; 
   cout << "高さの初期値(メートル) : "; cin >> y1;
 r1[1] = 0; r1[2] = y1;    // 初期位置ベクトル
 cout << "初期速度(m/s) : "; cin >> speed;
 cout << "初期角度(度) : "; cin >> theta;
 const double pi = 3.141592654;
 v1[1] = speed*cos(theta*pi/180);   // 初期速度 (x)
 v1[2] = speed*sin(theta*pi/180);   // 初期速度 (y)
 r[1] = r1[1]; r[2] = r1[2];   // 初期位置および初期速度を設定
 v[1] = v1[1]; v[2] = v1[2];
 //* 物理パラメータを設定(質量, Cd値など)
 double Cd = 0.35;       // 空気抵抗(無次元)
 double area = 4.3e-3;   // 投射物の横断面積(m^2)
 double grav = 9.81;     // 重力加速度(m/s^2)
 double mass = 0.145;    // 投射物の質量(kg)
 double airFlag, rho;
 cout << "空気抵抗(あり:1, なし:0) : "; cin >> airFlag;
 if( airFlag == 0 )
   rho = 0;   // 空気抵抗なし
 else
   rho = 1.2;   // 空気の密度(kg/m^3)
 double air_const = -0.5*Cd*rho*area/mass;   // 空気抵抗定数
 //* ボールが地面に着くまで, あるいは最大の刻み数になるまでループ
 double tau;
 cout << "時間刻みτ(秒) : "; cin >> tau;
 int iStep, maxStep = 1000;   // 最大の刻み数
 double *xplot, *yplot, *xNoAir, *yNoAir;
 xplot = new double [maxStep + 1];
 yplot = new double [maxStep + 1];
 xNoAir = new double [maxStep + 1];
 yNoAir = new double [maxStep + 1];
 for( iStep=1; iStep<=maxStep; iStep++ ) {
   //* プロット用に位置(計算値および理論値)を記録する
   xplot[iStep] = r[1];   // プロット用に軌道を記録
   yplot[iStep] = r[2];
   double t = ( iStep-1 )*tau;   // 現在時刻
   xNoAir[iStep] = r1[1] + v1[1]*t; // 位置(x)
   yNoAir[iStep] =  ??????          // 位置(y)
   //* ボールの加速度を計算する
   double normV = sqrt( v[1]*v[1] + v[2]*v[2] );
   accel[1] = air_const*normV*v[1];   // 空気抵抗
   accel[2] = air_const*normV*v[2];   // 空気抵抗
   accel[2] -= grav;                  // 重力
   //* オイラー法を用いて, 新しい位置および速度を計算する

/* ここにオイラー法のアルゴリズムを書く */

   //* ボールが地面に着いたら(y < 0)ループを抜ける

/* if文を使って書く */

 }
 //* 最大到達高さと滞空時間を表示する
 cout << "最大到達高さは" << r[1] << "メートル" << endl;
           滞空時間の表示をここに書く
 //* プロットする変数を出力する
 //   xplot, yplot xNoAir, yNoAir
 ofstream xplotOut("xplot.txt"), yplotOut("yplot.txt"), 
   xNoAirOut("xNoAir.txt"), yNoAirOut("yNoAir.txt");
 int i;
 for( i=1; i<=iStep+1; i++ ) {
   xplotOut << xplot[i] << endl;
   yplotOut << yplot[i] << endl;
 }
 for( i=1; i<=iStep+1; i++ ) {
   xNoAirOut << xNoAir[i] << endl;
   yNoAirOut << yNoAir[i] << endl;
 }
 delete [] xplot, yplot, xNoAir, yNoAir;  // メモリを開放

}

問題:3

   ボールの軌道のグラフを gnuplot で出力せよ.なお,時間刻み  \tau 0 &lt; t \leq 2 の間で5個選ぶこと.補助的に Octave を用いてよもい. 

問題:4

   時間刻み  \tau の設定によって,計算結果が大きく異なること が確認できるが,その理由を考察せよ. 

問題:5

   オイラー法よりも高精度な数値計算アルゴリズムについて調べて よ.余力のある人は,アルゴリズムを実装しその結果をオイラー法 と比較してみよ. 

Tomoki MIYAZATO 平成16年6月29日

最終更新:2010年06月22日 02:08
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。