diff --git a/common/celestial_data_service.py b/common/celestial_data_service.py index f582a46630c2930bafabc5afcd31840296d4b77c..270f1f906d385c67ef3391e19996114322855586 100644 --- a/common/celestial_data_service.py +++ b/common/celestial_data_service.py @@ -137,8 +137,11 @@ def set_solar_system_celestial_position(bodies, dt, recalc_moon_pos): if isinstance(body, Asteroids): # 小行星带是模拟,不是正常的天体 posvel = None else: - # 获取天体的三维位置和矢量速度 - posvel = get_body_posvel(body, dt) + try: + # 获取天体的三维位置和矢量速度 + posvel = get_body_posvel(body, dt) + except Exception: + continue if isinstance(body, Moon): # 如果是月球,为了更好的展示效果,需要对月球的位置重新计算 moon_real_pos = [posvel[0].x.value * AU, posvel[0].z.value * AU, posvel[0].y.value * AU] diff --git a/sim_scenes/solar_system/halley_comet_sim_03.py b/sim_scenes/solar_system/halley_comet_sim_03.py new file mode 100644 index 0000000000000000000000000000000000000000..3dbf2f5238c39b5613ec306a618613ea3a643ec5 --- /dev/null +++ b/sim_scenes/solar_system/halley_comet_sim_03.py @@ -0,0 +1,226 @@ +# -*- coding:utf-8 -*- +# title :哈雷彗星场景模拟 +# description :哈雷彗星场景模拟 +# author :Python超人 +# date :2023-10-28 +# link :https://gitcode.net/pythoncr/ +# python_version :3.9 +# ============================================================================== +import math + +from astropy.time import Time +from ursina import camera, application + +from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto +from common.celestial_data_service import init_bodies_reality_pos_vels, get_reality_orbit_points, \ + conv_to_astropy_time, set_solar_system_celestial_position +from common.color_utils import trail_color_brightest +from common.consts import SECONDS_PER_YEAR, AU +from common.func import calculate_distance +from objs import HalleComet +from sim_scenes.func import create_text_panel +from sim_scenes.func import ursina_run, create_sphere_sky +from simulators.ursina.entities.body_timer import TimeData +from simulators.ursina.ui.control_ui import ControlUI +from simulators.ursina.ursina_config import UrsinaConfig +from simulators.ursina.ursina_event import UrsinaEvent +from simulators.ursina.ursina_mesh import create_orbit_by_points + + +class HalleyCometSim: + """ + 哈雷彗星场景模拟 + """ + + def __init__(self, start_time=None): + if start_time is None: + self.start_time = Time.now() + elif isinstance(start_time, str): + self.start_time = conv_to_astropy_time(start_time) + else: + self.start_time = start_time + # print("北京时间:", dt.to_datetime(timezone=pytz.timezone('Asia/Shanghai'))) + + def build_solar_system(self): + # region 构建太阳系 + show_trail = False + self.sun = Sun(size_scale=0.6e2, show_trail=show_trail) + self.mercury = Mercury(size_scale=5e3, show_trail=show_trail) + self.venus = Venus(size_scale=5e3, show_trail=show_trail) + self.earth = Earth(size_scale=5e3, rotate_angle=0, show_trail=show_trail) + self.mars = Mars(size_scale=5e3, show_trail=show_trail) + self.jupiter = Jupiter(size_scale=2.5e3, show_trail=show_trail) + self.saturn = Saturn(size_scale=2.5e3, show_trail=show_trail) + self.uranus = Uranus(size_scale=6e3, show_trail=show_trail) + self.neptune = Neptune(size_scale=6e3, show_trail=show_trail) + self.pluto = Pluto(size_scale=1e5, show_trail=show_trail) + self.bodies = [ + self.sun, # 太阳 + self.mercury, # 水星 + self.venus, # 金星 + self.earth, # 地球 + self.mars, # 火星 + self.jupiter, # 木星 + self.saturn, # 土星 + self.uranus, # 天王星 + self.neptune, # 海王星 + # self.pluto, # 冥王星 + ] + self.mercury.orbital_days = 87.9691 + self.venus.orbital_days = 224.701 + self.earth.orbital_days = 365.24219 + self.mars.orbital_days = 686.971 + self.jupiter.orbital_days = 11.862 * 365.24219 + self.saturn.orbital_days = 29.4571 * 365.24219 + self.uranus.orbital_days = 84.0205 * 365.24219 + self.neptune.orbital_days = 164.8 * 365.24219 + + # self.bodies = [ + # self.sun, # 太阳 + # self.mars, # 火星 + # self.neptune, # 海王星 + # ] + # endregion + trail_color_brightest(self.bodies) + for body in self.bodies[1:]: + body.init_velocity = [0, 0, 0] + body.set_ignore_gravity(True) + + init_bodies_reality_pos_vels(self.bodies, self.start_time) + + def build_halley_comet(self): + """ + 创建哈雷彗星 + @return: + """ + # 哈雷彗星的平均运行速度约为每小时 70,000 英里或每小时 126,000 公里 。(35公里/秒) + # 每76.1年环绕太阳一周的周期彗星 + self.halley_comet = HalleComet( # size_scale=4e7, + size_scale=0.2e8, + # [3.34, 0, 10.7] 2060-4- + # [3.34, 0, 10.712] 2061-5 + # [3.34, 0, 10.715] 2061-6-24 + # [3.34, 0, 10.718] 2061-8 + init_velocity=[3.34, 0, 10.718], + init_position=[0, 0.5 * AU, -10 * AU]) \ + .set_light_disable(True) + + self.bodies.append(self.halley_comet) + + def build(self): + self.build_solar_system() + self.build_halley_comet() + + def create_orbit_line(self, center_body, body): + orbital_days = int(math.ceil(body.orbital_days * 1.02)) + points = get_reality_orbit_points(type(body).__name__.lower(), start_time=self.start_time, days=orbital_days, + segments=100) + # print(points) + orbit_line = create_orbit_by_points(center_body.position, points, line_color=body.trail_color) + return orbit_line + + def on_ready(self): + """ + 事件绑定后,模拟器运行前会触发 + @return: + """ + # 创建天空 + UrsinaConfig.trail_type = "line" + UrsinaConfig.trail_length = 91 + # UrsinaConfig.trail_length = 1000 + UrsinaConfig.trail_thickness_factor = 3 + # camera.clip_plane_near = 0.1 + camera.clip_plane_far = 1000000 + create_sphere_sky(scale=200000) + + # WorldGrid().draw_axises(10) + + application.time_scale = 5 + self.orbit_lines = [] + for body in self.bodies[1:]: + if isinstance(body, HalleComet): + continue + orbit_line = self.create_orbit_line(self.sun, body) + self.orbit_lines.append(orbit_line) + + self.text_panel = create_text_panel() + + def show_clock(self, dt): + """ + 显示时钟 + @param dt: 时间 datetime + @return: + """ + # if self.clock_position_center: + # position, origin = (0, .25), (0, 0), + # else: + position, origin = (0.60, -0.465), (-0.5, 0.5), + + ControlUI.current_ui.show_message(dt.strftime('%Y-%m-%d %H:%M:%S'), + position=position, + origin=origin, + font="verdana.ttf", + close_time=-1) + + def set_bodies_position(self, time_data: TimeData): + """ + 设置天体的位置(包含速度和加速度的信息) + @param time_data: + @return: + """ + t = self.start_time + time_data.total_days + set_solar_system_celestial_position(self.bodies, t, False) + + def on_timer_changed(self, time_data): + """ + + @param time_data: + @return: + """ + dt = time_data.get_datetime(str(self.start_time)) + if hasattr(self, "halley_comet"): + # 哈雷彗星飞行的翻转效果 + if self.halley_comet.planet.enabled: + self.halley_comet.planet.rotation_x += 0.1 + self.halley_comet.planet.rotation_y += 1 + d = calculate_distance(self.halley_comet.position, self.sun.position) + self.text_panel.text = "哈雷彗星距离太阳:%.3f AU" % (d / AU) + + self.set_bodies_position(time_data) + self.show_clock(dt) + + for i, orbit_line in enumerate(self.orbit_lines): + orbit_line.position = self.sun.planet.position + + +if __name__ == '__main__': + """ + 哈雷彗星场景模拟 + """ + # 近日点 0.586 AU + # 上次通过近日点: 1986年2月9日 + # 下次通过近日点: 2061年7月28日 + # 远日点 35.1 AU 2023年12月9日 + sim = HalleyCometSim(start_time='1983-03-20 00:00:00') + sim.build() + + # 订阅事件后,上面2个函数功能才会起作用 + # 运行中,每时每刻都会触发 on_timer_changed + UrsinaEvent.on_timer_changed_subscription(sim.on_timer_changed) + # 运行前会触发 on_ready + UrsinaEvent.on_ready_subscription(sim.on_ready) + # 使用 ursina 查看的运行效果 + # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 + # position = 左-右+、上+下-、前+后- + ursina_run(sim.bodies, + SECONDS_PER_YEAR, + # position=(0, 2 * AU, -11 * AU), + position=(0, 0.5 * AU, -5 * AU), + cosmic_bg='', + show_trail=True, + # bg_music='sounds/no_glory.mp3', + show_camera_info=False, + show_control_info=False, + timer_enabled=True, + show_grid=False + ) diff --git a/simulators/simulator.py b/simulators/simulator.py index a1f1d544e24dd16c424c34ca331d09d3a08e8483..404bc54ae3acb3da1f695306f6e461194f8cd9e2 100644 --- a/simulators/simulator.py +++ b/simulators/simulator.py @@ -48,7 +48,7 @@ class Simulator(metaclass=ABCMeta): for idx, view in enumerate(self.body_views): body = self.bodies_sys.bodies[idx] - body.dt = dt + body.start_time = dt view.appeared = body.appeared if not view.appeared: view.disappear()