🚙

質量と反発係数を考慮した衝突時の速度の求め方

2023/09/24に公開

登場する変数

変数 意味 備考
e 反発係数 1.0 を超えて反発することは普通ない
am 車aの質量
as 車aの速度
as2 車aの速度(衝突後) ← これを求めたい
bm 車bの質量
bs 車bの速度
bs2 車bの速度(衝突後) ← これを求めたい

公式1. 運動量保存則

am * as + bm * bs = am * as2 + bm * bs2

「質量×速度」の総和は衝突後も変わらない。

公式2. 反発係数

e = -(bs2 - as2) / (bs - as)

個々に車が進んでいる方向を正とするのではなく共通で一つの方向を正と考える。もし逆走車と正面衝突する場合、一方の速度は負になっている。

移項する

二つの公式を合体して as2 と bs2 を左辺に置く式にする。

as2 = (am*as + bm*bs - (e * bm * (as - bs))) / (am + bm)``bs2 = (am*as + bm*bs + (e * am * (as - bs))) / (am + bm)

あとは代入していくと衝突後の速度が求まる。

飲酒運転

e  = 1.0                        # 反発係数
am = 8.0                        # 車aの質量
as = 5.0                        # 車aの速度
bm = 8.0                        # 車bの質量
bs = 0.0                        # 車bの速度
as2 = (am*as + bm*bs - (e * bm * (as - bs))) / (am + bm)  # => 0.0
bs2 = (am*as + bm*bs + (e * am * (as - bs))) / (am + bm)  # => 5.0

反発係数は 1.0 なのでお互いの車はめちゃくちゃ固かった。a と b は同じ質量つまり同じ車種だった。b は信号待ちしていた。そこに a が速度 5 で突っ込んだ。a はぴったり止まったが、b は速度 5 で吹っ飛んだ。

煽り運転

e  = 1.0                        # 反発係数
am = 5.0                        # 車aの質量
as = -3.0                       # 車aの速度
bm = 5.0                        # 車bの質量
bs = -6.0                       # 車bの速度
as2 = (am*as + bm*bs - (e * bm * (as - bs))) / (am + bm)  # => -6.0
bs2 = (am*as + bm*bs + (e * am * (as - bs))) / (am + bm)  # => -3.0

反発係数は 1.0 なのでお互いの車はめちゃくちゃ固かった。a と b は同じ質量つまり同じ車種だった。a と b は左方向に進んでいた。a は b の前方に出て急ブレーキをかけた。b は衝突した。a は押し出されて加速し b は速度が落ちた。

高齢ドライバー

e  = 0.5                        # 反発係数
am = 2.0                        # 車aの質量
as = 4.0                        # 車aの速度
bm = 1.0                        # 車bの質量
bs = -6.0                       # 車bの速度
as2 = (am*as + bm*bs - (e * bm * (as - bs))) / (am + bm)  # => -1.0
bs2 = (am*as + bm*bs + (e * am * (as - bs))) / (am + bm)  # => 4.0

大型トラック a と逆走の乗用車 b が正面衝突した。反発係数は 0.5 なので、おそらく乗用車の方がへしゃげた。その上、吹っ飛んだ。乗用車はかなりのスピードが出ていたため大型トラックも衝撃で少し後退した。

コード
class App < Base
  def initialize
    super

    a = window_wh * V[0.3, 0.33]
    b = window_wh * V[0.7, 0.33]
    @points = [a, b]

    @mode = 0
  end

  def button_down(id)
    super

    if id == Gosu::KB_Z
      @mode = @mode.next.modulo(3)
    end
  end

  def draw
    super

    a, b = @points
    scale = 20

    if @mode == 0
      e = 1.0   # 反発係数
      am = 8.0  # 物体aの質量
      as = 5.0  # 物体aの速度
      bm = 8.0  # 物体bの質量
      bs = 0.0  # 物体bの速度
    end

    if @mode == 1
      e = 1.0   # 反発係数
      am = 5.0  # 物体aの質量
      as = -3   # 物体aの速度
      bm = 5.0  # 物体bの質量
      bs = -6.0 # 物体bの速度
    end

    if @mode == 2
      e = 0.5   # 反発係数
      am = 2.0  # 物体aの質量
      as = 4.0  # 物体aの速度
      bm = 1.0  # 物体bの質量
      bs = -6.0 # 物体bの速度
    end

    as2 = (am*as + bm*bs - (e * bm * (as - bs))) / (am + bm)  # => -1.0
    bs2 = (am*as + bm*bs + (e * am * (as - bs))) / (am + bm)  # => 4.0

    arrow_head(b, a, "a")
    arrow_head(a, b, "b")
    vector_draw(a, a + (b - a).clamp_length_max(as * scale), "", as)
    vector_draw(b, b + (b - a).clamp_length_max(bs * scale), "", bs)

    translate(*(wh * V[0, 0.33])) do
      vector_draw(a, a + (b - a).clamp_length_max(as2 * scale), "", as2.round(2))
      vector_draw(b, b + (b - a).clamp_length_max(bs2 * scale), "", bs2.round(2))
    end
  end

  def window_size_default
    V[800, 80]
  end

  show
end

参照

Discussion