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

Python超人-宇宙模拟器

上级 6a718659
......@@ -6,31 +6,45 @@
# link :https://gitcode.net/pythoncr/
# 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
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 common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY, SECONDS_PER_YEAR, AU
from sim_scenes.func import mayavi_run, ursina_run
from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Moon
from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY, AU
from sim_scenes.func import ursina_run
from simulators.ursina.entities.body_timer import TimeData
from simulators.ursina.ui.control_ui import ControlUI
from simulators.ursina.ursina_event import UrsinaEvent
from astropy.coordinates import get_body_barycentric
from astropy.time import Time
from ursina import camera
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:
time = Time.now()
planets = planet_names.split(",")
positions = {}
posvels = {}
for planet in planets:
try:
position = get_body_barycentric(planet, time)
positions[planet] = position
print(planet, position)
position, velocity = get_body_barycentric_posvel(planet, time)
posvels[planet] = position, velocity
# print(planet, position)
except Exception as 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):
......@@ -51,43 +65,58 @@ if __name__ == '__main__':
# =====================================================================
# 以下展示的效果为太阳系真实的距离
# 由于宇宙空间尺度非常大,如果按照实际的天体大小,则无法看到天体,因此需要对天体的尺寸进行放大
sun = Sun(name="太阳", size_scale=0.4e2) # 太阳放大 80 倍,距离保持不变
sun = Sun(name="太阳", size_scale=0.4e2) # 太阳放大 40 倍,距离保持不变
bodies = [
sun,
Mercury(name="水星", size_scale=3e3), # 水星
Venus(name="金星", size_scale=3e3), # 金星
Earth(name="地球", size_scale=3e3), # 地球
Moon(name="月球", size_scale=3e3), # 月球
Mars(name="火星", size_scale=3e3), # 火星
Mercury(name="水星", size_scale=1.5e3), # 水星
Venus(name="金星", size_scale=1e3), # 金星
Earth(name="地球", size_scale=1e3), # 地球
Moon(name="月球", size_scale=2e3), # 月球
Mars(name="火星", size_scale=1.2e3), # 火星
Jupiter(name="木星", size_scale=6e2), # 木星
Saturn(name="土星", size_scale=6e2), # 土星
Uranus(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]
return [position.x.value * AU, position.z.value * AU, position.y.value * AU]
def get_body_posvel(body, posvels):
posvel = posvels.get(body.__class__.__name__, None)
return posvel
def on_ready():
# 运行前触发
pass
camera.rotation_z = -20
def on_timer_changed(time_data: TimeData):
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:
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.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))
# print(time_data.get_datetime(str(current_time)))
......@@ -102,8 +131,8 @@ if __name__ == '__main__':
# 使用 ursina 查看的运行效果
# 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹
# position = 左-右+、上+下-、前+后-
ursina_run(bodies, SECONDS_PER_WEEK,
position=(0, 2 * AU, -11 * AU),
ursina_run(bodies, 1,
position=(0, 0.2 * AU, -3 * AU),
gravity_works=False, # 关闭万有引力的计算
show_grid=False,
show_timer=True)
......@@ -224,6 +224,8 @@ class UrsinaSimulator(Simulator):
UrsinaEvent.on_evolving(evolve_dt)
# 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}
UrsinaEvent.on_before_evolving(evolve_args)
# if evolve_args["evolve_dt"] > 0:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册