事先只是一点免责声明:我从来没有研究过天文学或任何与此相关的精确科学(甚至没有研究过IT),所以我试图通过自我教育来填补这一空白。天文学是引起我注意的领域之一,而我的自我教育理念是应用方法。因此,直截了当-这是我有时间/心情时随便正在研究的轨道仿真模型。我的主要目标是创建一个完整的运动中的太阳系,并具有计划将航天器发射到其他行星的能力。
您都可以随时选择这个项目,并享受有趣的实验!
更新!!!(11月10日)
- 速度现在是适当的deltaV,并且通过给予附加运动来计算速度的和向量
- 您可以在每个运动的单位对象上放置任意数量的静态对象,以检查所有来源的重力矢量(并检查碰撞)
- 大大提高了计算性能
- 在matplotlib中解决交互式mod的问题。看起来这是仅适用于ipython的默认选项。常规python3明确要求该语句。
基本上,现在可以通过GiveMotion()进行deltaV矢量校正,从而从地球表面“发射”航天器并绘制向月球的任务。下一步是尝试实现全局时间变量以实现同步运动,例如,月球绕地球轨道飞行,而航天器尝试进行重力辅助操纵。
随时欢迎提出改进意见和建议!
使用matplotlib库在Python3中完成
import matplotlib.pyplot as plt
import math
plt.ion()
G = 6.673e-11 # gravity constant
gridArea = [0, 200, 0, 200] # margins of the coordinate grid
gridScale = 1000000 # 1 unit of grid equals 1000000m or 1000km
plt.clf() # clear plot area
plt.axis(gridArea) # create new coordinate grid
plt.grid(b="on") # place grid
class Object:
_instances = []
def __init__(self, name, position, radius, mass):
self.name = name
self.position = position
self.radius = radius # in grid values
self.mass = mass
self.placeObject()
self.velocity = 0
Object._instances.append(self)
def placeObject(self):
drawObject = plt.Circle(self.position, radius=self.radius, fill=False, color="black")
plt.gca().add_patch(drawObject)
plt.show()
def giveMotion(self, deltaV, motionDirection, time):
if self.velocity != 0:
x_comp = math.sin(math.radians(self.motionDirection))*self.velocity
y_comp = math.cos(math.radians(self.motionDirection))*self.velocity
x_comp += math.sin(math.radians(motionDirection))*deltaV
y_comp += math.cos(math.radians(motionDirection))*deltaV
self.velocity = math.sqrt((x_comp**2)+(y_comp**2))
if x_comp > 0 and y_comp > 0: # calculate degrees depending on the coordinate quadrant
self.motionDirection = math.degrees(math.asin(abs(x_comp)/self.velocity)) # update motion direction
elif x_comp > 0 and y_comp < 0:
self.motionDirection = math.degrees(math.asin(abs(y_comp)/self.velocity)) + 90
elif x_comp < 0 and y_comp < 0:
self.motionDirection = math.degrees(math.asin(abs(x_comp)/self.velocity)) + 180
else:
self.motionDirection = math.degrees(math.asin(abs(y_comp)/self.velocity)) + 270
else:
self.velocity = self.velocity + deltaV # in m/s
self.motionDirection = motionDirection # degrees
self.time = time # in seconds
self.vectorUpdate()
def vectorUpdate(self):
self.placeObject()
data = []
for t in range(self.time):
motionForce = self.mass * self.velocity # F = m * v
x_net = 0
y_net = 0
for x in [y for y in Object._instances if y is not self]:
distance = math.sqrt(((self.position[0]-x.position[0])**2) +
(self.position[1]-x.position[1])**2)
gravityForce = G*(self.mass * x.mass)/((distance*gridScale)**2)
x_pos = self.position[0] - x.position[0]
y_pos = self.position[1] - x.position[1]
if x_pos <= 0 and y_pos > 0: # calculate degrees depending on the coordinate quadrant
gravityDirection = math.degrees(math.asin(abs(y_pos)/distance))+90
elif x_pos > 0 and y_pos >= 0:
gravityDirection = math.degrees(math.asin(abs(x_pos)/distance))+180
elif x_pos >= 0 and y_pos < 0:
gravityDirection = math.degrees(math.asin(abs(y_pos)/distance))+270
else:
gravityDirection = math.degrees(math.asin(abs(x_pos)/distance))
x_gF = gravityForce * math.sin(math.radians(gravityDirection)) # x component of vector
y_gF = gravityForce * math.cos(math.radians(gravityDirection)) # y component of vector
x_net += x_gF
y_net += y_gF
x_mF = motionForce * math.sin(math.radians(self.motionDirection))
y_mF = motionForce * math.cos(math.radians(self.motionDirection))
x_net += x_mF
y_net += y_mF
netForce = math.sqrt((x_net**2)+(y_net**2))
if x_net > 0 and y_net > 0: # calculate degrees depending on the coordinate quadrant
self.motionDirection = math.degrees(math.asin(abs(x_net)/netForce)) # update motion direction
elif x_net > 0 and y_net < 0:
self.motionDirection = math.degrees(math.asin(abs(y_net)/netForce)) + 90
elif x_net < 0 and y_net < 0:
self.motionDirection = math.degrees(math.asin(abs(x_net)/netForce)) + 180
else:
self.motionDirection = math.degrees(math.asin(abs(y_net)/netForce)) + 270
self.velocity = netForce/self.mass # update velocity
traveled = self.velocity/gridScale # grid distance traveled per 1 sec
self.position = (self.position[0] + math.sin(math.radians(self.motionDirection))*traveled,
self.position[1] + math.cos(math.radians(self.motionDirection))*traveled) # update pos
data.append([self.position[0], self.position[1]])
collision = 0
for x in [y for y in Object._instances if y is not self]:
if (self.position[0] - x.position[0])**2 + (self.position[1] - x.position[1])**2 <= x.radius**2:
collision = 1
break
if collision != 0:
print("Collision!")
break
plt.plot([x[0] for x in data], [x[1] for x in data])
Earth = Object(name="Earth", position=(50.0, 50.0), radius=6.371, mass=5.972e24)
Moon = Object(name="Moon", position=(100.0, 100.0), radius=1.737, mass = 7.347e22) # position not to real scale
Craft = Object(name="SpaceCraft", position=(49.0, 40.0), radius=1, mass=1.0e4)
Craft.giveMotion(deltaV=8500.0, motionDirection=100, time=130000)
Craft.giveMotion(deltaV=2000.0, motionDirection=90, time=60000)
plt.show(block=True)
怎么运行的
归结为两点:
- 使用对象
Earth = Object(name="Earth", position=(50.0, 50.0), radius=6.371, mass=5.972e24)
在网格上的位置参数创建对象(默认情况下,网格的1个单位为1000 km,但是也可以更改),以网格为单位的半径和以kg为单位的质量。 - 给对象一些deltaV,例如,
Craft.giveMotion(deltaV=8500.0, motionDirection=100, time=130000)
显然需要Craft = Object(...)
首先创建,如前所述。此处的参数deltaV
以m / s为单位(请注意,现在加速度是瞬时的),motionDirection
是以度为单位的deltaV的方向(从当前位置想象物体周围360度的圆,因此方向是该圆上的一个点),最后参数time
是多少秒之后,将监视对象的delV推入轨迹。随后giveMotion()
从上一个的最后一个位置开始giveMotion()
。
问题:
- 这是计算轨道的有效算法吗?
- 有哪些明显的改进要做?
- 我一直在考虑“ timeScale”变量,它将优化计算,因为可能不必每秒重新计算向量和位置。关于应该如何实施它的任何想法,或者通常它是一个好主意?(准确性损失与改进的性能)
基本上,我的目的是开始对该主题进行讨论,并探讨其发展方向。并且,如果可能的话,学习(甚至更好地-教)一些新颖有趣的东西。
随时尝试!
尝试使用:
Earth = Object(name="Earth", position=(50.0, 100.0), radius=6.371, mass=5.972e24)
Moon = Object(name="Moon", position=(434.0, 100.0), radius=1.737, mass = 7.347e22)
Craft = Object(name="SpaceCraft", position=(43.0, 100.0), radius=1, mass=1.0e4)
Craft.giveMotion(deltaV=10575.0, motionDirection=180, time=322000)
Craft.giveMotion(deltaV=400.0, motionDirection=180, time=50000)
经过两次燃烧-我在地球轨道上进行了一次前进,而在月球轨道上进行了一次倒退,我获得了稳定的月球轨道。这些接近理论上的期望值吗?
建议的运动:尝试3次燃烧-从地球表面稳定地球轨道,前进燃烧以到达月球,逆行燃烧以稳定绕月球的轨道。然后尝试最小化deltaV。
注意:我计划为不熟悉python3语法的人使用大量注释来更新代码。