stimpmeter 9 ft — 俯瞰図(真上から)
| 時刻 (s) | 位置 (m) |
|---|
import math
# ボールがカップで止まるような速度で転がり始めた場合の、n秒後のボールの位置を計算する。
# 空気抵抗は考慮しない。
#
# stimpmeter_feet: ゴルフ場に書いてあるスティンプメーター値
# distance_to_cup_meter: カップまでの距離
#
# 戻り値は
# ([1秒ごとのボールの位置(m)]、ボールが止まるまでの秒数)
def ball_at(stimpmeter_feet: float, distance_to_cup_meter: float, slope_percent: float = 0.0):
g = 9.8
# フィート -> メートルに変換
stimpmeter_meter = stimpmeter_feet * 0.3048
# スティンプメーターから転がした球の初速
stimpmeter_initial_v = math.sqrt(2 * g * 0.1715) # 0.1715はスティンプメーターの高さ (m)
# スティンプメーターの計測値を使った転がり抵抗係数の計算
rolling_resistance_factor = (stimpmeter_initial_v ** 2) / (2 * g * stimpmeter_meter)
# 平坦なグリーン上のボール減速度 (m/s^2)
a_flat = rolling_resistance_factor * g
# 傾斜による加速度の補正。斜面に沿った重力 g*sin(theta) の近似。
# 上り(正)なら減速方向、下り(負)なら加速方向に働くので、
# 「減速度」に対しては符号そのまま加算すればよい:
# 上り: 重力が逆向きに働く -> 減速が強まる -> a_slope は正
# 下り: 重力が進行方向に働く -> 減速が弱まる -> a_slope は負
a_slope = g * (slope_percent / 100.0)
# 傾斜を考慮した実効減速度
a = a_flat + a_slope
if a <= 0:
# 下りが急すぎて転がり抵抗だけでは減速しきれず、止まらないケース
raise ValueError(
f"傾斜が急すぎてボールが止まりません "
f"(stimp={stimpmeter_feet}ft, slope={slope_percent}%, a_eff={a:.4f})"
)
# カップまでの距離をDとすると、
# カップで止まらなければいけないので、Dm地点での速度が0になるから、
# v(T) = v0 - a * T = 0
# -> T = v0 / a
# また、D = v0 * T + 1/2 * a * T^2 なので、
# D = v0 * (v0 / a) + 1/2 * a * (v0 / a)^2
# = (v0^2 / a) + (v0^2 / 2a)
# = v0^2 / 2a
# 求めたいのはv0なので、
# v0 = sqrt(2a * D)
v0 = math.sqrt(2 * a * distance_to_cup_meter)
def x(t):
# T秒後のボールの位置は
# D = v0 * T + 1/2 * a * T^2
# ただし減速なので
xT = (v0 * t) - ((1/2) * a * (t ** 2))
return xT
xts = []
T_stop = v0 / a
for T in range(0, int(T_stop)):
# ボールが1秒以内に止まるケースを考慮する
# ボールが止まるまでの時間は
# v(T) = v0 - a * T
# このときの速度が0なので
# v0 - a * T_stop = 0
xT = x(T+1)
xts.append(xT)
return (xts, T_stop)
stimpmeter_feet = [8.5, 9.0, 9.5, 10.0, 10.5]
meters = [0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, 10.0, 10.5, 11.0, 11.5, 12.0, 12.5, 13.0, 13.5, 14.0, 14.5, 15.0, 15.5, 16.0, 16.5, 17.0, 17.5, 18.0, 18.5, 19.0, 19.5, 20.0]
# 正が上り、負が下り
slope_percents = [-2.0, -1.0, 0.0, 1.0, 2.0]
for f in stimpmeter_feet:
print(f"{f}フィートグリーンの場合:")
for s in slope_percents:
print(f" 傾斜{s}%の場合:")
for m in meters:
ball_positions_m, total_s = ball_at(f, m, s)
print(f" カップまで{m}m: 止まるまでの時間: {total_s:.2f}秒")
print("\n".join([f" {i+1}秒後のボール位置: {pos:.5f}m\t" for i, pos in enumerate(ball_positions_m)]))