def forceVector(self, flightPitch, AoA, v, altitude = 0, planet = planet.kerbin, includeGravity = False): """ Returns (x, y) forces due to the airfoil. Includes drag, lift, and the parasitic drag due to lift. If includeGravity is set, also includes apparent gravity (taking into account centrifugal effects). flightPitch: angle of velocity vector relative to the surface (degrees) AoA: angle of the airfoil relative to the velocity vector (degrees) """ lift = self.liftForce(AoA, v, altitude, planet) drag = self.dragForce(AoA, v, altitude, planet) liftAngle = math.radians(flightPitch + 90) dragAngle = math.radians(flightPitch + 180) (liftX, liftY) = (lift * math.cos(liftAngle), lift * math.sin(liftAngle)) (dragX, dragY) = (drag * math.cos(dragAngle), drag * math.sin(dragAngle)) if not includeGravity: return (liftX + dragX, liftY + dragY) # now compute apparent gravity vOrbital = planet.orbitalVelocity(altitude) vSrfHorizontal = math.cos(math.radians(flightPitch)) * v vOrbHorizontal = vSrfHorizontal + planet.siderealSpeed(altitude) gravityAccel = planet.gravity(altitude) centrifugeAccel = vOrbHorizontal * vOrbHorizontal / (vOrbital * vOrbital) apparentGravityForce = (centrifugeAccel - gravityAccel) * self.mass return (liftX + dragX, liftY + dragY + apparentGravityForce)
def zeroThrustForces(self, flightPitchDegrees, AoADegrees, v, altitude, planet): """ Return the forces other than thrust that this part produces. Returns a tuple (drag, lift, apparentGravity) with quantities in kN. Lift and drag are vectors; gravity is a number (just the y coordinate, positive means up). """ Cd = self._staticCd Clift = 0 if isinstance(self._parttype, lift.wing): Cd = self._parttype.dragCoeff(self._AoA + AoADegrees) Clift = self._parttype.liftCoeff(self._AoA + AoADegrees) elif isinstance(self._parttype, jets.intake): Cd = self._parttype.dragCoeff(self._AoA + AoADegrees) elif isinstance(self._parttype, jets.jetengine): Cd = 0.2 elif isinstance(self._parttype, engine.engine): Cd = 0.2 dragMagnitude = planet.dragForce(altitude, v, self.mass(), Cd) liftMagnitude = v * planet.pressure(altitude) * Clift flightPitchRad = math.radians(flightPitchDegrees) cosPitch = math.cos(flightPitchRad) sinPitch = math.sin(flightPitchRad) horizontalSpeedSrf = v * cosPitch horizontalSpeedOrb = horizontalSpeedSrf + planet.siderealSpeed(altitude) vOrbit = planet.orbitalVelocity(altitude) centrifuge = horizontalSpeedOrb * horizontalSpeedOrb / (vOrbit * vOrbit) gravity = planet.gravity(altitude) downForceMagnitude = self.mass() * (centrifuge - gravity) dragVector = physics.vector(-cosPitch * dragMagnitude, -sinPitch * dragMagnitude) liftVector = physics.vector(-sinPitch * liftMagnitude, cosPitch * liftMagnitude) return (dragVector, liftVector, downForceMagnitude)
pygame.init() fps = pygame.time.Clock() window = pygame.display.set_mode(size) font = pygame.font.Font(None, 20) sun = MovingSun(pos=[400, 300], centerpos=[400, 300], vel=[0, 0], acc=[0, 0], mass=10000, color=(255, 255, 0), radius=10, window=window) moon = p.Planet(pos=[400, 500], vel=[-5, 0], acc=[0, 0], mass=10, color=(255, 255, 255), radius=5, window=window) planets = [sun, moon] counter = 0 stop = False while 1: sun.rotate() moon.verlet_a(0.5) moon.verlet_b(p.gravity(moon, sun), 0.5) moon.update_pos() sun.update_pos() if counter == 10: window.fill(pygame.Color(0, 0, 0)) for planet in planets: planet.t.newpoint((int(planet.pos[0]), int(planet.pos[1]))) planet.t.draw() for planet in planets: planet.draw() print_energy(sun, moon, font, window) pygame.display.update() fps.tick(30) counter = 0 counter += 1 for ev in pygame.event.get():
def reportLiftoffSpeed(name, mass, planet, altitude): liftForceNeeded = planet.gravity(altitude) * mass takeoffLift = liftForceNeeded / nlift liftoffSpeed = liftSurface.speedForLift(liftSurfaceAoA, takeoffLift, altitude, planet) print("%s speed %g m/s" % (name, liftoffSpeed))
def forces(parts, mass, flightPitch, AoA, v, altitude = 0, planet = planet.kerbin, deltaT = 0.04): """ Given a description of the plane, its total mass, the flight path pitch (the angle of prograde with the surface), the angle of attack (the angle of pitch with prograde), the speed, the altitude and the planet, Return the forces assuming we're at the max thrust we can muster at this altitude and controls are flat. """ vlift = [0, 0] vdrag = [0, 0] maxthrust = [0, 0] airUse = 0 airGet = 0 accountedMass = 0 pitch = flightPitch + AoA jetOptions = jets.standardoptions(planet, deltaT) flightPitchRad = math.radians(flightPitch) (flightPitchCos, flightPitchSin) = (math.cos(flightPitchRad), math.sin(flightPitchRad)) def standardDrag(mass): f = planet.dragForce(altitude, v, mass, 0.2) return (-f * flightPitchCos, -f * flightPitchSin) def liftVector(typ, angle): if isinstance(typ, lift.wing): f = typ.liftForce(AoA + angle, v, altitude, planet) # lift is 90 degrees from prograde return (-f * flightPitchSin, f * flightPitchCos) else: return (0,0) def dragVector(typ, angle): if isinstance(typ, lift.wing): f = typ.dragForce(AoA + angle, v, altitude, planet) return (-f * flightPitchCos, -f * flightPitchSin) elif isinstance(typ, jets.intake): f = typ.drag(altitude, v, AoA + angle, options = jetOptions) return (-f * flightPitchCos, -f * flightPitchSin) else: return standardDrag(typ.mass) def thrustVector(typ, angle): if isinstance(typ, jets.jetengine): t = typ.thrust(v) elif isinstance(typ, engine.engine): t = typ.thrust else: t = 0 enginePitch = math.radians(angle + pitch) return (math.cos(enginePitch) * t, math.sin(enginePitch) * t) def airRequired(typ): if isinstance(typ, jets.jetengine): return typ.airRequired(altitude, options = jetOptions) else: return 0 def airProvided(typ, angle): if isinstance(typ, jets.intake): return typ.intakeair(altitude, v, AoA + angle, options = jetOptions) else: return 0 for part in parts: try: (typ, n, angle) = part except: try: (typ, n) = part angle = 0 except: typ = part n = 1 angle = 0 vlift = vectoradd(vlift, vectorscale(n, liftVector(typ, angle))) vdrag = vectoradd(vdrag, vectorscale(n, dragVector(typ, angle))) maxthrust = vectoradd(maxthrust, vectorscale(n, thrustVector(typ, angle))) airUse += n * airRequired(typ) airGet += n * airProvided(typ, angle) accountedMass += n * typ.mass # account for throttle setting due to air if airUse <= airGet: throttle = 1 else: throttle = airGet / airUse thrust = vectorscale(throttle, maxthrust) # account for drag on unaccounted mass (at Cd = 0.2) unaccountedMass = mass - accountedMass if unaccountedMass > 0: vdrag = vectoradd(vdrag, standardDrag(unaccountedMass)) gravity = -planet.gravity(altitude) * mass net = [0, gravity] net = vectoradd(net, vlift) net = vectoradd(net, vdrag) net = vectoradd(net, thrust) print ("throttle: %.1f%%" % (throttle * 100)) print ("lift: (%7.2f, %7.2f) kN" % (vlift[0], vlift[1])) print ("drag: (%7.2f, %7.2f) kN" % (vdrag[0], vdrag[1])) print ("thrust: (%7.2f, %7.2f) kN" % (thrust[0], thrust[1])) print ("gravity: ( , %7.2f) kN" % gravity) print ("net: (%7.2f, %7.2f) kN" % (net[0], net[1])) return net