satschool / apps /code /trajectory.py
spiruel's picture
removing imgs
cc79988
Raw History Blame Contribute Delete
4.06 kB
from matplotlib import pyplot as plt
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
import numpy as np
def motion(v0, theta, t, g=9.81, x0=0, y0=0):
"""
Computes the trajectory of a projectile, given the initial velocity (v0),
launch angle (theta), and time (t).
"""
x = v0*np.cos(theta)*t
y = v0*np.sin(theta)*t - 0.5 * g * t**2
return x, y
def get_time(v0, theta, g=9.81, x0=0, y0=0):
"""
Computes the time of flight of a projectile, given the initial velocity (v0),
launch angle (theta), and distance (t).
"""
# Get the time to get back to the ground
# y = v0*np.sin(theta)*t - 0.5 * g * t**2 -> solve for y=0, t!=0
t_max = 2*v0*np.sin(theta)/g
# Create a time array
t = np.linspace(0, t_max, 100) # 0.1 is the time step
return t
def get_trajectory(v0, theta_deg, g=9.81, gravity_label="", x0=0, y0=0):
"""
Computes the trajectory of a projectile, given the initial velocity (v0),
launch angle (theta, in degrees). It creates a vector with times, and from that a
trajectory.
"""
# Convert theta
theta_rad = theta_deg * np.pi / 180
# Get the time to get back to the ground
t = get_time(v0, theta_rad, g=g, x0=x0, y0=y0)
# Get the trajectory for the times
x, y = motion(v0, theta_rad, t, g=g, x0=x0, y0=y0)
# Get a legend for the trajectory
legend = f"$v_0$={v0}, $\\theta$={theta_deg:.2f}, g={g} ({gravity_label})"
# Get the color
color_dict = {'Earth':"green", 'Moon':"gray", 'Mars':"red", 'Jupiter':"black"}
color = color_dict[gravity_label]
# Create a dictionary with the trajectory
trajectory_dict = {"x": x, "y": y, "legend": legend, "color": color, "v0": v0, "theta_deg": theta_deg}
return trajectory_dict
def plot_emoji(emoji_path, ax, x, y, zoom=0.35):
"""
Plots an emoji on a figure.
Based on:
https://www.geeksforgeeks.org/emojis-as-markers-in-matplotlib/
"""
# reading the image
image = plt.imread(emoji_path)
# OffsetBox
image_box = OffsetImage(image, zoom=zoom)
# Drawing the image
ab = AnnotationBbox(image_box, (x, y), frameon=False)
ax.add_artist(ab)
return
def fig_from_list(trajectory_list, pig_position=[]):
"""
Plots the trajectory of a projectile, given computed trajectories.
It optionally plots the pig position.
"""
fig = plt.figure(figsize=(16,12))
ax = plt.subplot(111)
legend = []
xmax_list = []
# Linestyles
linestyles = ['-', '--', '-.', ':']
# Iterate and plot
for i, trajectory in enumerate(trajectory_list):
plt.plot(trajectory["x"], trajectory["y"],
color = trajectory["color"],
linestyle=linestyles[i%len(linestyles)])
legend.append(trajectory["legend"])
xmax_list.append(np.max(trajectory["x"]))
plt.xlabel('x - horizonal distance in meters', fontsize=20)
plt.ylabel('y - vertical distance in meters', fontsize=20)
# Adding the pig and birds, if needed
if len(pig_position) > 0:
plot_emoji("apps/images/pig.png", ax, pig_position[0], pig_position[1])
xmax_list.append(pig_position[0])
for trajectory in trajectory_list:
plot_emoji("apps/images/bird.png", ax, trajectory["x"][-1], trajectory["y"][-1])
# legend, only if any trajectory
plt.legend(legend, fontsize=20, loc='upper center')
# xmax_list and ymax calculations
if len(xmax_list) > 0:
xmax = max(xmax_list)
plt.xlim(-xmax*0.05, xmax*1.05)
plt.ylim(-xmax*0.05, xmax*1.05) # Same limits for x and y
return fig
def check_solution(pig_position, trajectory_list):
"""
Checks if the pig is in the trajectory of the projectile.
"""
x_tol, y_tol = 1.0, 1.0
# Iterate and check
for trajectory in trajectory_list:
x = trajectory["x"][-1]
y = trajectory["y"][-1]
if abs(pig_position[0] - x) < x_tol and abs(pig_position[1] - y) < y_tol:
return True
return False