def cohesion(self,fish): if len(fish) < 1: return # calculate the average distances from the other boids com = Vector() count = 0 for boid in fish: if boid.pos == self.pos: continue elif (boid.pos - self.pos).length()<self.per: com += (self.pos - boid.pos) count+=1 if count>0: com = com.divide(count) return -com.normalize() else: return Vector()
class Fsh: def __init__(self,pos,bounds,imgr,imgl): self.bounds = bounds self.max_vel = 75 self.imgr = imgr self.imgl = imgl self.size = 25 self.per = self.size*3 self.pos = pos angle = random.random()*math.pi*2 self.vel = Vector(math.cos(angle),math.sin(angle)) * 20 def draw(self,canvas): #canvas.draw_circle(self.pos.get_p(),4,1,"red","red") a = self.vel.angle(Vector(0,1)) if self.vel.x > 0: a *= -1 img = self.imgr a += math.pi/2 else: a -= math.pi/2 img = self.imgl img.pos = self.pos img.draw(canvas,rotation=a) #canvas.draw_line(self.pos.get_p(),(self.pos+self.vel).get_p(),2,"blue") #canvas.draw_circle(self.pos.get_p(),self.size,1,"black") def allign(self,fish): if len(fish) < 1: return # calculate the average velocities of the other boids avg = Vector() count = 0 for boid in fish: if(boid.pos - self.pos).length()<self.per: count+=1 avg += boid.vel if count>0: avg = avg.divide(count) # set our velocity towards the others return (avg).normalize() else: return Vector() def cohesion(self,fish): if len(fish) < 1: return # calculate the average distances from the other boids com = Vector() count = 0 for boid in fish: if boid.pos == self.pos: continue elif (boid.pos - self.pos).length()<self.per: com += (self.pos - boid.pos) count+=1 if count>0: com = com.divide(count) return -com.normalize() else: return Vector() def seperation(self,fish, minDistance): if len(fish) < 1: return Vector() distance = 0 numClose = 0 distsum = Vector() for boid in fish: distance = (self.pos-boid.pos).length() if distance < minDistance and distance != 0: numClose += 1 distsum += (boid.pos-self.pos).divide(distance**2) if numClose == 0: return Vector() return (-distsum.divide(numClose)).normalize() def update(self,delta,fish): self.vel = self.vel.add(self.allign(fish).multiply(self.max_vel/50)) self.vel = self.vel.add(self.cohesion(fish).multiply(self.max_vel/50)) self.vel = self.vel.add(self.seperation(fish,self.per*3/5).multiply(self.max_vel/30)) self.vel = self.vel.normalize().multiply(self.max_vel) self.vel.rotate((random.random()*2-1)*delta*20) self.pos = self.pos.add(self.vel * delta) self.pos = self.bounds.correct(self)
def run_simulation(body, rocket, target_orbit): # Time t = 0.0 # Our step size dt = 0.1 time_list = [] altitude_list = [] phi_list = [] drag_list = [] thrust_list = [] velocity_list = [] mass_list = [] start = time.time() rocket.throttle = 1.0 # Let's run our simulation for i in range(75000): # gravity depends on altitude! A_gravity = body.accelleration(rocket.position) # Valid up to 2500,000 meters P0, density = body.air_pressure_and_density(rocket.position) # AUTO PILOT # really crude pitch control. Once above target_orbit. start pushing along the surface of the earth # First find orientation of the rocket. We assume this is always # along the surface of the earth, which is the tangent of the # position vector. orientation = Vector([-rocket.position[1], rocket.position[0],0]) # In order to rotate the force vector 'upwards' a certain degree # we need to find the rotation axis. This is the vector orthogonal # to the position and the orientation. rotation_axis = rocket.position.cross( orientation ).normalize() # High tech auto pilot # Straight up first, then abruptly point force vector along the # surface of the earth at 200km up. Then when orbital velocity is # acchieved power down. delta = 1.0 if rocket.position.magnitude > body.radius + 1e3: delta = 0.5 if rocket.position.magnitude > body.radius + 200e3: delta = 0.1 # should really test for velocity parallel with Earth. if rocket.velocity.magnitude > 8672.0: rocket.throttle = 0.0 # Negative rotation means point the force vector out from earth # along the surface. orientation.rotate( - delta * math.pi/2.0, rotation_axis ) rocket.set_orientation(orientation.normalize()) # Force from rocket thurst depends on altitude F_rocket = rocket.thrust(P0) # Force from drag due to atmosphere F_drag = rocket.drag(density) # Force from Gravity F_gravity = A_gravity * rocket.mass() # Make sure our airframe can handle! F_rocket_mag = F_rocket.magnitude F_drag_mag = F_drag.magnitude F_gravity_mag = F_gravity.magnitude force_mag_list = [F_rocket_mag, F_drag_mag, F_gravity_mag] # if the drag magnitude becomes too big, the airframe will break. maxForce = sum( force_mag_list ) if ( maxForce > rocket.max_forces ): print("R.U.D. Rapid Unscheduled Dissambly, too much forces, your rocket broke up in mid flight, iteration {}".format(i)) print("velocity={} altitude={}, max_force={}, force_list={} delta={}".format(rocket.velocity, rocket.position.magnitude, maxForce, force_mag_list, delta)) break # Sum Forces: Weight, Rocket Thrust and Drag in 3 dimensions. Fs = F_rocket + F_drag + F_gravity dv = Fs * (dt / rocket.mass()) # Time step! rocket.velocity += dv rocket.position += rocket.velocity * dt # did we make it back to terra firma? # hope we are going slow. if rocket.position.magnitude < body.radius - 1: print("Current Forces = {}".format(force_mag_list)) if rocket.velocity.magnitude > 5: print("R.U.D. Rapid Unscheduled Dissambly, welcome home!") else: print("Level: Musk, Mars is next") break # debug print if i%5000==0: print("velocity={} pos={}, drag={} delta={}".format(rocket.velocity, rocket.position.magnitude, F_drag, delta)) # step the rocket time ahead, this burns the fuel and potentially does stage sep. rocket.time_step(dt, t) # keep a list of maxForce and position so we can plot. time_list.append(t) drag_list.append( ( F_drag_mag ) / 1000.0 ) thrust_list.append( (F_rocket_mag ) / 1000.0 ) altitude_list.append((rocket.position.magnitude - body.radius ) / 1000.0) phi_list.append( 180.0 * rocket.position.phi / math.pi ) velocity_list.append( rocket.velocity.magnitude ) mass_list.append(rocket.mass()) # next time step! t = t + dt print("Simulation ran for {} seconds".format(time.time()-start)) return time_list, altitude_list, drag_list, velocity_list, phi_list, thrust_list, mass_list