In diesem Beitrag soll gezeigt werden, wie mit einem Python Programm die Flugbahn eines Geschosses berechnet werden kann. Als Eingabe wird folgendes eingegeben: Mündungsgeschwindigkeit, Geschossgewicht, Ballistischer Koeffizient, Zielfernrohrhöhe
Als Ausgabe wird eine Tabelle mit Geschwindigkeit, Energie, Geschossabfall (0–300 m in 50 m-Schritten) unter Berücksichtigung des Luftwiderstands (G1-Modell) berechnet.
Zur besseren Visualisierung der Ergebnisse wird eine grafische Darstellung der Flugbahn relativ zur Visierlinie erstellt.
Das Programm simuliert die ballistische Flugbahn eines Geschosses, indem es die wichtigsten physikalischen Größen berechnet:
Diese Werte definieren die Eigenschaften der Patrone und die Ausgangsbedingungen.
v0 = 1050 # Mündungsgeschwindigkeit in m/s
mass = 0.0032 # Geschossmasse in kg
bc = 0.200 # Ballistischer Koeffizient (G1)
scope_height = 0.045 # Zielfernrohrhöhe in m
Hier wird die Geschwindigkeit über die Entfernung berechnet – exponentieller Abfall durch Luftwiderstand. Je höher der BC, desto weniger bremst die Luft das Geschoss.
def velocity_at_distance(v0, bc, distance):
k = air_density / (bc * 1000)
return v0 * np.exp(-k * distance)
Berechnung der Energie erfolgt über folgenden Code-Abschnitt: Berechnung der Energie erfolgt überdie klassische Formel der Kinetik. Die Flugzeit ergibt sich aus der Entfernung geteilt durch Geschwindigkeit. Und der Abfall also wie weit das Geschoss durch Gravitation sinkt – relativ zur Visierlinie (Zielfernrohrhöhe wird berücksichtigt)
E = 0.5 * mass * v**2
t = d / v
drop = -0.5 * g * t**2 + scope_height
Die berechneten Ergebnisse werden dann als Tabelle und in Form einer Flugbahn dargestellt:
results.append((d, round(v, 2), round(E, 2), round(drop * 100, 2)))
plt.plot(x_vals, y_vals, marker='o')
Alles zusammen sieht dann so aus:
import numpy as np
import matplotlib.pyplot as plt
# Eingabewerte
v0 = 1050 # Mündungsgeschwindigkeit in m/s
mass = 0.0032 # Geschossmasse in kg
bc = 0.200 # Ballistischer Koeffizient (G1)
scope_height = 0.045 # Zielfernrohrhöhe in m (4.5 cm)
air_density = 1.225 # kg/m³ (Standard)
g = 9.81 # Erdbeschleunigung
# Entfernungsschritte
distances = np.arange(0, 301, 50) # 0 bis 300 m in 50 m-Schritten
# Funktion zur Berechnung der Geschwindigkeit mit Luftwiderstand (vereinfachtes Modell)
def velocity_at_distance(v0, bc, distance):
# Näherung: Geschwindigkeit sinkt exponentiell mit Entfernung
# Formel: v = v0 * exp(-k * x), wobei k = Luftwiderstandskoeffizient
k = air_density / (bc * 1000) # Näherungswert
return v0 * np.exp(-k * distance)
# Berechnungen
results = []
for d in distances:
v = velocity_at_distance(v0, bc, d)
E = 0.5 * mass * v**2
t = d / v if v > 0 else 0
drop = -0.5 * g * t**2 + scope_height # Relativ zur Visierlinie
results.append((d, round(v, 2), round(E, 2), round(drop * 100, 2))) # Drop in cm
# Tabelle ausgeben
print(f"{'Entfernung (m)':>15} | {'v (m/s)':>10} | {'Energie (J)':>12} | {'Abfall (cm)':>13}")
print("-" * 60)
for r in results:
print(f"{r[0]:>15} | {r[1]:>10} | {r[2]:>12} | {r[3]:>13}")
# Grafische Darstellung
x_vals = [r[0] for r in results]
y_vals = [r[3] for r in results]
plt.figure(figsize=(10, 5))
plt.plot(x_vals, y_vals, marker='o', label="Geschossabfall zur Visierlinie")
plt.axhline(0, color='gray', linestyle='--', label="Visierlinie")
plt.xlabel("Entfernung (m)")
plt.ylabel("Abfall (cm)")
plt.title("Ballistische Flugbahn – 5,6x50 R MAG (inkl. Luftwiderstand)")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
Entfernung (m) | Geschwindigkeit (m/s) | Energie (J) | Geschossabfall (cm) | Laborierung |
---|---|---|---|---|
0 | 1015.00 | 1648.80 | 0.00 | 3.2 g / 1015 m/s / BC 0.200 |
50 | 982.62 | 1545.61 | -0.81 | 3.2 g / 1015 m/s / BC 0.200 |
100 | 951.41 | 1447.18 | -2.85 | 3.2 g / 1015 m/s / BC 0.200 |
150 | 921.32 | 1353.22 | -6.21 | 3.2 g / 1015 m/s / BC 0.200 |
200 | 892.31 | 1263.45 | -10.96 | 3.2 g / 1015 m/s / BC 0.200 |
250 | 864.34 | 1177.61 | -17.17 | 3.2 g / 1015 m/s / BC 0.200 |
300 | 837.38 | 1095.45 | -24.89 | 3.2 g / 1015 m/s / BC 0.200 |
0 | 900.00 | 1658.25 | 0.00 | 4.1 g / 900 m/s / BC 0.240 |
50 | 875.84 | 1572.65 | -0.83 | 4.1 g / 900 m/s / BC 0.240 |
100 | 852.53 | 1490.49 | -2.94 | 4.1 g / 900 m/s / BC 0.240 |
150 | 830.03 | 1411.61 | -6.39 | 4.1 g / 900 m/s / BC 0.240 |
200 | 808.31 | 1335.88 | -11.24 | 4.1 g / 900 m/s / BC 0.240 |
250 | 787.33 | 1263.15 | -17.54 | 4.1 g / 900 m/s / BC 0.240 |
300 | 767.06 | 1193.30 | -25.35 | 4.1 g / 900 m/s / BC 0.240 |
Das nachfolgende Python Programm erlaugt es verschiedene Laborierungen (Geschoss-Arten und Gewichte) miteinander zu vergleichen. Die zu vergleichewnden Patronen müssen in der Liste "Laborierungen" spezifiziert werden.
import numpy as np
import plotly.graph_objects as go
# Parameter für beide Laborierungen
laborierungen = [
{"name": "3.2 g / 1015 m/s / BC 0.200", "v0": 1015, "mass": 0.0032, "bc": 0.200},
{"name": "4.1 g / 900 m/s / BC 0.240", "v0": 900, "mass": 0.0041, "bc": 0.240}
]
scope_height = 0.045 # Zielfernrohrhöhe in m
g = 9.81 # Erdbeschleunigung
air_density = 1.225 # kg/m³
distances = np.arange(0, 301, 50) # 0–300 m in 50 m-Schritten
# Funktion zur Berechnung der Geschwindigkeit mit Luftwiderstand
def velocity(v0, bc, x):
k = air_density / (bc * 1000)
return v0 * np.exp(-k * x)
# Plot vorbereiten
fig = go.Figure()
# Berechnung und Visualisierung für jede Laborierung
for lab in laborierungen:
v_list, E_list, drop_list = [], [], []
for d in distances:
v = velocity(lab["v0"], lab["bc"], d)
E = 0.5 * lab["mass"] * v**2
t = d / v if v > 0 else 0
drop = -0.5 * g * t**2 + scope_height
v_list.append(round(v, 2))
E_list.append(round(E, 2))
drop_list.append(round(drop * 100, 2)) # in cm
# Flugbahn hinzufügen
fig.add_trace(go.Scatter(
x=distances,
y=drop_list,
mode='lines+markers',
name=f"Flugbahn – {lab['name']}",
hovertemplate=
"Entfernung: %{x} m
" +
"Abfall: %{y} cm
" +
f"Laborierung: {lab['name']}"
))
# Layout
fig.update_layout(
title="Ballistische Flugbahn – 5,6x50 R MAG (inkl. Luftwiderstand)",
xaxis_title="Entfernung (m)",
yaxis_title="Geschossabfall zur Visierlinie (cm)",
template="plotly_white",
legend_title="Laborierungen",
hovermode="x unified"
)
fig.show()
Das Ergebnis wird graphisch dargestellt u nd zeigt die unterschiedlichen Flugbahnen: