I'm new to Python and I try to plot a trajectory of a projectile with given variables (initial velocity, g) with given displacement in x-axis, and calculate the value of the initial angle (theta). However, I'm not sure where the problems lie in. My best guess is the "measurement uncertainty" of the trigonometry functions. How do I make this graph more accurate? I have also thought of changing the "measurement units" but that doesn't seem to do much.
This image shows that note 'x' was declared as 1.5332(m) but what I got was up to ~2.3(m)
My code:
import numpy as np
import pylab as pyl
# Initialize variables
v, g = 4.8, 9.8
x2 = 1.5332 # Input displacement
theta = 0.5 * np.arcsin((g * x2**2) / (v**2)) # Angle from displacement 'x'
t = np.linspace(0, 5, num=10**4) # Set 'time' as continous parameter
x1 = []
y1 = []
# get position at every point in time
for k in t:
x = ((v * k) * np.cos(theta))
y = ((v * k) * np.sin(theta)) - ((0.5 * g) * (k**2))
x1.append(x)
y1.append(y)
pyl.plot(x1, y1) # Plot 'x' and 'y'
pyl.grid()
pyl.ylim(0, 1)
pyl.xlim(0, 3)
pyl.show() # Display graphically
There's an error in your angle calculation:
theta = 0.5 * np.arcsin((g * x2) / (v**2)) # Angle from displacement 'x'
In this program I've been working on with Python the goal is to take user inputs on a given initial velocity, angle, and how far away a structure is/how tall it is we're aiming for. I have been able to calculate how long it takes for something to reach a target, but I'm not sure why the final velocity (how fast it is going when it reaches the target) is coming up wrong.
# User inputs
velocity = float(input('Give me a velocity to fire at (in m/s): '))
angle = float(input('Give me an angle to fire at: '))
distance = float(input('Give me how far away you are from the
structure: '))
height = float(input('Give me the height of the structure (in meters):
'))
slingshot = 5 #Height of slingshot in meters
gravity = 9.8 #Earth gravity
# Converting angles to radians
angleRad = math.radians(angle)
# Computing our x and y coordinate
x = math.cos(angleRad)
y = math.sin(angleRad)
# Calculations
time = distance/(velocity * x)
vx = x
vy = y + (-9.8 * time)
finalVelocity = math.sqrt((vx ** 2) + (vy ** 2))
# Output of program
print('It takes your bird' , time , 'seconds to reach the structure')
print('Your velocity at the target distance is' , finalVelocity ,
'meters per second.')
Here is a sample input and what the expected output should be:
Input Velocity: 20
Input Angle: 40
Input Distance: 25
Input Height of Structure: 15
Expected Output:
Time to reach structure: 1.63176 s
Final velocity: 15.6384 s
My Program's Output:
Time to reach structure: 1.63176
Final velocity: 15.36755
At first glance it would appear my program is very close, so I suspected a rounding error, but it is mere coincidence with the chosen numbers that they're close.
You miscalculated the horizontal and vertical components of the final velocity. You only used the cosine and sine of the angle, rather than the (magnitude of the) initial velocity times the cosine and sine, respectively. If you modify the following two lines of code, you will obtain the result you were looking for given the sample input you provided:
vx = velocity * x
vy = velocity * y - 9.8 * time
I rewrote your original code a bit and also computed the final height to check whether the structure was hit or not, so feel free to use it if needed:
import math
# User inputs
# v0 = float(input('Give me a velocity to fire at (in m/s): '))
# angle = float(input('Give me an angle to fire at: '))
# distance = float(input('Give me how far away you are from the structure: '))
# height_structure = float(input('Give me the height of the structure (in meters):'))
# Test inputs
v0 = 20
angle = 40
distance = 25
height_structure = 15
# Constants
height_slingshot = 5 # Height of slingshot in meters
g = 9.8 # Earth gravity
# Converting angle to radians
angleRad = math.radians(angle)
# Computing initial velocity components
vx0 = v0 * math.cos(angleRad)
vy0 = v0 * math.sin(angleRad)
# Computing time to travel horizontal distance
t_x = distance / vx0
# Computing final vertical velocity component
vy_final = vy0 - g * t_x
# Computing magnitude of final velocity
v_final = math.sqrt((vx0 ** 2) + (vy_final ** 2))
# Note: Horizontal component is constant
# Computing final height
y_final = height_slingshot + vy0 * t_x - g / 2 * t_x ** 2
# Verify if t_x was computed correctly
# t_y1 = (vy0 + math.sqrt(vy0 ** 2 - 2 * g * y_final)) / g
# t_y2 = (vy0 - math.sqrt(vy0 ** 2 - 2 * g * y_final)) / g
# Output of program
print('It takes your bird', t_x, 'seconds to reach the structure.')
print('Your velocity at the target distance is', v_final,
'meters per second.')
print('\nFinal height: ', y_final)
print('Structure height:', height_structure)
if 0. <= y_final <= height_structure:
print('\nYou hit the structure!')
elif y_final < 0:
print('\nYou missed. Not far enough!')
else:
print('\nYou missed. Too far!')
I am new to Python, and currently having a rough time with turtle graphics. This is what I am trying to solve
On Turtellini (the planet where Python turtles live) the
transportation system propels turtles with a giant slingshot. A
particular turtle's original location (x0, y0) is (-180, -100). He is
then shot upward at an initial vertical velocity (vy) of 88 units per
second and a horizontal velocity (vx) of 20 units per second to the
right. He travels for 16 seconds. The acceleration due to gravity (g)
is 11 units per second squared. The the location of the turtle at a
given second (t) is calculated as follows: x = x0 + vx * t and y = y0
+ vy * t - g/2 * t2 . This program is to show how a turtle travels over this period of time.
The output should be like this:
Here is what I should do;
set up the constants (vertical velocity, horizontal velocity,
gravity) and variables (x and y coordinates) set up the turtle by
giving him a proper shape, putting his tail up, moving him to the
initial position, putting his tail down make a loop that repeats for
seconds 1 through 16 inclusive. in each iteration of the loop display
the the values of the x and y variables (in the shell window), move
the turtle to those coordinates, have the turtle stamp his shape,
calculate the new values for the x and y variables after the loop
terminates, move the turtle to the last calculated coordinates,
change his color, and stamp his shape, then wait for a mouse click
My code so far:
import turtle
def main():
wn = turtle.Screen()
turtellini = turtle.Turtle()
t = int(input("Blab blab blab: "))
x0 = -180
y0 = -100
vx = 20
vy = 88
g = 11
x = (float(x0 + vx * t))
y = (float(y0 + vy * t - g / 2 * t**2))
turtellini.color("black")
turtellini.shape("turtle")
turtellini.up()
turtellini.goto(-180,-100)
turtellini.down()
for i in range(1,16,1):
turtellini.stamp()
turtellini.forward(i)
turtellini.right(i)
print(x)
print(y)
if __name__ == "__main__":
main()
I know I am doing bad; but can anyone help me to solve this problem?
You seem to have most of the parts and pieces. The biggest issue I see is you didn't put your x,y calculation in the loop. The loop iteration variable i is really t in your motion equations. Each time you calculate a new x,y you simply move the turtle to that position:
import turtle
from math import pi, atan
x0, y0 = -180, -100 # initial location
vx, vy = 20.0, 88.0 # initial velocity in units per second
travel_time = 16 # seconds
g = 11.0 # acceleration due to gravity in units per second squared
turtellini = turtle.Turtle(shape='turtle', visible=False)
turtellini.penup()
turtellini.radians() # to make turtle compatible with math.atan()
turtellini.setheading(pi / 2) # straight up
turtellini.goto(x0, y0)
turtellini.pendown()
turtellini.showturtle()
turtellini.stamp()
for t in range(1, travel_time + 1):
x = x0 + vx * t
y = y0 + vy * t - g / 2 * t**2
turtellini.goto(x, y)
print(x, y)
angle = atan((vy * t - g * t**2) / (vx * t)) # a guess!
turtellini.setheading(angle)
turtellini.stamp()
turtle.exitonclick()
Unlike the gold standard image, I assumed the turtle was aerodynamic like a bullet and travelled head first through the flight. I don't know, and couldn't quickly find, the formula for the flight angle of a projectile so I guessed from the existing formulas:
I would like to make some kind of solar system in pygame. I've managed to do a fixed one but I thought it would be more interesting to do one with planets moving around the sun and moons around planets etc. Is there a way I could do that (using pygame if possible)?
What I would like is :
Sun = pygame.draw.circle(...)
planet1 = pygame.draw.circle(...)
etc.
a = [planet1, planet2, ...]
for p in a:
move p[2] to pos(x, y)
That is what I think would work but I'm not sure how to do it. Also, I've thought about deleting the ancient planet and drawing a new one right next to it, but problem is I'm using random features (like colours, distance to the sun, number of planets in the system etc.) and it would have to keep these same features. Any ideas?
Thanks in advance!
You can implement gravity with Newton's Law of Universal Gravitation and Newton's Second Law to get the accelerations of the planets. Give each planet an initial position, velocity and mass. Acceleration is change in velocity a = v * dt, velocity is change in position v = r * dt, so we can integrate to find velocity and position.
Universal gravitation: F = G * m1 * m2 / r ** 2 where F is the magnitude of the force on the object, G is the gravitational constant, m1 and m2 are the masses of the objects and r is the distance between the two objects.
Newton's Second Law: F = m1 * a where a is the acceleration.
dt = 0.01 # size of time step
G = 100 # gravitational constant
def calcGravity(sun, planet):
'Returns acceleration of planet with respect to the sun'
diff_x = sun.x - planet.x
diff_y = sun.y - planet.y
acceleration = G * sun.mass / (diff_x ** 2 + diff_y ** 2)
accel_x = acceleration * diff_x / (diff_x ** 2 + diff_y ** 2)
accel_y = acceleration * diff_y / (diff_x ** 2 + diff_y ** 2)
return accel_x, accel_y
while True:
# update position based on velocity
planet.x += planet.vel_x * dt
planet.y += planet.vel_y * dt
# update velocity based on acceleration
accel_x, accel_y = calcGravity(sun, planet)
planet.vel_x += accel_x * dt
planet.vel_y += accel_y * dt
This can produce circular and elliptical orbits. Creating an orbiting moon requires a very small timestep (dt) for the numeric integration.
Note: this approach is subtly inaccurate due to the limits of numeric integration.
Sample implementation in pygame here, including three planets revolving around a sun, a moon, and a basic orbital transfer.
https://github.com/c2huc2hu/orbital_mechanics
Coordinates of a planet rotated about the Sun through some angle with respect to the X-axis are , where r is the distance to the Sun, theta is that angle, and (a, b) are the coordinates of the sun. Draw your circle centered at (x, y).
EDIT:
General elliptical orbit:
Where
r0 is the radius of a circular orbit with the same angular momentum, and e is the "eccentricity" of the ellipse
I am trying to simulate how the oscillating electric field of an intense laser will push around an electron that is near the Coulomb potential of a +1 ion. The laser field is
E = Eo sin(wt), in the y direction.
and the Coulomb potential is
F = ke q1*q2/r^2, in the r direction.
The strong electric field causes the electron to tunnel ionize, so the initial condition of the electron is to be displaced from the atom in the y-direction. Then, the electron is pushed back and forth by the laser field and has a chance to interact with the Coulomb potential. I want to simulate how the Coulomb potential affects the flight of the electron. The simulations need to be in three dimensions, because I eventually want to include more complex laser fields that push the electron in the x and y directions and the electron can start with momentum in the z direction.
At first, I thought that this would be easy. Below is the code that I used to step through time in very small steps (1e-18 sec). When the electron is not near the ion, this works fine. However, for electrons that pass close to the ion, the results depend strongly on the time-step used in the simulations. If I make the time-step smaller, the calculations take a very long time.
So, I think in this case I am supposed to use an adaptive timestep. Also, from what I have read, the Runge-Kutta methods are supposed to be superior to the simple approach I am using. However, I don't think that scipy.odeint applies to three-dimensions. Any ideas on how to improve the accuracy and speed of these simulations?
Here is the figure showing how the time-step has a huge impact on the results (a bad thing):
And here is my code:
import numpy as np
import matplotlib.pyplot as plt
q = 1.602e-19 #Coulombs Charge of electron
h_bar = 1.054e-34 #J*s Plank's Constant div by 2Pi
c = 3.0e8 #m/s Speed of light
eo = 8.8541e-12 #C^2/(Nm^2) Permittivity of vacuum
me = 9.109e-31 #kg Mass of electron
ke = 8.985551e9 #N m^2 C-2 Coulomb's constant
def fly_trajectory(wavelength,intensity,tb=0,pulseFWHM=40.e-15,
final_time=100e-15,time_step=.001e-15,Ip=15.13,v0=(2e4,0,0)):
#Intensity is in w/cm2. Ip is in eV. Otherwise it's SI units throughout.
#The electric field of the later is in the y-direction
Ip = 15.13 * q #Calculate the ionization potential of the atom in Joules
Eo = np.sqrt(2*intensity*10**4/(c*8.85e-12)) # Electric field in V/m
w = c/wavelength * 2. * np.pi #Angular frequency of the laser
times = np.arange(tb,final_time,time_step)
Ey = Eo*np.sin(w*times) * np.exp(-times**2/(2*(pulseFWHM / 2.35482)**2))
Eb = Ey[0] #E-field at time of birth (time of tunneling)
if Eb == 0: return 0,0 #No field --> no electrons
tunnel_position = -Ip / (Eb*q)
x,y,z = 0,tunnel_position,0
vx,vy,vz = v0
y_list = np.zeros(len(times)) #store the y-values for later
for index in range(0,len(times)):
r = np.sqrt(x**2+y**2+z**2)
rx = x/r; ry = y/r; rz=z/r
Fcy = -q**2 * ke/(r**2) * ry
ay = Ey[index]*(-q)/me + Fcy/me #only y includes the laser
vy = vy + ay*time_step
y = y + vy * time_step
Fcx = -q**2 * ke/(r**2) * rx
ax = (-q)/me + Fcx/me
vx = vx + ax*time_step
x = x + vx * time_step
Fcz = -q**2 * ke/(r**2) * rz
az = (-q)/me + Fcz/me
vz = vz + az*time_step
z = z + vz * time_step
y_list[index] = y
return times,y_list
for tb in np.linspace(0.25*2.66e-15,0.5*2.66e-15,5):
print tb
times,ys = fly_trajectory(800e-9,2e14,tb=tb,time_step=.01e-15)
plt.plot(times,ys,color='r')
times,ys = fly_trajectory(800e-9,2e14,tb=tb,time_step=.001e-15)
plt.plot(times,ys,color='b')
#plot legend and labels:
plt.plot(0,0,color='r',label='10e-18 sec step')
plt.plot(0,0,color='b',label='1e-18 sec step')
plt.xlim(0,10e-15); plt.ylim(-1e-8,1e-8)
leg = plt.legend(); leg.draw_frame(False)
plt.xlabel('Time (sec)')
plt.ylabel('Y-distance (meters)')
plt.show()
As Warren Weckesser suggested, I can simply follow the Scipy cookbook for the coupled mass-spring system. First, I need to write my "right side" equations as:
x' = vx
y' = vy
z' = vz
vx' = Ac*x/r
vy' = Ac*y/r + q*E/m
vz' = Ac*z/r
where Ac=keq^2/(mr^2) is the magnitude of the acceleration due to the Coulomb potential and E is the time-dependent electric field of the laser. Then, I can use scipy.integrate.odeint to find the solutions. This is faster and more reliable than the method that I was using previously.
Here is what the electron trajectories look like with odeint. Now none of them fly away crazily:
And here is the code:
import numpy as np
import matplotlib.pyplot as plt
import scipy.integrate
q = 1.602e-19 #Coulombs Charge of electron
c = 3.0e8 #m/s Speed of light
eo = 8.8541e-12 #C^2/(Nm^2) Permittivity of vacuum
me = 9.109e-31 #kg Mass of electron
ke = 8.985551e9 #N m^2 C-2 Coulomb's constant
def tunnel_position(tb,intensity,wavelength,pulseFWHM,Ip):
Ip = 15.13 * q
Eb = E_laser(tb,intensity,wavelength,pulseFWHM)
return -Ip / (Eb*q)
def E_laser(t,intensity,wavelength,pulseFWHM):
w = c/wavelength * 2. * np.pi #Angular frequency of the laser
Eo = np.sqrt(2*intensity*10**4/(c*8.85e-12)) # Electric field in V/m
return Eo*np.sin(w*t) * np.exp(-t**2/(2*(pulseFWHM / 2.35482)**2))
def vectorfield(variables,t,params):
x,y,z,vx,vy,vz = variables
intensity,wavelength,pulseFWHM,tb = params
r = np.sqrt(x**2+y**2+z**2)
Ac = -ke*q**2/(r**2*me)
return [vx,vy,vz,
Ac*x/r,
Ac*y/r + q/me * E_laser((t-tb),intensity,wavelength,pulseFWHM),
Ac*z/r]
Ip = 15.13 # Ionization potential of Argon eV
intensity = 2e14
wavelength = 800e-9
pulseFWHM = 40e-15
period = wavelength/c
t = np.linspace(0,20*period,10000)
birth_times = np.linspace(0.01*period,0.999*period,50)
max_field = np.max(np.abs(E_laser(birth_times,intensity,wavelength,pulseFWHM)))
for tb in birth_times:
x0 = 0
y0 = tunnel_position(tb,intensity,wavelength,pulseFWHM,Ip)
z0 = 0
vx0 = 2e4
vy0 = 0
vz0 = 0
p = [intensity,wavelength,pulseFWHM,tb]
w0 = [x0,y0,z0,vx0,vy0,vz0]
solution,info = scipy.integrate.odeint(vectorfield,w0,t, args=(p,),full_output=True)
print 'Tb: %.2f fs - smallest step : %.05f attosec'%((tb*1e15),np.min(info['hu'])*1e18)
y = solution[:,1]
importance = (np.abs(E_laser(tb,intensity,wavelength,pulseFWHM))/max_field)
plt.plot(t,y,alpha=importance*0.8,lw=1)
plt.xlabel('Time (sec)')
plt.ylabel('Y-distance (meters)')
plt.show()