mirror of
https://github.com/NotAShelf/projectile-simulation.git
synced 2024-11-22 13:20:47 +00:00
make params customizable
This commit is contained in:
parent
1330fae08d
commit
e55c86767a
4 changed files with 93 additions and 1 deletions
16
README.md
16
README.md
|
@ -18,3 +18,19 @@ Run the main.py script:
|
||||||
```shell
|
```shell
|
||||||
python main.py
|
python main.py
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Or alternatively, with your own parameters:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
python main.py --g 9.8 --C_d 0.02 --v_init 150 --theta 45 --h_init 20 --dt 0.01 --t_end 10
|
||||||
|
```
|
||||||
|
|
||||||
|
### Arguments
|
||||||
|
|
||||||
|
- `--g`: The acceleration due to gravity in m/s^2. Default is 9.81.
|
||||||
|
- `--C_d`: The drag coefficient. Default is 0.01.
|
||||||
|
- `--v_init`: The initial velocity in m/s. Default is 100.
|
||||||
|
- `--theta`: The launch angle in degrees. Default is 180.
|
||||||
|
- `--h_init`: The launch height in meters. Default is 10.
|
||||||
|
- `--dt`: The time step in seconds. Default is 0.01.
|
||||||
|
- `--t_end`: The total time of the simulation in seconds. Default is 10.
|
||||||
|
|
33
main.py
33
main.py
|
@ -1,9 +1,40 @@
|
||||||
|
import argparse
|
||||||
from projectile.simulation import ProjectileSimulation
|
from projectile.simulation import ProjectileSimulation
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
sim = ProjectileSimulation(v_init=100, theta=np.radians(45))
|
parser = argparse.ArgumentParser(description="Run a projectile simulation.")
|
||||||
|
parser.add_argument(
|
||||||
|
"--g", type=float, default=9.81, help="Acceleration due to gravity (m/s^2)"
|
||||||
|
)
|
||||||
|
parser.add_argument("--C_d", type=float, default=0.01, help="Drag coefficient")
|
||||||
|
parser.add_argument(
|
||||||
|
"--v_init", type=float, default=100, help="Initial velocity (m/s)"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--theta",
|
||||||
|
type=float,
|
||||||
|
default=np.radians(180),
|
||||||
|
help="Launch angle (degrees to radians)",
|
||||||
|
)
|
||||||
|
parser.add_argument("--h_init", type=float, default=10, help="Launch height (m)")
|
||||||
|
parser.add_argument("--dt", type=float, default=0.01, help="Time step (s)")
|
||||||
|
parser.add_argument(
|
||||||
|
"--t_end", type=float, default=10, help="Total time of simulation (s)"
|
||||||
|
)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
sim = ProjectileSimulation(
|
||||||
|
g=args.g,
|
||||||
|
C_d=args.C_d,
|
||||||
|
v_init=args.v_init,
|
||||||
|
theta=args.theta,
|
||||||
|
h_init=args.h_init,
|
||||||
|
dt=args.dt,
|
||||||
|
t_end=args.t_end,
|
||||||
|
)
|
||||||
sim.run()
|
sim.run()
|
||||||
sim.plot()
|
sim.plot()
|
||||||
sim.print_range()
|
sim.print_range()
|
||||||
|
|
|
@ -3,6 +3,44 @@ import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
|
||||||
class ProjectileSimulation:
|
class ProjectileSimulation:
|
||||||
|
"""
|
||||||
|
A class used to simulate the motion of a projectile with air resistance.
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
Attributes
|
||||||
|
----------
|
||||||
|
g : float
|
||||||
|
acceleration due to gravity (m/s^2)
|
||||||
|
C_d : float
|
||||||
|
drag coefficient
|
||||||
|
v_init : float
|
||||||
|
initial velocity (m/s)
|
||||||
|
theta : float
|
||||||
|
launch angle (degrees to radians)
|
||||||
|
h_init : float
|
||||||
|
launch height (m)
|
||||||
|
dt : float
|
||||||
|
time step (s)
|
||||||
|
t_end : float
|
||||||
|
total time of simulation (s)
|
||||||
|
|
||||||
|
Methods
|
||||||
|
-------
|
||||||
|
reset():
|
||||||
|
Resets the simulation to its initial state.
|
||||||
|
calculate_acceleration(t, state):
|
||||||
|
Calculates the acceleration at a given time and state.
|
||||||
|
update_state(t, state):
|
||||||
|
Updates the state using the Runge-Kutta method.
|
||||||
|
run():
|
||||||
|
Runs the simulation.
|
||||||
|
plot():
|
||||||
|
Plots the trajectory of the projectile.
|
||||||
|
print_range():
|
||||||
|
Prints the range of the projectile.
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
g=9.81,
|
g=9.81,
|
||||||
|
@ -23,6 +61,7 @@ class ProjectileSimulation:
|
||||||
self.reset()
|
self.reset()
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
|
"""Resets the simulation to its initial state."""
|
||||||
self.x = [0]
|
self.x = [0]
|
||||||
self.y = [self.h_init]
|
self.y = [self.h_init]
|
||||||
self.vx = [self.v_init * np.cos(self.theta)]
|
self.vx = [self.v_init * np.cos(self.theta)]
|
||||||
|
@ -30,6 +69,7 @@ class ProjectileSimulation:
|
||||||
self.t = [0]
|
self.t = [0]
|
||||||
|
|
||||||
def calculate_acceleration(self, t, state):
|
def calculate_acceleration(self, t, state):
|
||||||
|
"""Calculates the acceleration at a given time and state."""
|
||||||
x, y, vx, vy = state
|
x, y, vx, vy = state
|
||||||
v = np.sqrt(vx**2 + vy**2)
|
v = np.sqrt(vx**2 + vy**2)
|
||||||
F_air_x = -self.C_d * v * vx
|
F_air_x = -self.C_d * v * vx
|
||||||
|
@ -39,6 +79,7 @@ class ProjectileSimulation:
|
||||||
return [vx, vy, ax, ay]
|
return [vx, vy, ax, ay]
|
||||||
|
|
||||||
def update_state(self, t, state):
|
def update_state(self, t, state):
|
||||||
|
"""Updates the state using the Runge-Kutta method."""
|
||||||
k1 = self.calculate_acceleration(t, state)
|
k1 = self.calculate_acceleration(t, state)
|
||||||
k2 = self.calculate_acceleration(
|
k2 = self.calculate_acceleration(
|
||||||
t + 0.5 * self.dt, [s + 0.5 * self.dt * k for s, k in zip(state, k1)]
|
t + 0.5 * self.dt, [s + 0.5 * self.dt * k for s, k in zip(state, k1)]
|
||||||
|
@ -55,6 +96,7 @@ class ProjectileSimulation:
|
||||||
]
|
]
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
"""Runs the simulation."""
|
||||||
while self.t[-1] < self.t_end:
|
while self.t[-1] < self.t_end:
|
||||||
state = [self.x[-1], self.y[-1], self.vx[-1], self.vy[-1]]
|
state = [self.x[-1], self.y[-1], self.vx[-1], self.vy[-1]]
|
||||||
state = self.update_state(self.t[-1], state)
|
state = self.update_state(self.t[-1], state)
|
||||||
|
@ -65,6 +107,7 @@ class ProjectileSimulation:
|
||||||
self.t.append(self.t[-1] + self.dt)
|
self.t.append(self.t[-1] + self.dt)
|
||||||
|
|
||||||
def plot(self):
|
def plot(self):
|
||||||
|
"""Plots the trajectory of the projectile."""
|
||||||
plt.plot(self.x, self.y)
|
plt.plot(self.x, self.y)
|
||||||
plt.xlabel("Horizontal distance (m)")
|
plt.xlabel("Horizontal distance (m)")
|
||||||
plt.ylabel("Vertical distance (m)")
|
plt.ylabel("Vertical distance (m)")
|
||||||
|
@ -72,5 +115,6 @@ class ProjectileSimulation:
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
||||||
def print_range(self):
|
def print_range(self):
|
||||||
|
"""Prints the range of the projectile."""
|
||||||
range_projectile = self.x[-1]
|
range_projectile = self.x[-1]
|
||||||
print(f"Range of projectile: {range_projectile:.2f} m")
|
print(f"Range of projectile: {range_projectile:.2f} m")
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
numpy
|
numpy
|
||||||
matplotlib
|
matplotlib
|
||||||
|
argparse
|
||||||
|
|
Loading…
Reference in a new issue