提交 2386ae12 编写于 作者: 三月三net's avatar 三月三net

Python超人-宇宙模拟器

上级 8173642d
from objs.obj import Obj
from objs.diamond import Diamond from objs.diamond import Diamond
from objs.football import Football from objs.football import Football
from objs.satellite import Satellite, Satellite2 from objs.satellite import Satellite, Satellite2
......
...@@ -14,6 +14,8 @@ from common.consts import AU ...@@ -14,6 +14,8 @@ from common.consts import AU
import copy import copy
import os import os
from simulators.ursina.entities.entity_utils import get_value_direction_vectors
class Obj(metaclass=ABCMeta): class Obj(metaclass=ABCMeta):
""" """
...@@ -197,6 +199,36 @@ class Obj(metaclass=ABCMeta): ...@@ -197,6 +199,36 @@ class Obj(metaclass=ABCMeta):
self.__position = value self.__position = value
self.__record_history() self.__record_history()
def acceleration_value(self):
"""
获取加速度的值(km/s²)
@return:
"""
direction_vectors = get_value_direction_vectors(self.acceleration)
return direction_vectors[0] # km/s²
def velocity_value(self):
"""
获取速度的值(km/s)
@return:
"""
direction_vectors = get_value_direction_vectors(self.velocity)
return direction_vectors[0] # km/s
def acceleration_value_direction(self):
"""
获取加速度的值(km/s²)和方向
@return: 值[0],方向[1]
"""
return get_value_direction_vectors(self.acceleration)
def velocity_value_direction(self):
"""
获取速度的值(km/s)和方向
@return: 值[0],方向[1]
"""
return get_value_direction_vectors(self.velocity)
@property @property
def acceleration(self): def acceleration(self):
""" """
......
...@@ -7,11 +7,31 @@ ...@@ -7,11 +7,31 @@
# python_version :3.8 # python_version :3.8
# ============================================================================== # ==============================================================================
from bodies import Body, Sun, Earth, Moon from bodies import Body, Sun, Earth, Moon
from objs import Obj
from objs import Satellite, Satellite2 from objs import Satellite, Satellite2
from common.consts import SECONDS_PER_HOUR, SECONDS_PER_DAY, SECONDS_PER_WEEK, SECONDS_PER_MONTH from common.consts import SECONDS_PER_HOUR, SECONDS_PER_DAY, SECONDS_PER_WEEK, SECONDS_PER_MONTH
from sim_scenes.func import calc_run from sim_scenes.func import calc_run
from bodies.body import AU from bodies.body import AU
from simulators.calc_simulator import CalcSimulator, CalcContext
def get_lagrangian_points(m1, m2, r):
"""
https://baike.baidu.com/item/%E6%8B%89%E6%A0%BC%E6%9C%97%E6%97%A5%E7%82%B9/731078
@param m1: 大质量
@param m2: 小质量
@param r: 半径
@return:
"""
a = m2 / (m1 + m2)
l1 = (0, 0, r * (1 - pow(a / 3, 1 / 3)))
l2 = (0, 0, r * (1 + pow(a / 3, 1 / 3)))
l3 = (0, 0, -r * (1 + (5 * a) / 12))
l4 = (pow(3, 1 / 2) / 2 * r, 0, (r / 2) * ((m1 - m2) / (m1 + m2)))
l5 = (-pow(3, 1 / 2) / 2 * r, 0, (r / 2) * ((m1 - m2) / (m1 + m2)))
return l1, l2, l3, l4, l5
bodies = [ bodies = [
Earth(init_position=[0, 0, 0], texture="earth_hd.jpg", Earth(init_position=[0, 0, 0], texture="earth_hd.jpg",
...@@ -19,17 +39,98 @@ bodies = [ ...@@ -19,17 +39,98 @@ bodies = [
Moon(init_position=[0, 0, 363104], # 距地距离约: 363104 至 405696 km Moon(init_position=[0, 0, 363104], # 距地距离约: 363104 至 405696 km
init_velocity=[-1.054152222, 0, 0], size_scale=1e1) # 月球放大 10 倍,距离保持不变 init_velocity=[-1.054152222, 0, 0], size_scale=1e1) # 月球放大 10 倍,距离保持不变
] ]
earth = bodies[0]
moon = bodies[1]
points = get_lagrangian_points(earth.mass, moon.mass, 363104)
L1_point = points[0]
point_z = L1_point[2] + 3301.0505 # 越大,离月球越近
init_velocity = [-0.890211, 0, 0]
satellite = Satellite(name=f'卫星', mass=1.4e10, size_scale=1e3, color=(255, 200, 0),
init_position=[L1_point[0], L1_point[1], point_z],
init_velocity=init_velocity, gravity_only_for=[earth, moon])
bodies.append(satellite)
def calc_simulator():
from simulators.calc_simulator import CalcSimulator, CalcContext
def evolve_next(context: CalcContext):
return context.evolve_count < 500
def after_evolve(dt, context: CalcContext):
target: Body = context.bodies[1]
# target: Obj = context.bodies[2]
context.init_param("acc_values", []).params["acc_values"].append(target.acceleration_value())
context.init_param("vel_values", []).params["vel_values"].append(target.velocity_value())
print(satellite.acceleration_value(), satellite.velocity_value())
def on_finished(context: CalcContext):
import matplotlib.pyplot as plt
# 解决中文显示问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
acc_values = context.params["acc_values"]
vel_values = context.params["vel_values"]
max_value = max(acc_values)
min_value = min(acc_values)
fig = plt.figure(figsize=(10, 6))
ax1 = fig.add_subplot(111)
ax1.plot(acc_values, 'blue', label='加速度')
ax1.set_ylabel('加速度', fontdict={'weight': 'normal', 'size': 15, 'color': 'blue'})
# ax1.set_title("加速度/速度", fontdict={'weight': 'normal', 'size': 15})
plt.title("%s max:%.4f mix:%.4f diff:%.4f" % (
moon.init_velocity[0], max_value * 1e6, min_value * 1e6, (max_value - min_value) * 1e6))
l1 = ax1.legend(loc='lower left', labels=['加速度'])
ax2 = ax1.twinx() # this is the important function
ax2.plot(vel_values, 'red', label='速度')
ax2.set_ylabel('速度', fontdict={'weight': 'normal', 'size': 15, 'color': 'red'})
ax2.set_xlabel('Same')
l2 = ax2.legend(loc='upper right', labels=['速度'])
plt.show()
CalcSimulator.on_after_evolve_subscription(after_evolve)
CalcSimulator.on_finished_subscription(on_finished)
calc_run(bodies, SECONDS_PER_HOUR, evolve_next=evolve_next)
def ursina_simulator():
from sim_scenes.func import ursina_run, camera_look_at
from simulators.ursina.entities.body_timer import TimeData
from simulators.ursina.entities.entity_utils import create_directional_light
from simulators.ursina.ursina_event import UrsinaEvent
from simulators.ursina.ursina_mesh import create_line
def on_ready():
# 运行前触发
# 运行开始前,将摄像机指向地球
def evolve_next(context: CalcContext): # 摄像机看向地球
return context.evolve_count < 200 camera_look_at(moon)
def on_timer_changed(time_data: TimeData):
from ursina import destroy
if hasattr(earth, "line"):
destroy(earth.line)
earth.line = create_line(from_pos=earth.planet.position, to_pos=moon.planet.main_entity.position)
def after_evolve(dt, context: CalcContext): # 订阅事件后,上面的函数功能才会起作用
moon: Body = context.bodies[1] # 运行前会触发 on_ready
print(moon.acceleration_value(), moon.velocity_value()) UrsinaEvent.on_ready_subscription(on_ready)
# 运行中,每时每刻都会触发 on_timer_changed
UrsinaEvent.on_timer_changed_subscription(on_timer_changed)
# 使用 ursina 查看的运行效果
# 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹
# position = 左-右+、上+下-、前+后-
ursina_run(bodies, SECONDS_PER_HOUR * 10,
position=(-300000, 1500000, -100),
show_timer=True,
show_trail=True)
CalcSimulator.on_after_evolve_subscription(after_evolve)
calc_run(bodies, SECONDS_PER_HOUR, evolve_next=evolve_next) if __name__ == '__main__':
calc_simulator()
# ursina_simulator()
...@@ -38,6 +38,17 @@ class CalcContext(Singleton): ...@@ -38,6 +38,17 @@ class CalcContext(Singleton):
# 存放参数字典数据,通过 get_param 获取 # 存放参数字典数据,通过 get_param 获取
self._params = {} self._params = {}
def init_param(self, key, value):
"""
只会初始化一次(除非删除掉)
@param key:
@param value:
@return:
"""
if key not in self._params:
self.put_param(key, value)
return self
@property @property
def bodies(self) -> []: def bodies(self) -> []:
return self.simulator.bodies_sys.bodies return self.simulator.bodies_sys.bodies
...@@ -52,6 +63,7 @@ class CalcContext(Singleton): ...@@ -52,6 +63,7 @@ class CalcContext(Singleton):
def put_param(self, key, data): def put_param(self, key, data):
self._params[key] = data self._params[key] = data
return self
def get_param(self, key): def get_param(self, key):
""" """
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册