def localVelocity(self): """ Return the velocity as (horizontal, vertical) in the local frame of reference. """ horizon = self.horizonVector() up = vector(-horizon[1], horizon[0]) return vector(self.v.dot(horizon), self.v.dot(up))
def __init__(self, planet, thrust, Isp, mass, v = None, altitude = 0, deltaT = 0.03): self.t = 0 self.p = vector(0, planet.radius + altitude) if v is None: self.v = vector(planet.siderealSpeed(altitude), 0) else: self.v = vector(*v) self.deltaT = deltaT self.mass = mass self.initialMass = mass self.thrust = thrust self.Ve = Isp * g0 self.planet = planet
def forces(self, flightPitch, AoA, v, altitude = 0, jetoptions = jets.kerbonormative, throttle = 1, verbose = False): """ Given: 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, the throttle (default max we can achieve at this altitude) Prints a report if 'verbose' is set. Returns a tuple: (net, throttle, lift, drag, thrust, apparentGravity) net, lift, drag, and thrust are vectors with X being forward and Y being up. throttle is, from 0 to 1, how much the jet engines will be throttled up assuming proper intake layout apparentGravity is the force of gravity minus centrifugal effects. Normally negative. """ drag = physics.vector(0,0) lift = physics.vector(0,0) down = 0 maxthrust = physics.vector(0,0) airProvided = 0 airRequired = 0 for part in self._parts: (d,l,g) = part.zeroThrustForces(flightPitch, AoA, v, altitude, jetoptions.planet) drag = drag.add(d) lift = lift.add(l) down += g maxthrust = maxthrust.add(part.thrustForceAtMaxThrottle(v, flightPitch, AoA)) airProvided += part.airProvided(AoA, v, altitude, jetoptions) airRequired += part.airRequired(v, altitude, jetoptions) # account for throttle setting due to air if throttle * airRequired > airProvided: throttle = airProvided / airRequired thrust = maxthrust.scale(throttle) net = thrust.add(lift.add(drag.add(physics.vector(0, down)))) if verbose: print ("throttle: %.1f%%" % (throttle * 100)) print ("lift: (%7.2f, %7.2f) kN" % (lift[0], lift[1])) print ("drag: (%7.2f, %7.2f) kN" % (drag[0], drag[1])) print ("thrust: (%7.2f, %7.2f) kN" % (thrust[0], thrust[1])) print ("gravity: ( , %7.2f) kN" % down) print ("net: (%7.2f, %7.2f) kN" % (net[0], net[1])) return (net, throttle, lift, drag, thrust, down)
def gravityVector(self): """ Return the gravity vector in global coordinates. """ horizon = self.horizonVector() down = vector(horizon[1], -horizon[0]) g = self.planet.gravity(self.altitude()) return down.scale(g)
def thrustForceAtMaxThrottle(self, v, flightPitchDegrees, AoAdegrees): if isinstance(self._parttype, jets.jetengine): t = self._parttype.thrust(v) elif isinstance(self._parttype, engine.engine): t = self._parttype.thrust else: t = 0 enginePitchRad = math.radians(flightPitchDegrees + AoAdegrees + self._AoA) return physics.vector(math.cos(enginePitchRad) * t, math.sin(enginePitchRad) * t)
def objUpdate(): # Gravity force1 = vector(0, -1) * 10 * obj.mass obj.addForce(force1) # Circular force2 = (obj.pos - center).normalized() * obj.mass * (abs( obj.v)**2) / abs(obj.pos - center) obj.addForce(force2) # Tension force3 = -(force2 + force2.normalized() * (force2.normalized() * force1)) obj.addForce(force3) obj.update(1 / FPS) print(obj.pos - center)
class ang_object: pos1 = vector(0, 0) pos2 = vector(0, 1) I = 1 alpha = 0 omega = 0 angle = 0 center = vector(0, 0) force = [vector(0, 0), vector(0, 0)] torque = 0 def update(self, timeInterval: int): self.torque = 0 self.alpha = 0 for Force in self.force: self.torque += (Force[0] - self.center) @ Force[1] self.alpha = self.torque / self.I self.omega += self.alpha * timeInterval self.angle = self.omega * timeInterval self.pos1 = (self.pos1 - self.center).rotated( self.angle * math.pi / 180) + self.center self.pos2 = (self.pos2 - self.center).rotated( self.angle * math.pi / 180) + self.center
def objUpdate(): spring.startPos = pane.pos1 spring2.startPos = pane.pos2 spring.endPos = obj.pos kx = (abs(spring.startPos - spring.endPos) - spring.length) * spring.k spring2.endPos = obj2.pos kx2 = (abs(spring2.startPos - spring2.endPos) - spring2.length) * spring2.k obj.force = (spring.startPos - spring.endPos).normalized() * kx obj2.force = (spring2.startPos - spring2.endPos).normalized() * kx2 SF = [] SF.append([pane.pos1, -obj.force]) SF.append([pane.pos2, -obj2.force]) pane.force = SF obj.force += vector(0, -obj.mass * 10) obj2.force += vector(0, -obj2.mass * 10) obj.update(1 / FPS) obj2.update(1 / FPS) pane.update(1 / FPS)
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)
def horizonVector(self): angle = self.horizonAngle() return vector(math.cos(angle), math.sin(angle))
CLOCK = 0 plot = [] ### ONLY EDIT THIS AREA ############ class springObj: startPos = vector(0, 0) endPos = vector(0, 1) length = 1 k = 1 obj = object() obj.mass = 200 obj.pos = vector(WIDTH / 2, HEIGHT / 2 + 50) spring = springObj() spring.startPos = vector(WIDTH / 2, HEIGHT / 2 + 150) spring.endPos = obj.pos spring.length = 150 spring.k = 16 obj2 = object() obj2.mass = 200 obj2.pos = vector(WIDTH / 2, HEIGHT / 2 - 200) spring2 = springObj() spring2.startPos = obj.pos spring2.endPos = obj2.pos spring2.length = 150
def objUpdate(): obj.force = vector(0, 0) obj.update(1 / FPS)
BLACK = (0, 0, 0) WHITE = (255, 255, 255) BLUE = (0, 0, 255) GREEN = (0, 255, 0) RED = (255, 0, 0) FPS = 100 ACCEL = 100 WIDTH = 800 HEIGHT = 600 CLOCK = 0 plot = [] G = 1 ### ONLY EDIT THIS AREA ############ obj = object() obj.pos = vector(WIDTH / 2, HEIGHT / 2) obj2 = object() obj.mass = 1000 obj2.mass = 10 init = (G * obj.mass / 200)**0.5 init *= 1 obj2.v = vector(init, 0) obj2.pos = vector(WIDTH / 2, HEIGHT / 2 + 200) center = vector(WIDTH / 2, HEIGHT / 2)
BLACK = (0, 0, 0) WHITE = (255, 255, 255) BLUE = (0, 0, 255) GREEN = (0, 255, 0) RED = (255, 0, 0) FPS = 100 ACCEL = 10 WIDTH = 800 HEIGHT = 600 CLOCK = 0 plot = [] ### ONLY EDIT THIS AREA ############ obj = object() obj.v = vector(15, 0) obj.pos = vector(WIDTH / 2, HEIGHT / 2 - 200) obj2 = object() obj2.v = vector(-15, 0) obj2.pos = vector(WIDTH / 2, HEIGHT / 2 + 200) center = vector(WIDTH / 2, HEIGHT / 2) def objUpdate(): obj.force = obj.v.norm().normalized() * (obj.mass * (abs(obj.v)**2) / 200) obj2.force = obj2.v.norm().normalized() * (obj2.mass * (abs(obj2.v)**2) / 200) obj.update(1 / FPS) obj2.update(1 / FPS)
HEIGHT = 600 CLOCK = 0 plot = [] ### ONLY EDIT THIS AREA ############ class springObj: startPos = vector(0, 0) endPos = vector(0, 1) length = 1 k = 1 obj = object() obj.pos = vector(WIDTH / 2, HEIGHT / 2 - 190) spring = springObj() spring.startPos = vector(WIDTH / 2, HEIGHT / 2 + 150) spring.endPos = obj.pos spring.length = 240 spring.k = 1 def objUpdate(): spring.endPos = obj.pos kx = (abs(spring.startPos - spring.endPos) - spring.length) * spring.k obj.force = (spring.startPos - spring.endPos).normalized() * kx print(obj.force) obj.update(1 / FPS)
def _polarToCartesian(r, theta): return vector(r * math.cos(theta), r * math.sin(theta))
ACCEL = 5 WIDTH = 800 HEIGHT = 600 CLOCK = 0 plot = [] ### ONLY EDIT THIS AREA ############ class springObj: startPos = vector(0,0) endPos = vector(0,1) length = 1 k = 1 obj = object() obj.v = vector(0,0.00000001) obj.pos = vector(WIDTH/2, HEIGHT/2-190) spring = springObj() spring.startPos = vector(WIDTH/2, HEIGHT/2+150) spring.endPos = obj.pos spring.length = 240 spring.k = 1 def objUpdate(): spring.endPos = obj.pos kx = (abs(spring.startPos - spring.endPos) - spring.length) * spring.k obj.force = (spring.startPos - spring.endPos).normalized() * kx - abs(obj.v)*obj.v.normalized() * 0.1 print(obj.force) obj.update(1/FPS)
def update(self, timeInterval: int): self.torque = 0 self.alpha = 0 for Force in self.force: self.torque += (Force[0] - self.center) @ Force[1] self.alpha = self.torque / self.I self.omega += self.alpha * timeInterval self.angle = self.omega * timeInterval self.pos1 = (self.pos1 - self.center).rotated( self.angle * math.pi / 180) + self.center self.pos2 = (self.pos2 - self.center).rotated( self.angle * math.pi / 180) + self.center obj = object() obj.pos = vector(WIDTH / 2 - 200, HEIGHT / 2 - 95) obj.mass = 10 obj2 = object() obj2.pos = vector(WIDTH / 2 + 200, HEIGHT / 2 - 250) obj2.mass = 10 spring = springObj() spring.startPos = vector(WIDTH / 2 - 200, HEIGHT / 2 + 150) spring.endPos = obj.pos spring.length = 240 spring.k = 20 spring2 = springObj() spring2.startPos = vector(WIDTH / 2 + 200, HEIGHT / 2 + 150) spring2.endPos = obj2.pos
class springObj: startPos = vector(0, 0) endPos = vector(0, 1) length = 1 k = 1
BLACK = (0, 0, 0) WHITE = (255, 255, 255) BLUE = (0, 0, 255) GREEN = (0, 255, 0) RED = (255, 0, 0) FPS = 100 ACCEL = 10 WIDTH = 800 HEIGHT = 600 CLOCK = 0 plot = [] ### ONLY EDIT THIS AREA ############ obj = object() obj.v = vector(10**-20, 10**-20) obj.pos = vector(WIDTH / 2 - 130, HEIGHT / 2 - 100) center = vector(WIDTH / 2, HEIGHT / 2 + 200) def objUpdate(): # Gravity force1 = vector(0, -1) * 10 * obj.mass obj.addForce(force1) # Circular force2 = (obj.pos - center).normalized() * obj.mass * (abs( obj.v)**2) / abs(obj.pos - center) obj.addForce(force2) # Tension force3 = -(force2 + force2.normalized() * (force2.normalized() * force1))