Added proper orbit calculations, and limited orbital plane calculations (only inclination is used).

This commit is contained in:
Quantum 2013-10-25 19:14:32 -04:00
parent f87524916e
commit 412387cc71
4 changed files with 55 additions and 7 deletions

View file

@ -1,5 +1,7 @@
from punyverse import framedata from punyverse import framedata
from math import radians, sin, cos from math import radians, sin, cos
from punyverse.orbit import KeplerOrbit
class Entity(object): class Entity(object):
def __init__(self, id, location, rotation=(0, 0, 0), direction=(0, 0, 0), background=False): def __init__(self, id, location, rotation=(0, 0, 0), direction=(0, 0, 0), background=False):
@ -48,9 +50,17 @@ class Satellite(Planet):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.parent = kwargs.pop('parent') self.parent = kwargs.pop('parent')
self.orbit_speed = kwargs.pop('orbit_speed', 1) self.orbit_speed = kwargs.pop('orbit_speed', 1)
self.inclination = kwargs.pop('inclination', 0)
# Semi-major axis and eccentricity defines orbit
self.distance = kwargs.pop('distance', 100) self.distance = kwargs.pop('distance', 100)
self.eccentricity = kwargs.pop('eccentricity', 0)
# Inclination and longitude of ascending node defines orbital plane
self.inclination = kwargs.pop('inclination', 0)
self.theta = 0 self.theta = 0
# OpenGL's z-axis is reversed
self.orbit = KeplerOrbit(self.distance, self.eccentricity, -self.inclination)
super(Satellite, self).__init__(*args, **kwargs) super(Satellite, self).__init__(*args, **kwargs)
def update(self): def update(self):
@ -63,10 +73,8 @@ class Satellite(Planet):
self.rotation = pitch, yaw, roll self.rotation = pitch, yaw, roll
self.parent.update() self.parent.update()
x, y, z = self.location
px, py, pz = self.parent.location px, py, pz = self.parent.location
self.theta += self.orbit_speed self.theta += self.orbit_speed
x = cos(radians(self.theta)) * self.distance + px x, z, y = self.orbit.orbit(self.theta)
z = sin(radians(self.theta)) * self.distance + pz self.location = (x + px, y + py, z + pz)
self.location = (x, y, z)

36
punyverse/orbit.py Normal file
View file

@ -0,0 +1,36 @@
from math import sin, cos, tan, atan, sqrt, radians
class KeplerOrbit(object):
def __init__(self, sma, eccentricity, inclination=0):
self.sma = sma
self.eccentricity = eccentricity
self.inclination = radians(inclination)
self.__true_anomaly_factor = sqrt((1 + eccentricity)/(1 - eccentricity))
self.__distance_factor = sma * (1 - eccentricity ** 2)
self.__sin_inclination = sin(self.inclination)
self.__cos_inclination = cos(self.inclination)
def eccentric_anomaly(self, mean_anomaly):
e1 = mean_anomaly
e2 = mean_anomaly + self.eccentricity * sin(e1)
while abs(e1 - e2) > 0.000001:
e1, e2 = e2, mean_anomaly + self.eccentricity * sin(e2)
return e2
def true_anomaly(self, mean_anomaly):
eccentric_anomaly = self.eccentric_anomaly(mean_anomaly)
return 2 * atan(self.__true_anomaly_factor * tan(eccentric_anomaly / 2))
def orbit(self, mean_anomaly):
mean_anomaly = radians(mean_anomaly)
phi = self.true_anomaly(mean_anomaly)
r = self.__distance_factor / (1 + self.eccentricity * cos(phi))
x = r * cos(phi)
y = r * sin(phi)
z = 0
x, z = (x * self.__cos_inclination - z * self.__sin_inclination,
x * self.__sin_inclination + z * self.__cos_inclination)
return x, y, z

View file

@ -17,6 +17,9 @@
"texture": ["moon.jpg", "moon_medium.jpg", "moon_small.jpg", [0.53, 0.53, 0.53, 1]], "texture": ["moon.jpg", "moon_medium.jpg", "moon_small.jpg", [0.53, 0.53, 0.53, 1]],
"radius": 25, "radius": 25,
"distance": 200, "distance": 200,
"orbit_speed": 1,
"eccentricity": 0.0549,
"inclination": 5.145,
"pitch": -90, "pitch": -90,
"yaw": 6.68 "yaw": 6.68
}, },

View file

@ -107,8 +107,9 @@ def load_world(file):
x, y, z = parent.location x, y, z = parent.location
distance = e(info.get('distance', 100)) distance = e(info.get('distance', 100))
x -= distance x -= distance
type = partial(Satellite, parent=parent, distance=distance, inclination=e(info.get('inclination', 0)), type = partial(Satellite, parent=parent, orbit_speed=info.get('orbit_speed', 1),
orbit_speed=e(info.get('orbit_speed', 1))) distance=distance, eccentricity=info.get('eccentricity', 0),
inclination=info.get('inclination', 0))
atmosphere_id = 0 atmosphere_id = 0
cloudmap_id = 0 cloudmap_id = 0