Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Python_超人
宇宙模拟器
提交
47ff8692
宇宙模拟器
项目概览
Python_超人
/
宇宙模拟器
通知
19
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
宇宙模拟器
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
47ff8692
编写于
11月 24, 2023
作者:
三月三net
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Python超人-宇宙模拟器
上级
ba7f7a13
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
488 addition
and
0 deletion
+488
-0
docs/oumuamua/运行轨迹和时间.jpg
docs/oumuamua/运行轨迹和时间.jpg
+0
-0
sim_lab/halley_comet_sim_02.py
sim_lab/halley_comet_sim_02.py
+0
-0
sim_lab/halley_comet_sim_03.py
sim_lab/halley_comet_sim_03.py
+0
-0
sim_lab/oumuamua_sim.py
sim_lab/oumuamua_sim.py
+488
-0
未找到文件。
docs/oumuamua/运行轨迹和时间.jpg
0 → 100644
浏览文件 @
47ff8692
36.6 KB
sim_
scenes/solar_system
/halley_comet_sim_02.py
→
sim_
lab
/halley_comet_sim_02.py
浏览文件 @
47ff8692
文件已移动
sim_
scenes/solar_system
/halley_comet_sim_03.py
→
sim_
lab
/halley_comet_sim_03.py
浏览文件 @
47ff8692
文件已移动
sim_lab/oumuamua_sim.py
0 → 100644
浏览文件 @
47ff8692
# -*- coding:utf-8 -*-
# title :哈雷彗星场景半真实模拟
# description :哈雷彗星运行轨道使用了万有引力,其他天体使用 astropy 包的真实数据
# author :Python超人
# date :2023-10-28
# link :https://gitcode.net/pythoncr/
# python_version :3.9
# ==============================================================================
from
dataclasses
import
dataclass
from
dataclasses
import
field
from
ursina
import
camera
,
application
,
lerp
,
Vec3
from
common.celestial_data_service
import
init_bodies_reality_pos_vels
,
conv_to_astropy_time
,
\
set_solar_system_celestial_position
from
common.consts
import
SECONDS_PER_YEAR
,
AU
from
common.func
import
calculate_distance
from
bodies
import
Earth
from
sim_scenes.func
import
create_text_panel
,
camera_look_at
,
get_run_speed_factor
,
\
camera_move_update
,
camera_move_to_target_update
,
camera_move_control
from
sim_scenes.func
import
ursina_run
,
create_sphere_sky
from
simulators.ursina.entities.body_timer
import
TimeData
from
simulators.ursina.entities.entity_utils
import
get_value_direction_vectors
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_label
@
dataclass
(
order
=
True
)
class
OumuamuaParams
:
start_time
:
str
=
field
(
default
=
'1983-03-20 00:00:00'
)
init_velocity
:
list
[
float
]
=
field
(
default_factory
=
[
3.34
,
0
,
10.718
])
init_position
:
list
[
float
]
=
field
(
default_factory
=
[
0
,
0.5
*
AU
,
-
10
*
AU
])
class
OumuamuaSim
:
"""
星际访客奥陌陌
重要时间点:
"""
def
__init__
(
self
,
_params
=
None
):
# super(OumuamuaParams, self).__init__()
if
_params
is
None
:
self
.
params
=
OumuamuaParams
()
else
:
self
.
params
=
_params
if
isinstance
(
_params
.
start_time
,
str
):
self
.
start_time
=
conv_to_astropy_time
(
_params
.
start_time
)
else
:
self
.
start_time
=
_params
.
start_time
# print("北京时间:", dt.to_datetime(timezone=pytz.timezone('Asia/Shanghai')))
def
build
(
self
):
"""
构建太阳系系统以及哈雷彗星
@return:
"""
self
.
build_solar_system
(
ignore_gravity
=
True
,
start_time
=
self
.
start_time
)
self
.
sun
.
glows
=
(
2
,
1.005
,
0.01
)
# 创建哈雷彗星创建哈雷彗星
self
.
halley_comet
=
create_halley_comet
(
self
.
params
.
init_velocity
,
self
.
params
.
init_position
)
self
.
bodies
.
append
(
self
.
halley_comet
)
# from objs import CameraTarget
#
# self.bodies.append(CameraTarget(size_scale=2e8, init_position=[0, 0, 0], color=(255, 0, 0)))
# self.bodies.append(CameraTarget(size_scale=2e8, init_position=[5 * AU, 0, 0], color=(255, 255, 0)))
# print(CameraTarget.targets)
def
init_settings
(
self
):
"""
初始化设置
@return:
"""
from
ursina
import
color
# 创建天空
create_sphere_sky
(
scale
=
50000
)
# UrsinaConfig.trail_type = "curve_line"
# UrsinaConfig.trail_length = 300
UrsinaConfig
.
trail_type
=
"line"
# UrsinaConfig.trail_length = 152 # 尾巴数量刚刚好
UrsinaConfig
.
trail_length
=
130
UrsinaConfig
.
trail_thickness_factor
=
3
# UrsinaConfig.trail_length = 180
UrsinaConfig
.
trail_factor
=
3
# camera.clip_plane_near = 0.1
camera
.
clip_plane_far
=
51000
# camera.fov = 60
# self.sun.planet.color = color.white
# application.time_scale = 0.01
# 摄像机移动 update
# camera_move_update()
# camera_move_to_target_update()
def
create_orbit_lines
(
self
):
"""
创建太阳系天体的真实轨迹(太阳和哈雷彗星除外)
@return:
"""
self
.
orbit_lines
=
[]
for
body
in
self
.
bodies
[
1
:]:
if
isinstance
(
body
,
Earth
):
alpha
=
0.5
else
:
alpha
=
0.2
orbit_line
=
create_orbit_line
(
self
.
sun
,
body
,
self
.
start_time
,
alpha
=
alpha
)
if
orbit_line
is
not
None
:
self
.
orbit_lines
.
append
(
orbit_line
)
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
create_year_label
(
self
,
trail
,
year
,
halley_comet_pos
=
None
,
pos
=
None
,
label_color
=
None
,
scale
=
40
,
background
=
False
):
"""
在界面上创建年份的标签
@param trail:
@param year:
@param halley_comet_pos:
@return:
"""
# 为了不影响 2023年12月9日的显示,附近的 Label 就不显示
# if year in ["1986", "2061", "2023"]:
# return
if
trail
is
None
:
_pos
=
halley_comet_pos
else
:
_pos
=
pos
if
_pos
is
None
:
_pos
=
(
0
,
0
,
0
)
if
label_color
is
None
:
label_color
=
(
255
,
255
,
255
,
255
)
label
=
create_label
(
trail
,
label
=
year
,
pos
=
_pos
,
label_color
=
label_color
,
font
=
"fonts/DroidSansFallback.ttf"
,
scale
=
scale
,
alpha
=
1.0
,
background
=
background
)
label
.
set_light_off
()
# 只记录年
if
len
(
str
(
year
))
==
4
:
self
.
last_year
=
year
def
update_comet_trail_alpha
(
self
,
distance_sun
):
"""
根据彗哈雷星和太阳的距离,设置彗星尾巴的透明度来模仿接近太阳有慧尾,离开太阳到一定距离就渐渐消失
@param distance_sun: 彗哈雷星和太阳的距离
@return:
"""
# 距离转为天文单位
d_au
=
distance_sun
/
AU
# 渐渐消失的距离范围(开始消失距离, 完全消失距离)
HIDE_DISTANCE
=
3
,
12
# 彗星最大的透明度
MAX_ALPHA
=
0.8
# 大于完全消失距离
if
d_au
>=
HIDE_DISTANCE
[
1
]:
alpha
=
0
elif
HIDE_DISTANCE
[
1
]
>
d_au
>
HIDE_DISTANCE
[
0
]:
# 渐渐消失的距离范围内,通过距离值大小确定透明度(慢慢消失的效果)
alpha
=
MAX_ALPHA
-
(
d_au
-
HIDE_DISTANCE
[
0
])
/
(
HIDE_DISTANCE
[
1
]
-
HIDE_DISTANCE
[
0
])
*
MAX_ALPHA
else
:
alpha
=
MAX_ALPHA
# 修改彗星尾巴的透明度
self
.
halley_comet
.
planet
.
comet_trail
.
set_alpha
(
alpha
)
# self.halley_comet.planet.comet_sphere.alpha = alpha
def
show_milestone_lable
(
self
,
last_trail
,
dt
):
"""
远日点: 35.1 AU(2023年12月9日)
近日点: 0.586 AU 上次通过近日点:1986年2月9日 下次通过近日点:2061年7月28日
@param last_trail:
@param dt:
@return:
"""
milestones
=
[(
"1986-02-09"
,
(
0
,
2
,
0
)),
(
"2023-12-09"
,
(
0
,
0
,
-
3
)),
(
"2061-07-28"
,
(
0
,
3
,
0
))]
for
milestone
,
pos
in
milestones
:
prop_name
=
f
"milestone_
{
milestone
}
"
if
not
hasattr
(
self
,
prop_name
)
and
dt
.
strftime
(
"%Y-%m-%d"
)
>=
milestone
:
setattr
(
self
,
prop_name
,
milestone
)
if
pos
is
None
:
pos
=
(
0
,
2
,
0
)
self
.
create_year_label
(
last_trail
,
milestone
,
label_color
=
(
0
,
255
,
0
),
pos
=
pos
,
scale
=
60
,
background
=
True
)
# application.paused = True
# UrsinaEvent.on_pause()
# ControlUI.current_ui.on_off_switch.on_value_changed()
def
s_f
(
self
,
value
=
1
):
if
value
==
0
:
return
0
return
get_run_speed_factor
()
*
value
def
camera_move
(
self
,
dt
):
"""
摄像机移动控制
@param dt:
@return:
"""
# 摄像机移动控制数据
camera_move_infos
=
[
# 条件:年份
# 移动的信息:
# 按坐标系方向移动 x:右+左-, y:升+降-, z:前+(接近太阳)后-(远离太阳)
# 以摄像机视角移动 f:前 b:后 l:左 r:右 u:上 d:下
(
1982
,
{
"x"
:
2
,
"y"
:
1
}),
# (1983, {"to": {"ct_id": 1, "t": 10}}),
(
1986
,
{
"x"
:
2
,
"y"
:
-
2
,
"z"
:
-
15
}),
(
1987
,
{
"y"
:
-
6
,
"z"
:
-
12
}),
(
1988
,
{
"y"
:
-
3
,
"z"
:
-
12
}),
(
1989
,
{
"z"
:
-
8
,
"f"
:
-
5
}),
(
1993
,
{
"z"
:
-
8
,
"f"
:
-
3
}),
(
1995
,
{
"z"
:
-
8
}),
(
2000
,
{
"z"
:
-
8
,
"y"
:
-
0.2
}),
(
2013
,
{}),
(
2048
,
{
"f"
:
3
}),
(
2062
,
{
"y"
:
-
3
}),
(
2063
,
{
"y"
:
-
10
,
"z"
:
2
}),
(
2181
,
{}),
# (2082, {"exit": True})
]
camera_move_control
(
camera_move_infos
,
cond_cb
=
lambda
ps
:
ps
[
"next_cond"
]
>
dt
.
year
>=
ps
[
"cond"
],
value_conv
=
self
.
s_f
,
smooth
=
10
)
def
check_create_year_label
(
self
,
last_trail
,
dt
):
"""
检测并创建年标签
@param last_trail:
@param dt:
@return:
"""
if
last_trail
is
None
:
return
import
copy
year
=
dt
.
strftime
(
"%Y"
)
pos
=
self
.
halley_comet
.
planet
.
position
# 里程碑标签
if
self
.
show_milestone_lable
(
last_trail
,
dt
):
pass
elif
not
hasattr
(
self
,
"last_year"
):
# 第一次运行,则创建“年标签”
self
.
create_year_label
(
last_trail
,
year
,
pos
)
self
.
last_label_pos
=
copy
.
deepcopy
(
self
.
halley_comet
.
position
)
elif
self
.
last_year
!=
year
:
if
hasattr
(
self
,
"last_label_pos"
):
# 防止“年标签”显示非常紧密
d
=
calculate_distance
(
self
.
halley_comet
.
position
,
self
.
last_label_pos
)
if
d
>
2
*
AU
:
self
.
create_year_label
(
last_trail
,
year
,
pos
)
self
.
last_label_pos
=
copy
.
deepcopy
(
self
.
halley_comet
.
position
)
def
update_halley_comet_info
(
self
,
dt
):
"""
更新哈雷彗星的信息
@param dt:
@return:
"""
# 哈雷彗星面向太阳,这样彗尾就远离太阳的方向
self
.
halley_comet
.
planet
.
look_at
(
self
.
sun
.
planet
)
# 计算哈雷彗星与太阳、地球的距离
d_sun
=
calculate_distance
(
self
.
halley_comet
.
position
,
self
.
sun
.
position
)
d_earth
=
calculate_distance
(
self
.
halley_comet
.
position
,
self
.
earth
.
position
)
# 哈雷彗星所有轨迹线(注意不是彗尾)
trail_keys
=
self
.
halley_comet
.
planet
.
trails
.
keys
()
# 哈雷彗星有轨迹线
if
len
(
trail_keys
)
>
0
:
# 找的最后的轨迹线
last_trail
=
list
(
trail_keys
)[
-
1
]
if
hasattr
(
last_trail
,
"entity_infos"
):
# 如果是轨迹球,则轨迹球会记录当前位置与太阳、地球的距离,并记录了当前的日期
last_trail
.
entity_infos
[
"distance_from_sun"
]
=
d_sun
last_trail
.
entity_infos
[
"distance_from_earth"
]
=
d_earth
last_trail
.
entity_infos
[
"time"
]
=
dt
.
strftime
(
"%Y-%m-%d"
)
# 检测并再轨迹线上创建年标签
self
.
check_create_year_label
(
last_trail
,
dt
)
# 更新彗星尾巴的透明度
self
.
update_comet_trail_alpha
(
d_sun
)
# 计算和更新近日点数据
self
.
update_comet_peri
(
d_sun
,
dt
)
# 计算和更新远日点数据
self
.
update_comet_aphel
(
d_sun
,
dt
)
# 更新文字信息面板
self
.
update_text_panel
(
d_sun
)
def
update_text_panel
(
self
,
d_sun
):
"""
更新文字信息面板
@param d_sun:
@return:
"""
panel_text
=
"哈雷彗星:
\n\n
当前日距:%s AU"
%
"{:.3f}"
.
format
(
d_sun
/
AU
).
rjust
(
6
,
"0"
)
panel_text
+=
"
\n\n
最大日距:%s AU"
%
"{:.3f}"
.
format
(
self
.
comet_aphel
/
AU
).
rjust
(
6
,
"0"
)
panel_text
+=
"
\n\n
最小日距:%s AU"
%
"{:.3f}"
.
format
(
self
.
comet_peri
/
AU
).
rjust
(
6
,
"0"
)
velocity
,
_
=
get_value_direction_vectors
(
self
.
halley_comet
.
velocity
)
panel_text
+=
"
\n\n
当前速度:%s km/s"
%
"{:.3f}"
.
format
(
velocity
).
rjust
(
6
,
"0"
)
self
.
text_panel
.
text
=
panel_text
def
update_comet_aphel
(
self
,
d_sun
,
dt
):
"""
计算和更新远日点数据
@param d_sun:
@param dt:
@return:
"""
# 哈雷彗星离太阳最远的点称为 "aphelion of Halley's Comet"(远日点)
if
not
hasattr
(
self
,
"comet_aphel"
):
self
.
comet_aphel
=
d_sun
self
.
comet_aphel_dt
=
dt
.
strftime
(
"%Y-%m-%d"
)
elif
d_sun
>
self
.
comet_aphel
:
self
.
comet_aphel
=
d_sun
self
.
comet_aphel_dt
=
dt
.
strftime
(
"%Y-%m-%d"
)
def
update_comet_peri
(
self
,
d_sun
,
dt
):
"""
计算和更新近日点数据
@param d_sun:
@param dt:
@return:
"""
# 哈雷彗星离太阳最近的点称为 "perihelion of Halley's Comet"(近日点:comet_peri),
if
not
hasattr
(
self
,
"comet_peri"
):
self
.
comet_peri
=
d_sun
self
.
comet_peri_dt
=
dt
.
strftime
(
"%Y-%m-%d"
)
elif
d_sun
<
self
.
comet_peri
:
self
.
comet_peri
=
d_sun
self
.
comet_peri_dt
=
dt
.
strftime
(
"%Y-%m-%d"
)
def
update_ui
(
self
,
time_data
,
dt
):
"""
更新UI,包含天体的位置、时钟、轨道的位置
@param time_data:
@param dt:
@return:
"""
if
dt
.
year
>
2041
:
UrsinaConfig
.
trail_length
=
210
# 更新天体的位置
self
.
set_bodies_position
(
time_data
)
# # 更新时钟
# self.show_clock(dt)
# 更新轨道的位置(TODO:短时间可以忽略)
# for i, orbit_line in enumerate(self.orbit_lines):
# orbit_line.position = self.sun.planet.position
def
on_ready
(
self
):
"""
事件绑定后,模拟器运行前会触发
@return:
"""
# 初始化设置
self
.
init_settings
()
# self.set_window_size((int(1920 * r), int(1080 * r)), False)
# 最大分辨率的高度-1,保证不全屏
self
.
set_window_size
((
1920
,
1079
),
False
)
# self.set_window_size((1920 , 1080 ), False)
# 显示网格以及坐标线
# self.show_grid_axises()
# 创建太阳系天体的真实轨迹(太阳和哈雷彗星除外)
self
.
create_orbit_lines
()
# 创建信息显示面板
# self.text_panel = create_text_panel(font="fonts/sanjixiaozhuanti.ttf", font_scale=1.5)
self
.
text_panel
=
create_text_panel
(
font
=
"fonts/DroidSansFallback.ttf"
,
font_scale
=
1.3
)
def
on_timer_changed
(
self
,
time_data
):
"""
@param time_data:
@return:
"""
dt
=
time_data
.
get_datetime
(
self
.
start_time
)
# 摄像机看向哈雷彗星
camera_look_at
(
self
.
halley_comet
,
rotation_z
=
0
)
# camera.look_at_2d(self.halley_comet.planet.position, axis='y')
time_total_hours
=
time_data
.
total_hours
# if not hasattr(self, "last_total_hours"):
# self.last_total_hours = time_total_hours
# self.update_halley_comet_info(dt)
# print("time_total_hours", time_total_hours)
# # 摄像机移动每10小时更新一次
# self.interval_run(fun=self.camera_move, fun_args=[dt],
# total_times=time_total_hours,
# interval=20)
self
.
camera_move
(
dt
)
if
2040
>
dt
.
year
>
1987
:
update_halley_comet_info_interval
=
400
update_clock_interval
=
400
else
:
update_halley_comet_info_interval
=
33
update_clock_interval
=
60
# 更新哈雷彗星信息是每20个小时更新一次(哈雷彗星姿态、哈雷彗星距离信息)
self
.
interval_run
(
fun
=
self
.
update_halley_comet_info
,
fun_args
=
[
dt
],
total_times
=
time_total_hours
,
interval
=
update_halley_comet_info_interval
)
# 每50个小时更新一次界面(天体位置)
self
.
interval_run
(
fun
=
self
.
update_ui
,
fun_args
=
[
time_data
,
dt
],
total_times
=
time_total_hours
,
interval
=
60
)
self
.
interval_run
(
fun
=
self
.
show_clock
,
fun_args
=
[
dt
],
total_times
=
time_total_hours
,
interval
=
update_clock_interval
)
# # 每隔一段时间运行一次更新(不要太频繁更新,会导致摄像机抖动)
# if time_total_hours - self.last_total_hours > 50:
# self.update_halley_comet_info(dt)
# self.update_ui(time_data, dt)
# # 记录最后更新的总耗时(小时)
# self.last_total_hours = time_total_hours
if
__name__
==
'__main__'
:
"""
哈雷彗星场景模拟
"""
# 远日点: 35.1 AU(2023年12月9日)
# 近日点: 0.586 AU 上次通过近日点:1986年2月9日 下次通过近日点:2061年7月28日
# 2019年5月6日 34.772
params
=
OumuamuaParams
(
start_time
=
'1982-09-24 00:00:00'
,
# init_velocity=[-2.80, 5.10, 8.65], # 1/8
init_velocity
=
[
-
2.774
,
5.126
,
8.65
],
# 1/8
init_position
=
[
0
,
-
5
*
AU
,
-
10
*
AU
]
)
sim
=
OumuamuaSim
(
params
)
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
*
get_run_speed_factor
(),
# position=(0, 2 * AU, -11 * AU),
# position=(0, 0.5 * AU, -5 * AU),
# position=(2 * AU, -5 * AU, -20 * AU),
position
=
(
2
*
AU
,
-
6
*
AU
,
-
20
*
AU
),
cosmic_bg
=
''
,
show_trail
=
True
,
# bg_music='sounds/no_glory.mp3',
show_camera_info
=
False
,
# video_recoder=True,
show_control_info
=
False
,
timer_enabled
=
True
,
show_grid
=
False
)
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录