Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Python_超人
宇宙模拟器
提交
92b65ae6
宇宙模拟器
项目概览
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看板
提交
92b65ae6
编写于
8月 27, 2023
作者:
三月三net
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Python超人-宇宙模拟器
上级
e7d1a17f
变更
3
显示空白变更内容
内联
并排
Showing
3 changed file
with
153 addition
and
165 deletion
+153
-165
common/celestial_data_service.py
common/celestial_data_service.py
+111
-2
sim_scenes/solar_system/earth_moon_reality.py
sim_scenes/solar_system/earth_moon_reality.py
+38
-89
sim_scenes/solar_system/solar_system_reality.py
sim_scenes/solar_system/solar_system_reality.py
+4
-74
未找到文件。
common/celestial_data_service.py
浏览文件 @
92b65ae6
...
...
@@ -7,11 +7,18 @@
# python_version :3.8
# ==============================================================================
import
math
from
common.consts
import
G
from
bodies
import
Body
from
common.consts
import
G
,
AU
,
SECONDS_PER_DAY
from
bodies
import
Body
,
Sun
,
Asteroids
,
Moon
,
Earth
import
numpy
as
np
def
calc_solar_acceleration
(
body_or_pos
,
big_body
):
"""
计算天体的加速度
@param body_or_pos: 需要计算的天体
@param big_body: 大天体(太阳 或者 地球)
@return:
"""
if
isinstance
(
body_or_pos
,
Body
):
body_pos
=
body_or_pos
.
position
else
:
...
...
@@ -97,6 +104,108 @@ def get_celestial_body_data(body_name):
return
position
,
velocity
def
set_solar_system_celestial_position
(
bodies
,
dt
,
recalc_moon_pos
):
"""
根据日期时间 dt 设置太阳系中天体的真实位置
@param bodies: 太阳系中天体
@param dt: 时间
@param recalc_moon_pos: 是否对月球的位置进行重新计算。
为了更好的展示效果,需要对月球的位置重新计算(使得地月距离放大,月球相对地球方向不变),
重新计算位置后,地球和月球可以放大1000倍以上
@return:
"""
earth_pos
=
None
sun_pos
=
None
earth
=
None
sun
=
None
moon
=
None
for
body
in
bodies
:
if
isinstance
(
body
,
Sun
):
sun
=
body
elif
isinstance
(
body
,
Earth
):
earth
=
body
elif
isinstance
(
body
,
Moon
):
moon
=
body
for
body
in
bodies
:
if
isinstance
(
body
,
Asteroids
):
# 小行星带是模拟,不是正常的天体
posvel
=
None
else
:
# 获取天体的三维位置和矢量速度
posvel
=
get_body_posvel
(
body
,
dt
)
if
isinstance
(
body
,
Moon
):
# 如果是月球,为了更好的展示效果,需要对月球的位置重新计算
moon_real_pos
=
[
posvel
[
0
].
x
.
value
*
AU
,
posvel
[
0
].
z
.
value
*
AU
,
posvel
[
0
].
y
.
value
*
AU
]
# TODO:注释下行,月球就会在真实的位置
if
recalc_moon_pos
:
posvel
=
recalc_moon_position
(
posvel
,
earth_pos
)
if
posvel
is
None
:
# posvel 为空,则使用太阳的坐标
position
,
velocity
=
[
sun_pos
.
x
.
value
*
AU
,
sun_pos
.
z
.
value
*
AU
,
sun_pos
.
y
.
value
*
AU
],
[
0
,
0
,
0
]
else
:
# 坐标单位:千米 速度单位:千米/秒
position
,
velocity
=
[
posvel
[
0
].
x
.
value
*
AU
,
posvel
[
0
].
z
.
value
*
AU
,
posvel
[
0
].
y
.
value
*
AU
],
\
[
posvel
[
1
].
x
.
value
*
AU
/
SECONDS_PER_DAY
,
posvel
[
1
].
z
.
value
*
AU
/
SECONDS_PER_DAY
,
posvel
[
1
].
y
.
value
*
AU
/
SECONDS_PER_DAY
]
# 实时调整天体的位置和速度
body
.
position
=
np
.
array
(
position
)
body
.
velocity
=
np
.
array
(
velocity
)
if
isinstance
(
body
,
Asteroids
):
pass
elif
isinstance
(
body
,
Sun
):
# 记录太阳的位置
sun_pos
=
posvel
[
0
]
elif
isinstance
(
body
,
Moon
):
# 月球受到2个影响比较大的天体引力(地球和太阳),计算引力引起的加速度和
acc_earth
=
calc_solar_acceleration
(
moon_real_pos
,
earth
)
acc_sun
=
calc_solar_acceleration
(
moon_real_pos
,
sun
)
body
.
acceleration
=
[
acc_earth
[
0
]
+
acc_sun
[
0
],
acc_earth
[
1
]
+
acc_sun
[
1
],
acc_earth
[
2
]
+
acc_sun
[
2
]]
# elif isinstance(body, Earth):
# # 月球受到2个影响比较大的天体引力(地球和太阳),计算引力引起的加速度和
# acc_earth = calc_solar_acceleration(earth, moon)
# acc_sun = calc_solar_acceleration(earth, sun)
# body.acceleration = [acc_earth[0] + acc_sun[0],
# acc_earth[1] + acc_sun[1],
# acc_earth[2] + acc_sun[2]]
else
:
# 其他天体受到太阳引力
body
.
acceleration
=
calc_solar_acceleration
(
body
,
sun
)
if
isinstance
(
body
,
Earth
):
# 记录地球的位置
earth_pos
=
posvel
[
0
]
def
set_earth_rotation
(
earth
,
dt
):
"""
根据指定的时间控制地球的旋转角度(保证地球的自转和北京时间同步)
@param dt: 时间 datetime
@return:
"""
# timetuple 可以获取当天的小时数、分数钟、秒数
timetuple
=
dt
.
timetuple
()
# 当年的第几天
day_of_year
=
timetuple
.
tm_yday
# 根据当年的第几天计算出该日期当天的偏转角度:360度 / 365天 = 当天的偏转角度
angle_of_day
=
day_of_year
*
(
360
/
365
)
# 计算出精确的小时数
total_hours
=
timetuple
.
tm_hour
+
timetuple
.
tm_min
/
60
+
timetuple
.
tm_sec
/
60
/
60
# -total_hours: 负号控制地球的旋转方向、1天24小时,360度/24=15
# total_hours * 15:1天24小时,360度/24小时=1小时15度
# angle_of_day: 1年第几天的角度
earth
.
planet
.
rotation_y
=
-
total_hours
*
15
-
angle_of_day
+
15
# 精确调整
# pip install Astropysics
if
__name__
==
'__main__'
:
...
...
sim_scenes/solar_system/earth_moon_reality.py
浏览文件 @
92b65ae6
...
...
@@ -11,7 +11,8 @@ import math
import
numpy
as
np
from
bodies
import
Sun
,
Mercury
,
Venus
,
Earth
,
Mars
,
Asteroids
,
Jupiter
,
Saturn
,
Uranus
,
Neptune
,
Moon
from
common.celestial_data_service
import
get_body_posvel
,
recalc_moon_position
,
calc_solar_acceleration
from
common.celestial_data_service
import
get_body_posvel
,
recalc_moon_position
,
calc_solar_acceleration
,
\
set_solar_system_celestial_position
,
set_earth_rotation
from
common.consts
import
SECONDS_PER_WEEK
,
SECONDS_PER_DAY
,
AU
from
sim_scenes.func
import
ursina_run
,
camera_look_at
from
simulators.ursina.entities.body_timer
import
TimeData
...
...
@@ -53,8 +54,12 @@ class SolarSystemRealitySim:
self
.
moon_size_scale
=
5e1
self
.
sun_size_scale
=
1e1
self
.
earth_size_scale
=
1
self
.
moon_size_scale
=
1
self
.
sun_size_scale
=
1
self
.
sun
=
Sun
(
name
=
"太阳"
,
size_scale
=
self
.
sun_size_scale
)
# 太阳
self
.
earth
=
Earth
(
name
=
"地球"
,
texture
=
"earth_hd.jpg"
,
self
.
earth
=
Earth
(
name
=
"地球"
,
#
texture="earth_hd.jpg",
rotate_angle
=
3.44
,
size_scale
=
self
.
earth_size_scale
)
# 地球
self
.
earth_camera
=
Earth
(
name
=
"地球摄像机"
,
texture
=
"transparent.png"
,
...
...
@@ -80,26 +85,6 @@ class SolarSystemRealitySim:
if
self
.
debug_mode
:
self
.
earth
.
set_light_disable
(
True
)
def
set_earth_rotation
(
self
,
dt
):
"""
根据指定的时间控制地球的旋转角度(保证地球的自转和北京时间同步)
@param dt: 时间 datetime
@return:
"""
# timetuple 可以获取当天的小时数、分数钟、秒数
timetuple
=
dt
.
timetuple
()
# 当年的第几天
day_of_year
=
timetuple
.
tm_yday
# 根据当年的第几天计算出该日期当天的偏转角度:360度 / 365天 = 当天的偏转角度
angle_of_day
=
day_of_year
*
(
360
/
365
)
# 计算出精确的小时数
total_hours
=
timetuple
.
tm_hour
+
timetuple
.
tm_min
/
60
+
timetuple
.
tm_sec
/
60
/
60
# -total_hours: 负号控制地球的旋转方向、1天24小时,360度/24=15
# total_hours * 15:1天24小时,360度/24小时=1小时15度
# angle_of_day: 1年第几天的角度
self
.
earth
.
planet
.
rotation_y
=
-
total_hours
*
15
-
angle_of_day
+
15
# 精确调整
def
show_clock
(
self
,
dt
):
"""
显示时钟
...
...
@@ -125,58 +110,7 @@ class SolarSystemRealitySim:
@return:
"""
t
=
self
.
start_time
+
time_data
.
total_days
earth_pos
=
None
sun_pos
=
None
for
body
in
self
.
bodies
:
if
isinstance
(
body
,
Asteroids
):
# 小行星带是模拟,不是正常的天体
posvel
=
None
else
:
# 获取天体的三维位置和矢量速度
posvel
=
get_body_posvel
(
body
,
t
)
if
isinstance
(
body
,
Moon
):
# 如果是月球,为了更好的展示效果,需要对月球的位置重新计算
moon_real_pos
=
[
posvel
[
0
].
x
.
value
*
AU
,
posvel
[
0
].
z
.
value
*
AU
,
posvel
[
0
].
y
.
value
*
AU
]
# TODO:注释下行,月球就会在真实的位置
if
self
.
recalc_moon_pos
:
posvel
=
recalc_moon_position
(
posvel
,
earth_pos
)
if
posvel
is
None
:
# posvel 为空,则使用太阳的坐标
position
,
velocity
=
[
sun_pos
.
x
.
value
*
AU
,
sun_pos
.
z
.
value
*
AU
,
sun_pos
.
y
.
value
*
AU
],
[
0
,
0
,
0
]
else
:
# 坐标单位:千米 速度单位:千米/秒
position
,
velocity
=
[
posvel
[
0
].
x
.
value
*
AU
,
posvel
[
0
].
z
.
value
*
AU
,
posvel
[
0
].
y
.
value
*
AU
],
\
[
posvel
[
1
].
x
.
value
*
AU
/
SECONDS_PER_DAY
,
posvel
[
1
].
z
.
value
*
AU
/
SECONDS_PER_DAY
,
posvel
[
1
].
y
.
value
*
AU
/
SECONDS_PER_DAY
]
# 实时调整天体的位置和速度
body
.
position
=
np
.
array
(
position
)
body
.
velocity
=
np
.
array
(
velocity
)
if
isinstance
(
body
,
Asteroids
):
pass
elif
isinstance
(
body
,
Sun
):
# 记录太阳的位置
sun_pos
=
posvel
[
0
]
elif
isinstance
(
body
,
Moon
):
# 月球受到2个影响比较大的天体引力(地球和太阳),计算引力引起的加速度和
acc_earth
=
calc_solar_acceleration
(
moon_real_pos
,
self
.
earth
)
acc_sun
=
calc_solar_acceleration
(
moon_real_pos
,
self
.
sun
)
body
.
acceleration
=
[
acc_earth
[
0
]
+
acc_sun
[
0
],
acc_earth
[
1
]
+
acc_sun
[
1
],
acc_earth
[
2
]
+
acc_sun
[
2
]]
else
:
# 其他天体受到太阳引力
body
.
acceleration
=
calc_solar_acceleration
(
body
,
self
.
sun
)
if
isinstance
(
body
,
Earth
):
# 记录地球的位置
earth_pos
=
posvel
[
0
]
set_solar_system_celestial_position
(
self
.
bodies
,
t
,
self
.
recalc_moon_pos
)
def
on_ready
(
self
):
"""
...
...
@@ -190,6 +124,8 @@ class SolarSystemRealitySim:
# camera.fov = 30 # 调试时,拉近摄像机距离
# camera.fov = 1
camera
.
parent
=
self
.
earth_camera
.
planet
# camera.update = self.camera_update
# 需要按照时间和日期来控制地球的自转,所以删除控制地球自转的属性
delattr
(
self
.
earth
.
planet
,
"rotation_speed"
)
delattr
(
self
.
earth
.
planet
,
"rotspeed"
)
...
...
@@ -202,23 +138,36 @@ class SolarSystemRealitySim:
# 设置后,可以调整鼠标键盘的控制速度
application
.
time_scale
=
2
#
# def camera_update(self):
# camera.x = -50 # 100
# # camera.z = -10
# camera.y = 20
# camera.z = -10
# # 摄像机看向地球
# camera_look_at(self.earth)
def
set_camera_pos
(
self
,
time_data
:
TimeData
):
if
time_data
.
total_days
>
120
:
self
.
earth_camera
.
camera_init_val
=
+
3000000
elif
time_data
.
total_days
>
90
:
self
.
earth_camera
.
camera_init_val
=
+
1200000
elif
time_data
.
total_days
>
90
:
self
.
earth_camera
.
camera_init_val
+=
600000
elif
time_data
.
total_days
>
60
:
self
.
earth_camera
.
camera_init_val
+=
100000
camera
.
x
=
-
300
# 100
def
set_camera_pos
(
self
,
time_data
:
TimeData
):
# if time_data.total_days > 120:
# self.earth_camera.camera_init_val = +3000000
# elif time_data.total_days > 90:
# self.earth_camera.camera_init_val = +1200000
# elif time_data.total_days > 90:
# self.earth_camera.camera_init_val += 600000
# elif time_data.total_days > 60:
# self.earth_camera.camera_init_val += 100000
# camera.x = -300 # 100
# camera.z = 200
camera
.
y
+=
self
.
earth_camera
.
camera_init_val
*
UrsinaConfig
.
SCALE_FACTOR
# camera.y += self.earth_camera.camera_init_val * UrsinaConfig.SCALE_FACTOR
camera
.
x
=
-
60
# 100
# camera.z = -10
camera
.
y
=
50
UrsinaConfig
.
trail_factor
=
3
*
math
.
sqrt
(
camera
.
y
/
250
)
# UrsinaConfig.trail_factor = 3 * math.sqrt(camera.y / 250)
pass
def
on_timer_changed
(
self
,
time_data
:
TimeData
):
"""
...
...
@@ -230,7 +179,7 @@ class SolarSystemRealitySim:
# 设置天体的位置(包含速度和加速度的信息)
self
.
set_bodies_position
(
time_data
)
# 保证地球的自转和北京时间同步
se
lf
.
set_earth_rotation
(
dt
)
se
t_earth_rotation
(
self
.
earth
,
dt
)
# 调整摄像机的位置
self
.
set_camera_pos
(
time_data
)
# 摄像机看向地球
...
...
@@ -282,7 +231,7 @@ class SolarSystemRealitySim:
# 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹
# position = 左-右+、上+下-、前+后-
ursina_run
(
self
.
bodies
,
dt
,
position
=
(
0
,
50000000
0
,
0
),
position
=
(
0
,
0
,
0
),
# position=(0, 0.2 * AU, -3 * AU),
gravity_works
=
False
,
# 关闭万有引力的计算
show_grid
=
False
,
...
...
sim_scenes/solar_system/solar_system_reality.py
浏览文件 @
92b65ae6
...
...
@@ -10,7 +10,8 @@
import
numpy
as
np
from
bodies
import
Sun
,
Mercury
,
Venus
,
Earth
,
Mars
,
Asteroids
,
Jupiter
,
Saturn
,
Uranus
,
Neptune
,
Moon
from
common.celestial_data_service
import
get_body_posvel
,
recalc_moon_position
,
calc_solar_acceleration
from
common.celestial_data_service
import
get_body_posvel
,
recalc_moon_position
,
calc_solar_acceleration
,
\
set_solar_system_celestial_position
,
set_earth_rotation
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
...
...
@@ -90,26 +91,6 @@ class SolarSystemRealitySim:
if
self
.
debug_mode
:
self
.
earth
.
set_light_disable
(
True
)
def
set_earth_rotation
(
self
,
dt
):
"""
根据指定的时间控制地球的旋转角度(保证地球的自转和北京时间同步)
@param dt: 时间 datetime
@return:
"""
# timetuple 可以获取当天的小时数、分数钟、秒数
timetuple
=
dt
.
timetuple
()
# 当年的第几天
day_of_year
=
timetuple
.
tm_yday
# 根据当年的第几天计算出该日期当天的偏转角度:360度 / 365天 = 当天的偏转角度
angle_of_day
=
day_of_year
*
(
360
/
365
)
# 计算出精确的小时数
total_hours
=
timetuple
.
tm_hour
+
timetuple
.
tm_min
/
60
+
timetuple
.
tm_sec
/
60
/
60
# -total_hours: 负号控制地球的旋转方向、1天24小时,360度/24=15
# total_hours * 15:1天24小时,360度/24小时=1小时15度
# angle_of_day: 1年第几天的角度
self
.
earth
.
planet
.
rotation_y
=
-
total_hours
*
15
-
angle_of_day
+
15
# 精确调整
def
show_clock
(
self
,
dt
):
"""
显示时钟
...
...
@@ -134,58 +115,7 @@ class SolarSystemRealitySim:
@return:
"""
t
=
self
.
start_time
+
time_data
.
total_days
earth_pos
=
None
sun_pos
=
None
for
body
in
self
.
bodies
:
if
isinstance
(
body
,
Asteroids
):
# 小行星带是模拟,不是正常的天体
posvel
=
None
else
:
# 获取天体的三维位置和矢量速度
posvel
=
get_body_posvel
(
body
,
t
)
if
isinstance
(
body
,
Moon
):
# 如果是月球,为了更好的展示效果,需要对月球的位置重新计算
moon_real_pos
=
[
posvel
[
0
].
x
.
value
*
AU
,
posvel
[
0
].
z
.
value
*
AU
,
posvel
[
0
].
y
.
value
*
AU
]
# TODO:注释下行,月球就会在真实的位置
if
self
.
recalc_moon_pos
:
posvel
=
recalc_moon_position
(
posvel
,
earth_pos
)
if
posvel
is
None
:
# posvel 为空,则使用太阳的坐标
position
,
velocity
=
[
sun_pos
.
x
.
value
*
AU
,
sun_pos
.
z
.
value
*
AU
,
sun_pos
.
y
.
value
*
AU
],
[
0
,
0
,
0
]
else
:
# 坐标单位:千米 速度单位:千米/秒
position
,
velocity
=
[
posvel
[
0
].
x
.
value
*
AU
,
posvel
[
0
].
z
.
value
*
AU
,
posvel
[
0
].
y
.
value
*
AU
],
\
[
posvel
[
1
].
x
.
value
*
AU
/
SECONDS_PER_DAY
,
posvel
[
1
].
z
.
value
*
AU
/
SECONDS_PER_DAY
,
posvel
[
1
].
y
.
value
*
AU
/
SECONDS_PER_DAY
]
# 实时调整天体的位置和速度
body
.
position
=
np
.
array
(
position
)
body
.
velocity
=
np
.
array
(
velocity
)
if
isinstance
(
body
,
Asteroids
):
pass
elif
isinstance
(
body
,
Sun
):
# 记录太阳的位置
sun_pos
=
posvel
[
0
]
elif
isinstance
(
body
,
Moon
):
# 月球受到2个影响比较大的天体引力(地球和太阳),计算引力引起的加速度和
acc_earth
=
calc_solar_acceleration
(
moon_real_pos
,
self
.
earth
)
acc_sun
=
calc_solar_acceleration
(
moon_real_pos
,
self
.
sun
)
body
.
acceleration
=
[
acc_earth
[
0
]
+
acc_sun
[
0
],
acc_earth
[
1
]
+
acc_sun
[
1
],
acc_earth
[
2
]
+
acc_sun
[
2
]]
else
:
# 其他天体受到太阳引力
body
.
acceleration
=
calc_solar_acceleration
(
body
,
self
.
sun
)
if
isinstance
(
body
,
Earth
):
# 记录地球的位置
earth_pos
=
posvel
[
0
]
set_solar_system_celestial_position
(
self
.
bodies
,
t
,
self
.
recalc_moon_pos
)
def
on_ready
(
self
):
"""
...
...
@@ -219,7 +149,7 @@ class SolarSystemRealitySim:
# 设置天体的位置(包含速度和加速度的信息)
self
.
set_bodies_position
(
time_data
)
# 保证地球的自转和北京时间同步
se
lf
.
set_earth_rotation
(
dt
)
se
t_earth_rotation
(
self
.
earth
,
dt
)
# 显示时钟
self
.
show_clock
(
dt
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录