From 7b36b769b90a871ef9a733954c0873eb85a3b68d Mon Sep 17 00:00:00 2001 From: march3 Date: Sun, 23 Jul 2023 17:31:33 +0800 Subject: [PATCH] =?UTF-8?q?Python=E8=B6=85=E4=BA=BA-=E5=AE=87=E5=AE=99?= =?UTF-8?q?=E6=A8=A1=E6=8B=9F=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../solar_system/solar_system_reality.py | 89 ++++++++++++------- simulators/ursina_simulator.py | 2 + 2 files changed, 61 insertions(+), 30 deletions(-) diff --git a/sim_scenes/solar_system/solar_system_reality.py b/sim_scenes/solar_system/solar_system_reality.py index 7e5799c..cfa7bc0 100644 --- a/sim_scenes/solar_system/solar_system_reality.py +++ b/sim_scenes/solar_system/solar_system_reality.py @@ -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) diff --git a/simulators/ursina_simulator.py b/simulators/ursina_simulator.py index c31db3f..0b69177 100644 --- a/simulators/ursina_simulator.py +++ b/simulators/ursina_simulator.py @@ -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: -- GitLab