I try to understand this code and I actually understood the whole thing except these 2 line:
f_grav = gravity * sun.mass * earth.mass * (sun.pos - earth.pos).norm() / (sun.pos - earth.pos).mag2
earth.vel = earth.vel + (f_grav/earth.mass) * dt
Why couldn't it just be: f_grav = gravity * sun.mass * earth.mass / (sun.pos-earth.pos)**2
I also dont get the role of .norm() and .mag2
Here is the whole code snippet of the program(GlowScript):
sunRadius = 10 * realSunRadius # the size for our solar system
earthRadius = sunRadius * 0.25 # note: real value would be sunRadius * 0.01, a good choice for sim is * 0.25
astronomicalUnit = 212.7 * realSunRadius # the distance from Sun to Earth - the Sun is about 100 Sun diameters away
gravity = 6.6e-11 # sets the strength of the gravitational constant to 6.6x10-11 Newton x meters squared per kilograms squared
# create the Sun object
sun = sphere( radius = sunRadius, opacity = 0.7, emissive = True, texture = "http://i.imgur.com/yoEzbtg.jpg" )
sun.mass = 2e30 # mass of the Sun in kilograms is 2,000,000,000,000,000,000,000,000,000,000 kg
sun.pos = vec(0,0,0)
sun.vel = vec(0,0,0)
# place a few sources of light at the same position as the Sun to illuminate the Earth and Moon objects
sunlight = local_light( pos = vec(0,0,0), color=color.white )
more_sunlight = local_light( pos = vec(0,0,0), color=color.white ) # I found adding two lights was about right
# create the Earth object
earth = sphere ( radius = earthRadius, texture = "http://i.imgur.com/rhFu01b.jpg",make_trail=True)
earth.mass = 6e24 # mass of Earth in kilograms
earth.pos = vec(astronomicalUnit, 0, 0)
earth.vel = vec(0,0,-30000) # the Earth is moving around 30000 m/s
dt = 10000
# below is the main loop of the program - everything above is "setup" and now we are in the main "loop" where all the action occurs
while (True): # this will make it loop forever
rate(100) # this limits the animation rate so that it won't depend on computer/browser processor speed
# calculate the force of gravity on each object
f_grav = gravity * sun.mass * earth.mass * (sun.pos - earth.pos).norm() / (sun.pos - earth.pos).mag2
earth.vel = earth.vel + (f_grav/earth.mass) * dt
# update the position of the Earth and Moon by using simple circle trigonometry
earth.pos = earth.pos + earth.vel * dt
(sun.pos-earth.pos) is a vector. I don't think you can do (sun.pos-earth.pos)**2 because you can't square a vector. Unless you're trying to do a dot product of the vector with itself? But the result of a dot product is a scalar, so f_grav would be a scalar. Forces are vectors, so it doesn't make sense to use a dot product there.
In comparison, f_grav = gravity * sun.mass * earth.mass * (sun.pos - earth.pos).norm() / (sun.pos - earth.pos).mag2 makes sense because you're multiplying (sun.pos - earth.pos).norm(), a vector, by three scalars, and dividing by one scalar. So the result is a vector as desired.
.norm() returns a unit vector so that the result is a vector not a scalar. This is the vector form of Newtonian gravity. (See Wikipedia)
.mag2 does the same thing as what is expected from **2, however in general, powers of vectors are not defined, so it wouldn't make sense to define the exponentiation operator on the vector class.
Related
I'm trying to reproduce the model described in this paper https://hal.archives-ouvertes.fr/file/index/docid/683477/filename/clarinette-logique-8.pdf.
Here is a method that returns the transfer matrix for a cylinder of radius a and length L.
# density of air
rho = 1.2250
# viscosity of air
eta = 18.5
# transfer matrix for a cylinder
def Tcyl(a, L):
rv = a * math.sqrt(rho*omega/eta)
Z0 = (rho * constants.c) / (constants.pi * a**2)
Zc = Z0 * complex(1 + 0.369/rv, -(0.369/rv + 1.149/rv**2))
gamma = k * complex(1.045/rv + 1.080/rv**2, 1 + 1.045/rv)
return
np.matrix([[cmath.cosh(gamma*L),Zc*cmath.sinh(gamma*L)],
[(1.0/Zc)*cmath.sinh(gamma*L),cmath.cosh(gamma*L)]], dtype=complex)
The input impedance is calculated for different frequencies as follow.
for f in range(1,4000):
# angular frequency
omega = 2*constants.pi*f
# wave number
k = omega/constants.c
# transfer matrix for a cylinder of radius 7.5mm and length 100mm
T = Tcyl(7.5, 100.0)
# radiation impedance
Zr = complex(0,0)
# [P,U] vector (pression and velocity)
T = np.dot(T,np.matrix([[Zr],[complex(1,0)]], dtype=complex))
# input impedance (Z = P/U)
Z = T.item(0)/T.item(1)
The playing frequency satisfy the equation Im[Z]=0. When plotting the imaginary part of Z I get the following figure : wrong impedance
This is clearly wrong as the expected output should be something like this : correct impedance
What am I doing wrong?
Thank you.
You have
Z0 = (rho * constants.c) / (constants.pi * a**2)
The impedance of a clarinet depends on the speed of SOUND, not the speed of LIGHT. Replace constants.c with 343 and your results will be closer. I'm still not sure it's quite right, but closer.
As a clarinetist, I try to make people think my fingers move as fast as light, but it ain't so.
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
this is my first post on here.
So I am trying to make a model solar system using visual python. I am defining each planet as a sphere, with radius, distance from sun, mass, and momentum variables. Then each planet (or body) is put into a list structure. As you can see currently I have a list with [earth, moon, mars] the sun is excluded for reason i will explain shortly.
So my problem comes when I'm trying to calculate the force caused by each body on each other body. What I am doing here is, for every ith value in the bodies list, the force between that and the nth body is calculated, the force on the ith body in the list bodies is the sum of the force between the ith body and each nth body from 0 to the end of the list. (i.e. the sum of all the forces due to every other body in the list)
This works correctly for the moon and mars (2nd and 3rd items in the list) but not for the earth. The output for the code below is,
<3.57799e+022, 0, 0>
<4.3606e+020, 0, 0>
<1.64681e+021, 0, 0>
<-1.#IND, -1.#IND, -1.#IND> - this is the total force on earth.
<0, 2.07621e+027, 0>
<0, 9.83372e+027, 0>
from visual import *
AU = 149.6e9
MU = 384.4e6 # moon - earth orbital - radius
MarU = 227.92e9
G =6.673e-11
sun_mass =2e30
sun_radius =6.96e8
earth_mass =6e24
earth_radius =6.37e6
moon_mass =7.35e22
moon_radius =1.74e6
mars_mass = 6.41e23
mars_radius = 3390000
sun = sphere ( pos =(0 , 0 ,0) , velocity = vector (0 ,0 ,0) ,mass = sun_mass , radius =0.1* AU , color = color . yellow )
earth = sphere ( pos =( AU , 0 ,0) ,mass = earth_mass , radius =63170000, color = color . cyan ,make_trail=True )# create a list of gravitating objects
moon = sphere ( pos =( AU+MU , 0 ,0) ,mass = moon_mass , radius =17380000 , color = color . white, make_trail=True )
mars = sphere ( pos =( MarU , 0 ,0) ,mass = mars_mass , radius = mars_radius , color = color . red, make_trail=True )
#initialise values:
we = 1.9578877e-7
wm = sqrt(G*earth.mass/3.38e8**3)
wma = 9.617e-5
dt = 3*60
earth.mom = vector(0,1.5e11*earth.mass*we,0)
mars.mom = vector(0, 9.833720638948e+27,0)
moon.mom = moon.mass*(earth.mom/earth.mass+vector(0,-3.48e8*wm,0))
bodies = [earth, moon, mars]
*N = 0
initialdiff = 0
for i in bodies:
initialdiff = i.pos - sun.pos
TotalForce = (G * i. mass * sun. mass * norm ( initialdiff )/ initialdiff . mag2)
print TotalForce
while N < len(bodies):
if N!=i:
diff = i.pos - bodies[N].pos
Force = (G * i. mass * bodies[N]. mass * norm ( diff )/ diff . mag2)
TotalForce = TotalForce + Force
i.mom = i.mom+TotalForce*dt
N = N+1
else:
N = N+1
print earth.mom
print moon.mom
print mars.mom*
Thanks for any help you can give.
'''Abel Tilahun HW 3 '''
# 02/03 / 2015
# make the necessary imports , visual import gives visual output, cos, sin and pi allows calculation of the positions
# in real time. The numpy arange import returns evenly spaced values within a given interval (angles)
from visual import *
from math import cos,sin,pi
from numpy import arange
# i used 'a' to magnify the sizes of the planet for better visualization
a=600
# the following line defines a sphere for the sun centered at the origin(0,0,0) all the other planets are positioned at a radial distance from this center.
Sun=sphere(pos=(0,0,0),radius=6955500*(a/100),color=color.yellow)
#the next 5 commands code the planets with their center being positioned at a distance of the radii of their orbit. Their radii are multiplied by a factor of 'a' to magnify them
Mercury=sphere(pos=vector(579e5,0,0),radius=2440*(a),color=color.red)
Venus=sphere(pos=vector(1082e5,0,0),radius=6052*a,color=color.orange)
Earth=sphere(pos=vector(1496e5,0,0),radius=6371*a,color=color.green)
Mars=sphere(pos=vector(2279e5,0,0),radius=3386*a,color=color.white)
Jupiter=sphere(pos=vector(7785e5,0,0),radius=69173*(a),color=color.cyan)
Saturn=sphere(pos=[14334e5,0,0],radius=57316*(a),color=color.magenta)
# the for loop calculates position of the planets by changing
# the arange function increases the angle from 0 to pi with a small increment of 0.025 each time
for theta in arange(0,100*pi,0.025):
rate(30)
x = 579e5*cos(theta)
y = 579e5*sin(theta)
Mercury.pos = [x,y,0]
x = 1082e5*cos(theta)
y = 1082e5*sin(theta)
Venus.pos = [x,y,0]
x = 1496e5*cos(theta)
y = 1496e5*sin(theta)
Earth.pos = [x,y,0]
x = 2279e5*cos(theta)
y = 2279e5*sin(theta)
Mars.pos = [x,y,0]
x = 7785e5*cos(theta)
y = 7785e5*sin(theta)
Jupiter.pos = [x,y,0]
x = 14334e5*cos(theta)
y = 14334e5*sin(theta)
Saturn.pos = [x,y,0]