自由落下2の続き
自由落下2の追加の検討です。
ここでは、落下の途中で、空気抵抗係数が大きくなる場合についてです。
落下の途中で、空気抵抗係数が著しく大きくなるのは、スカイダイビングによる落下です。
スカイダイビングで、降下しているときの速度は、50m/s~60m/sの速度になるようですが、地表に近づいて、パラシュートを開いたとき、どれ位で減速するのかまず考えてみます。
パラシュートを開く前と、開いた後では空気抵抗係数が、150倍程度変化します。
パラシュートの開き方についてはスカイダイブ藤岡のパラシュートオープン解説を読んでください。
急激にオープンすると、パラシュートと、スカイダイバーにダメージを与えるので、パラシュートは徐々に開くように工夫されています。
現代のスカイダイビングで利用されているパラシュートは、小さなパラグライダーであり、降下時、30km/h~50km/hで前進するので揚力が働き、降下率は3m/s~4m/sで、前進しない時は、5m/s~6m/s位になるようです。
自衛隊でのパラシュートは、円形であり、滑空の降下はあまりなく、飛行機が低空でとび、飛行機から飛び降りてから、少し間をおいて開いているようですが、スカイダイビングの様に長い時間パラシュートを開かずに落下することは無いようです。
スカイダイビングのパラシュートを開くタイミングは、地上から1000m位なので、パラシュートが無かったら地上まで20秒弱の時間となります。
メインのパラシュートが開かなかったら、リザーブのパラシュートを開くので500mで開いて減速をする必要があります。
落下速度60m/sから5m/s迄、500mの高さで等減速度で減速するのが、一番負荷が小さくて済みます。
しかし、空気抵抗が、速度の二乗に比例する為に、等加速度で減速する様に、パ゛シュートを開く細工をすることは、非常に困難かと思われます。
そこで、パラシュートが開くときの空気抵抗係数が、sinカーブ変化するものとして、計算してみる事にしました。
実際には、スカイダイビングでの、パラシュートが開くときの速度変化を計測すればよいのでしょうが、データーが無いので、代用計算値を使用します。
(パラシュートを製作しているメーカーには、実測したデーターがあるのですが、公開されていないようなので)
此処での計算は、あくまでも、パラシュートがsinカーブで開くとしたもので、実際の値とは違いますので注意してください。
パラシュートによる空気抵抗が係数k[kg/m]に対してk*P
になる場合と、k*P2になる場合として計算します。
パラシュートにより減速が働き、パラシュートでの落下時間が無限大の時の速度に近づきます。
k : ダイバー空気抵抗係数
kb: パラシュート空気抵抗係数
m: 質量
t: 時間
g: 重力加速度
j := 1000;
dt := t / j;
Qs2 := -pi / 2;
dq := pi / j;
for i := 0 to j do begin
ti := i * dt;
sq := (1 + sin(Qs2 + dq * i)) / 2; //
Q パラシュートの開き係数sin(-pi/2~pi/2)
if
checkbox1.Checked = true then
mkb := k +
kB * sq * sq // 空気抵抗係数計算 sin(Q)^2
else
mkb := k + kB * sq; //
空気抵抗係数計算 sin(Q)
vmax := sqrt(m * g / mkb); //
t∞速度 m/s
dm := vmax * vmax * mkb; //
t∞抗力 m.kg/s^2
dv := v * v * mkb; //
抗力 m.kg/s^2
mdg := (dv - dm) / m; //
加速度 m/s^2
fv := v - mdg * dt; //
予減速 m/s
ndv := fv * fv * mkb; //
予抗力 m.kg/s^2
nmdg := (ndv - dm) / m; //
予加速度 m/s^2
mdg := (nmdg + mdg) / 2; //
平均加速度 m/s^2
fv := v - mdg * dt; //
減速 m/s
if fv < 0 then break;
h := h + (fv + v) /
2 * dt; // 高さ + 平均速度*時間 m
v := fv; // 新速度 m/s
end;
若干、値が値が大きくなる傾向がありますが、1000分割程度で、4桁の精度を得ることが可能です。
kがダイバーの空気抵抗係数、kpがパラシュートの空気抵抗係数です。
空気密度は高度によって変化するのですが、此処では一定の値としています。
プログラム
unit main; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Buttons, Vcl.ExtCtrls, VclTee.TeeGDIPlus, VCLTee.TeEngine, VCLTee.Series, VCLTee.TeeProcs, VCLTee.Chart; type TForm1 = class(TForm) GroupBox1: TGroupBox; rhoEdit: TLabeledEdit; sumEdit: TLabeledEdit; KcalcBtn: TBitBtn; kEdit: TLabeledEdit; CdEdit: TLabeledEdit; GroupBox2: TGroupBox; mEdit: TLabeledEdit; gEdit: TLabeledEdit; vhBtn: TBitBtn; Memo1: TMemo; Chart1: TChart; Series1: TLineSeries; jEdit: TLabeledEdit; Series2: TLineSeries; GroupBox3: TGroupBox; sum2Edit: TLabeledEdit; k2Edit: TLabeledEdit; cd2Edit: TLabeledEdit; kcalc2Btn: TBitBtn; tBEdit: TLabeledEdit; CheckBox1: TCheckBox; Series3: TPointSeries; RadioGroup1: TRadioGroup; Label1: TLabel; Series4: TPointSeries; procedure KcalcBtnClick(Sender: TObject); procedure vhBtnClick(Sender: TObject); procedure kcalc2BtnClick(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private 宣言 } procedure downN(tB, k, kb, m, g: extended; j: integer); public { Public 宣言 } end; var Form1: TForm1; implementation {$R *.dfm} // パラシュート空気抗力係数から空気抵抗計算kg/m計算 // パラシュートが開いた時の代表面積で、開く途中の // 面積は、降下計算の中でsinカーブで計算します。 procedure TForm1.kcalc2BtnClick(Sender: TObject); var kp : extended; // 空気抵抗係数 kg/m Cdp: extended; // 空気抗力係数 r : extended; // 空気密度 kg/m^3 Sp : extended; // 代表面積 m^2 ch : integer; begin val(Cd2Edit.Text, Cdp, ch); if ch <> 0 then begin Memo1.Text := 'Cdp:空気抗力係数に間違いがあります。'; exit; end; val(rhoEdit.Text, r, ch); if ch <> 0 then begin Memo1.Text := 'ρ:空気密度に間違いがあります。'; exit; end; val(sum2Edit.Text, Sp, ch); if ch <> 0 then begin Memo1.Text := 'Sp:代表面積に間違いがあります。'; exit; end; kp := Cdp * r * sp / 2; k2Edit.Text := floatTostr(kp); end; // ダイバー空気抗力係数から空気抵抗計算kg/m計算 // パラシュートが開くとダイバーの姿勢が変わり // 代表面積が変わるのは考慮なし // パラシュートが開いた時は、ダイバーの空気抵抗は // 計算上殆ど影響なし procedure TForm1.KcalcBtnClick(Sender: TObject); var k : extended; // 空気抵抗係数 kg/m Cd : extended; // 空気抗力係数 r : extended; // 空気密度 kg/m^3 S : extended; // 代表面積 m^2 ch : integer; begin val(CdEdit.Text, Cd, ch); if ch <> 0 then begin Memo1.Text := 'Cd:空気抗力係数に間違いがあります。'; exit; end; val(rhoEdit.Text, r, ch); if ch <> 0 then begin Memo1.Text := 'ρ:空気密度に間違いがあります。'; exit; end; val(sumEdit.Text, S, ch); if ch <> 0 then begin Memo1.Text := 'S:代表面積に間違いがあります。'; exit; end; k := Cd * r * s / 2; kEdit.Text := floatTostr(k); end; // 鉛直降下 滑空の計算はなし // パラシュートがsinカーブで開くものとして計算 // ダイバーの姿勢変化は考慮無し // tB: 時間 sec // k: 身体部 空気抵抗係数 kg/m // kb: パラシュート 空気抵抗係数 kg/m // m: 身体部荷重(重さ) kg // g: 重力加速度 m/s^2 procedure TForm1.downN(tB, k, KB, m, g: extended; j: integer); var vmax, ti : extended; h, v: extended; hb, vb: extended; dv, dm, dt, mdg, fv : extended; ndv, nmdg : extended; i, n : integer; mkB : extended; maxmdg : extended; dq, sq : extended; Qs2 : extended; kf : extended; begin series1.Clear; series2.Clear; series3.Clear; series4.Clear; Chart1.RightAxis.AutomaticMaximum := True; case radiogroup1.ItemIndex of 0: begin Chart1.LeftAxis.Title.Text := 'G'; Chart1.RightAxis.Title.Text := 'm'; end; 1: begin Chart1.LeftAxis.Title.Text := 'G'; Chart1.RightAxis.Title.Text := 'm/s'; Chart1.RightAxis.AutomaticMaximum := False; Chart1.RightAxis.Maximum := 0; end; 2: begin Chart1.LeftAxis.Title.Text := 'kg/m'; Chart1.RightAxis.Title.Text := 'm'; end; 3: begin Chart1.LeftAxis.Title.Text := 'G'; Chart1.RightAxis.Title.Text := 'm'; end; 4: begin Chart1.LeftAxis.Title.Text := 'G'; Chart1.RightAxis.Title.Text := '%'; end; end; n := j div 10; h := 0; // 高さ or 距離 m hb := h; dt := tb / j; // Δt fv := 0; // 速度 m/s vmax := sqrt(m * g / k); // t∞速度 m/s v := vmax; vb := v; // 初速度 maxmdg := 0; // 最大加速度 Qs2 := - pi / 2; // sin 開始角度 rad dq := pi / j; // Δ角度 Δrad sq := 0; for i := 0 to j + n do begin ti := i * dt; if i <= J then begin sq := (1 + sin(Qs2 + dq * i)) / 2; // Q パラシュートの開き係数sin(-pi/2~pi/2) if checkbox1.Checked = true then mkb := k + kB * sq * sq // 空気抵抗係数 sin(Q)^2修正 else mkb := k + kB * sq; // 空気抵抗係数 sin(Q)修正 end else mkb := k + kB; vmax := sqrt(m * g / mkb); // t∞速度 m/s dm := vmax * vmax * mkb; // t∞抗力 m.kg/s^2 dv := v * v * mkb; // 抗力 m.kg/s^2 mdg := (dv - dm) / m; // 加速度 m/s^2 fv := v - mdg * dt; // 予減速 m/s ndv := fv * fv * mkb; // 予抗力 m.kg/s^2 nmdg := (ndv - dm) / m; // 予加速度 m/s^2 mdg := (nmdg + mdg) / 2; // 平均加速度 m/s^2 fv := v - mdg * dt; // 減速 m/s if fv < 0 then break; h := h + (fv + v) / 2 * dt; // 高さ + 平均速度*時間 m v := fv; // 新速度 m/s kf := (m - v * v * k / g) / m; // 身体部 G if i = j then begin hb := h; vb := v; end; if radiogroup1.ItemIndex = 3 then begin if maxmdg < mdg + kf * g then maxmdg := mdg + kf * g; end else if maxmdg < mdg then maxmdg := mdg; case radiogroup1.ItemIndex of 0: begin series1.AddXY(ti , -mdg / g); // 加速度 G series2.AddXY(ti , -h); // 距離 m end; 1: begin series1.AddXY(ti , -mdg / g); // 加速度 G series2.AddXY(ti , -v); // 速度 m/s end; 2: begin series1.AddXY(ti , mkb); // 空気抵抗係数 kg/m series2.AddXY(ti , -h); // 距離 m end; 3: begin series1.AddXY(ti , -mdg /g - kf); // 加速度 G series2.AddXY(ti , -h); // 距離 m end; 4: begin series1.AddXY(ti , -mdg / g); // 加速度 G if checkbox1.Checked = false then series2.AddXY(ti , sq * 100) // パラシュート開度% else series2.AddXY(ti , sq * sq * 100); // パラシュート開度% end; end; end; if fv < 0 then begin memo1.Lines.Append('新減速計算 分割数不足、時間が長い為計算出来ません。'); exit; end; if checkbox1.Checked = true then memo1.Lines.Append('パラシュートの開く速度が時間のsin二乗に比例') else memo1.Lines.Append('パラシュートの開く速度が時間のsinに比例'); memo1.Lines.Append('t∞速度 ' + floatTostr(-vmax) + ' m/s'); memo1.Lines.Append(floattostr(tB) + 'sec後 速度 ' + floatTostr(-vb) + ' m/s'); memo1.Lines.Append(floattostr(tB) + 'sec後 高さ ' + floatTostr(-hb) + ' m'); if radiogroup1.ItemIndex = 3 then memo1.Text := memo1.Text + 'ライザー最大負荷 ' + floatTostr(-maxmdg / g) + ' G' else memo1.Text := memo1.Text + '最大加速度 ' + floatTostr(-maxmdg / g) + ' G'; end; // vh計算実行 procedure TForm1.vhBtnClick(Sender: TObject); var k : extended; // 空気抵抗係数 kg/m kB : extended; // 空気抵抗係数 kg/m m : extended; // 質量 kg tB : extended; // 減速時間 sec g : extended; // 重力加速度 m/sec^2 ch : integer; j : integer; begin Memo1.Clear; val(kEdit.Text, k, ch); if ch <> 0 then begin Memo1.Text := 'k:空気抵抗係数に間違いがあります。'; exit; end; if k <= 0 then begin Memo1.Text := 'k:空気抵抗係数の値は0(ゼロ)より大きくしてください。'; exit; end; val(k2Edit.Text, kB, ch); if ch <> 0 then begin Memo1.Text := 'kB:空気抵抗係数に間違いがあります。'; exit; end; if kB <= 0 then begin Memo1.Text := 'kB:空気抵抗係数の値は0(ゼロ)より大きくしてください。'; exit; end; val(mEdit.Text, m, ch); if ch <> 0 then begin Memo1.Text := 'm:質量に間違いがあります。'; exit; end; if m <= 0 then begin Memo1.Text := 'm:質量の値は0(ゼロ)より大きくしてください。'; exit; end; val(tbEdit.Text, tB, ch); if ch <> 0 then begin Memo1.Text := 'tB:Reduce speed timeに間違いがあります。'; exit; end; if tB < 0 then begin Memo1.Text := 'tB:Reduce speed timeは0(ゼロ)より大きくしてください。'; exit; end; val(gEdit.Text, g, ch); if ch <> 0 then begin Memo1.Text := 'g:加速度に間違いがあります。'; exit; end; if g <= 0 then begin Memo1.Text := 'g:加速度の値は0(ゼロ)より大きくしてください。'; exit; end; val(jEdit.Text, j, ch); if ch <> 0 then begin Memo1.Text := 'j:分割数に間違いがあります。'; exit; end; if j <= 2 then begin Memo1.Text := 'j:分割数は2より大きくしてください。'; exit; end; if j > 10000000 then begin Memo1.Text := 'j:分割数が大きすぎます。'; exit; end; memo1.Clear; downN(tB, k, kB, m, g, j); end; procedure TForm1.FormCreate(Sender: TObject); begin label1.Caption := 'ρ:空気密度[kg/m^3]は' + #13#10 + ' 左の値です。'; end; end.