提交 7b36b769 编写于 作者: 三月三net's avatar 三月三net

Python超人-宇宙模拟器

上级 6a718659
...@@ -6,31 +6,45 @@ ...@@ -6,31 +6,45 @@
# link :https://gitcode.net/pythoncr/ # link :https://gitcode.net/pythoncr/
# python_version :3.8 # python_version :3.8
# ============================================================================== # ==============================================================================
# pip install -i http://pypi.douban.com/simple/ --trusted-host=pypi.douban.com de423
# solar_system_ephemeris.bodies
# ('earth', 'sun', 'moon', 'mercury', 'venus', 'earth-moon-barycenter', 'mars', 'jupiter', 'saturn', 'uranus', 'neptune')
import numpy as np import numpy as np
from astropy.coordinates import get_body_barycentric_posvel
from astropy.time import Time
from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto, Moon, Asteroids from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Moon
from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY, SECONDS_PER_YEAR, AU from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY, AU
from sim_scenes.func import mayavi_run, ursina_run from sim_scenes.func import ursina_run
from simulators.ursina.entities.body_timer import TimeData from simulators.ursina.entities.body_timer import TimeData
from simulators.ursina.ui.control_ui import ControlUI from simulators.ursina.ui.control_ui import ControlUI
from simulators.ursina.ursina_event import UrsinaEvent from simulators.ursina.ursina_event import UrsinaEvent
from astropy.coordinates import get_body_barycentric from ursina import camera
from astropy.time import Time
def get_bodies_positions(planet_names="sun,mercury,venus,earth,moon,mars,jupiter,saturn,uranus,neptune", time=None): def get_bodies_posvels(planet_names="sun,mercury,venus,earth,moon,mars,jupiter,saturn,uranus,neptune", time=None):
if time is None: if time is None:
time = Time.now() time = Time.now()
planets = planet_names.split(",") planets = planet_names.split(",")
positions = {} posvels = {}
for planet in planets: for planet in planets:
try: try:
position = get_body_barycentric(planet, time) position, velocity = get_body_barycentric_posvel(planet, time)
positions[planet] = position posvels[planet] = position, velocity
print(planet, position) # print(planet, position)
except Exception as e: except Exception as e:
print(planet, str(e)) print(planet, str(e))
return positions return posvels
def recalc_moon_position(moon_posvel, earth_pos):
moon_pos, moon_vel = moon_posvel[0], moon_posvel[1]
moon_pos_to_earth = moon_pos - earth_pos
moon_pos_to_earth = moon_pos_to_earth * 50
return moon_pos_to_earth + earth_pos, moon_vel
def get_bodies_names(bodies): def get_bodies_names(bodies):
...@@ -51,43 +65,58 @@ if __name__ == '__main__': ...@@ -51,43 +65,58 @@ if __name__ == '__main__':
# ===================================================================== # =====================================================================
# 以下展示的效果为太阳系真实的距离 # 以下展示的效果为太阳系真实的距离
# 由于宇宙空间尺度非常大,如果按照实际的天体大小,则无法看到天体,因此需要对天体的尺寸进行放大 # 由于宇宙空间尺度非常大,如果按照实际的天体大小,则无法看到天体,因此需要对天体的尺寸进行放大
sun = Sun(name="太阳", size_scale=0.4e2) # 太阳放大 80 倍,距离保持不变 sun = Sun(name="太阳", size_scale=0.4e2) # 太阳放大 40 倍,距离保持不变
bodies = [ bodies = [
sun, sun,
Mercury(name="水星", size_scale=3e3), # 水星 Mercury(name="水星", size_scale=1.5e3), # 水星
Venus(name="金星", size_scale=3e3), # 金星 Venus(name="金星", size_scale=1e3), # 金星
Earth(name="地球", size_scale=3e3), # 地球 Earth(name="地球", size_scale=1e3), # 地球
Moon(name="月球", size_scale=3e3), # 月球 Moon(name="月球", size_scale=2e3), # 月球
Mars(name="火星", size_scale=3e3), # 火星 Mars(name="火星", size_scale=1.2e3), # 火星
Jupiter(name="木星", size_scale=6e2), # 木星 Jupiter(name="木星", size_scale=6e2), # 木星
Saturn(name="土星", size_scale=6e2), # 土星 Saturn(name="土星", size_scale=6e2), # 土星
Uranus(name="天王星", size_scale=10e2), # 天王星 Uranus(name="天王星", size_scale=10e2), # 天王星
Neptune(name="海王星", size_scale=10e2), # 海王星 Neptune(name="海王星", size_scale=10e2), # 海王星
] ]
# pip install -i http://pypi.douban.com/simple/ --trusted-host=pypi.douban.com de423
names = get_bodies_names(bodies)
names = get_bodies_names(bodies)
def get_body_position(body, positions):
position = positions.get(body.__class__.__name__, None)
if position is None:
return [0, 0, 0]
# return [position.x.value * AU, position.y.value * AU, position.z.value * AU] def get_body_posvel(body, posvels):
return [position.x.value * AU, position.z.value * AU, position.y.value * AU] posvel = posvels.get(body.__class__.__name__, None)
return posvel
def on_ready(): def on_ready():
# 运行前触发 # 运行前触发
pass camera.rotation_z = -20
def on_timer_changed(time_data: TimeData): def on_timer_changed(time_data: TimeData):
t = current_time + time_data.total_days t = current_time + time_data.total_days
positions = get_bodies_positions(names, t) posvels = get_bodies_posvels(names, t)
# earth_loc = None
earth_pos = None
for body in bodies: for body in bodies:
position = get_body_position(body, positions)
posvel = get_body_posvel(body, posvels)
if isinstance(body, Moon):
posvel = recalc_moon_position(posvel, earth_pos)
if posvel is None:
position, velocity = [0, 0, 0], [0, 0, 0]
else:
S_OF_D = 24 * 60 * 60
# 坐标单位:千米 速度单位:千米/秒
position, velocity = [posvel[0].x.value * AU, posvel[0].z.value * AU, posvel[0].y.value * AU], \
[posvel[1].x.value * AU / S_OF_D, posvel[1].z.value * AU / S_OF_D,
posvel[1].y.value * AU / S_OF_D]
body.position = np.array(position) body.position = np.array(position)
body.velocity = np.array(velocity)
if isinstance(body, Earth):
# earth_loc = EarthLocation(x=posvel[0].x, y=posvel[0].y, z=posvel[0].z)
earth_pos = posvel[0]
dt = time_data.get_datetime(str(current_time)) dt = time_data.get_datetime(str(current_time))
# print(time_data.get_datetime(str(current_time))) # print(time_data.get_datetime(str(current_time)))
...@@ -102,8 +131,8 @@ if __name__ == '__main__': ...@@ -102,8 +131,8 @@ if __name__ == '__main__':
# 使用 ursina 查看的运行效果 # 使用 ursina 查看的运行效果
# 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹
# position = 左-右+、上+下-、前+后- # position = 左-右+、上+下-、前+后-
ursina_run(bodies, SECONDS_PER_WEEK, ursina_run(bodies, 1,
position=(0, 2 * AU, -11 * AU), position=(0, 0.2 * AU, -3 * AU),
gravity_works=False, # 关闭万有引力的计算 gravity_works=False, # 关闭万有引力的计算
show_grid=False, show_grid=False,
show_timer=True) show_timer=True)
...@@ -224,6 +224,8 @@ class UrsinaSimulator(Simulator): ...@@ -224,6 +224,8 @@ class UrsinaSimulator(Simulator):
UrsinaEvent.on_evolving(evolve_dt) UrsinaEvent.on_evolving(evolve_dt)
# interval_fator 能让更新天体运行状态(位置、速度)更精确 # interval_fator 能让更新天体运行状态(位置、速度)更精确
evolve_dt = evolve_dt * self.interval_fator evolve_dt = evolve_dt * self.interval_fator
if run_speed_factor < 3:
evolve_dt *= 1.666 # 人为加入一个针对秒级计算的误差,保证模拟器的1秒和现实同步(不要求精确可以注释掉)
evolve_args = {"evolve_dt": evolve_dt} evolve_args = {"evolve_dt": evolve_dt}
UrsinaEvent.on_before_evolving(evolve_args) UrsinaEvent.on_before_evolving(evolve_args)
# if evolve_args["evolve_dt"] > 0: # if evolve_args["evolve_dt"] > 0:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册