From 4cc9d0743cf2d0639c732135ee6833705265f1aa Mon Sep 17 00:00:00 2001 From: march3 Date: Tue, 4 Apr 2023 23:08:44 +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 --- sim_scenes/earth/earth_satellites.py | 111 +++++++++++++++++++++ sim_scenes/earth/free_fall_of_ball.py | 1 - simulators/ursina/entities/body_trail.py | 57 ++++++++--- simulators/ursina/entities/entity_utils.py | 15 +-- simulators/ursina/ursina_mesh.py | 12 ++- 5 files changed, 166 insertions(+), 30 deletions(-) create mode 100644 sim_scenes/earth/earth_satellites.py diff --git a/sim_scenes/earth/earth_satellites.py b/sim_scenes/earth/earth_satellites.py new file mode 100644 index 0000000..566e37c --- /dev/null +++ b/sim_scenes/earth/earth_satellites.py @@ -0,0 +1,111 @@ +# -*- coding:utf-8 -*- +# title :地月场景模拟 +# description :地月场景模拟 +# author :Python超人 +# date :2023-02-11 +# link :https://gitcode.net/pythoncr/ +# python_version :3.8 +# ============================================================================== +from bodies import Moon, Earth, Body +from common.consts import SECONDS_PER_HOUR, SECONDS_PER_HALF_DAY, SECONDS_PER_DAY, SECONDS_PER_WEEK, SECONDS_PER_MONTH +from sim_scenes.func import mayavi_run, ursina_run +import math +import random + +# def calculate_satellite_velocity(earth: Earth, altitude): +# """ +# +# @param earth_raduis: +# @param altitude: +# @return: +# """ +# # 地球引力常数 +# G = 6.67430e-11 +# # 地球质量 +# M = earth.mass # 5.97e24 +# # 地球半径 +# R = earth.raduis + altitude +# # 地球表面的线速度 +# v_surface = math.sqrt(G * M / R) +# # 地球卫星轨道速度 +# v_satellite = math.sqrt(G * M / (R + altitude)) +# return v_satellite - v_surface + +import random + +import random +import math + + +def get_satellite_position_velocity(earth_mass, earth_position, earth_radius, altitude): + # 万有引力常数 + G = 6.6743 * 10 ** (-11) + # 地球质量 + M = earth_mass + # 地球半径+海拔高度 + R = earth_radius + altitude + + # 随机生成卫星的位置,确保在球面上 + phi = random.uniform(0, 2 * math.pi) + costheta = random.uniform(-1, 1) + u = random.uniform(0, 1) + + theta = math.acos(costheta) + r = R * (u ** (1 / 3)) + + x = r * math.sin(theta) * math.cos(phi) + y = r * math.sin(theta) * math.sin(phi) + z = r * math.cos(theta) + + # 计算速度的方向 + # 位置矢量 + r_vec = [x, y, z] + # 速度方向和位置矢量垂直,采用向量叉积的性质 + v_dir = [-y, x, 0] + # 归一化 + v_dir_norm = [v / math.sqrt(x ** 2 + y ** 2) for v in v_dir] + + # 计算速度大小 + v = math.sqrt(G * M / R) + + # 计算速度矢量 + v_vec = [v * dir for dir in v_dir_norm] + + # 计算卫星的位置和速度 + position = [earth_position[0] + x, earth_position[1] + y, earth_position[2] + z] + velocity = v_vec + + return tuple(position), [0, 0, 0] + + +def generate_satellite_coordinates(earth_radius, altitude): + theta = random.uniform(0, 2 * math.pi) # 在0~2π内随机生成一个角度 + phi = random.uniform(0, math.pi) # 在0~π内随机生成一个角度 + r = earth_radius + altitude # 地球半径+海拔高度 + x = r * math.sin(phi) * math.cos(theta) # 计算x坐标 + y = r * math.sin(phi) * math.sin(theta) # 计算y坐标 + z = r * math.cos(phi) # 计算z坐标 + + return [x, y, z] + + +if __name__ == '__main__': + """ + 地球、6个月球 + """ + # 地球在中心位置 + earth = Earth(init_position=[0, 0, 0], size_scale=1, texture="earth_hd.jpg", init_velocity=[0, 0, 0]) + # 北斗卫星高度为2.13-2.15万千米。GPS卫星平均轨道高度2.02万千米。 + bodies = [earth] + for i in range(10): + altitude = random.randint(4000, 10000) + position, velocity = get_satellite_position_velocity(earth.mass, earth.init_position, earth.raduis, altitude) + satellite = Body(name=f'卫星{i + 1}', mass=4.4e10, size_scale=1e3, color=(255, 200, 0), + init_position=position, + init_velocity=velocity) + bodies.append(satellite) + + # 使用 ursina 查看的运行效果 + # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 + # position = 左-右+、上+下-、前+后- + ursina_run(bodies, SECONDS_PER_HOUR/60, position=(0, 0, -80000), show_trail=True, view_closely=0.01) diff --git a/sim_scenes/earth/free_fall_of_ball.py b/sim_scenes/earth/free_fall_of_ball.py index d59aca3..89de9f9 100644 --- a/sim_scenes/earth/free_fall_of_ball.py +++ b/sim_scenes/earth/free_fall_of_ball.py @@ -9,7 +9,6 @@ from bodies import Moon, Earth, Body from common.consts import SECONDS_PER_HOUR, SECONDS_PER_HALF_DAY, SECONDS_PER_DAY, SECONDS_PER_WEEK, SECONDS_PER_MONTH from sim_scenes.func import mayavi_run, ursina_run -from bodies.body import AU if __name__ == '__main__': """ diff --git a/simulators/ursina/entities/body_trail.py b/simulators/ursina/entities/body_trail.py index 50bbaf9..f4fd60d 100644 --- a/simulators/ursina/entities/body_trail.py +++ b/simulators/ursina/entities/body_trail.py @@ -10,6 +10,7 @@ from ursina import Entity, Mesh, Text, color, destroy, Vec3 from common.color_utils import get_inverse_color +from simulators.ursina.ursina_mesh import create_label from simulators.ursina.ursina_mesh import create_arrow_line @@ -56,22 +57,46 @@ class BodyTrail(Entity): self.alpha = 0.3 # self.color = get_inverse_color(self.origin_color) - vel_info, vel_direction, vel_position = self.entity_infos["velocity"] - acc_info, acc_direction, acc_position = self.entity_infos["acceleration"] - - v_arrow, v_line, v_text = create_arrow_line((0, 0, 0), tuple(vel_direction), parent=self, - label=vel_info, color=color.red, alpha=0.8, arrow_scale=0.5) - if str(vel_info).startswith("0.00"): - v_text.parent = self - v_arrow.enabled = False - v_line.enabled = False - - a_arrow, a_line, a_text = create_arrow_line((0, 0, 0), tuple(acc_direction), parent=self, - label=acc_info, color=color.green, alpha=0.8, arrow_scale=0.5) - if str(acc_info).startswith("0.00"): - a_text.parent = self - a_arrow.enabled = False - a_line.enabled = False + vel_value, vel_direction, vel_position = self.entity_infos["velocity"] + acc_value, acc_direction, acc_position = self.entity_infos["acceleration"] + + if vel_value >= 0.01: + vel_info = "%.2fkm/s" % (vel_value) + elif vel_value >= 0.00001: + vel_info = "%.2fm/s" % (vel_value * 1000) + elif vel_value >= 0.00000001: + vel_info = "%.2fmm/s" % (vel_value * 1000 * 1000) + else: + vel_info = "0m/s" + + acc_m = acc_value * 1000 + + if acc_m >= 0.01: + acc_info = "%.2fm/s²" % (acc_m) + elif acc_m >= 0.00001: + acc_info = "%.2fmm/s²" % (acc_m * 1000) + # elif acc_m >= 0.00000001: + # acc_info = "%.2fμm/s²" % (acc_m * 1000 * 1000) + else: + acc_info = "0m/s²" + + if vel_value < 0.00000001: + create_label(parent=self, label=vel_info, pos=Vec3(-0.5, -0.5, -0.5), color=color.red).set_light_off() + # v_text.parent = self + # # v_arrow.enabled = False + # # v_line.enabled = False + else: + v_arrow, v_line, v_text = create_arrow_line((0, 0, 0), tuple(vel_direction), parent=self, + label=vel_info, color=color.red, alpha=0.8, arrow_scale=0.5) + + if acc_m < 0.00001: + create_label(parent=self, label=acc_info, pos=Vec3(0.5, 0.5, 0.5), color=color.green).set_light_off() + # a_text.parent = self + # a_arrow.enabled = False + # a_line.enabled = False + else: + a_arrow, a_line, a_text = create_arrow_line((0, 0, 0), tuple(acc_direction), parent=self, + label=acc_info, color=color.green, alpha=0.8, arrow_scale=0.5) class BodyTrailLine_OK(Entity): diff --git a/simulators/ursina/entities/entity_utils.py b/simulators/ursina/entities/entity_utils.py index e41ec0a..1d5042e 100644 --- a/simulators/ursina/entities/entity_utils.py +++ b/simulators/ursina/entities/entity_utils.py @@ -276,14 +276,8 @@ def merge_vectors(vectors): def create_trail_info(body, trail): velocity = merge_vectors(body.velocity) acceleration = merge_vectors(body.acceleration) - vel_info = "%.2fkm/s" % (velocity[0]) - - acc_m = acceleration[0] * 1000 - - if acc_m >= 0.01: - acc_info = "%.2fm/s²" % (acc_m) - else: - acc_info = "%.2fmm/s²" % (acc_m * 1000) + vel_value = velocity[0] # km/s + acc_value = acceleration[0] # km/s² vel_direction = velocity[1] vel_direction = np.array(vel_direction) * 5 @@ -297,5 +291,6 @@ def create_trail_info(body, trail): acc_position = acc_direction # acc_position = (acc_position[0], acc_position[1], acc_position[2]) if trail is not None: - trail.entity_infos = {"velocity": [vel_info, vel_direction, vel_position], - "acceleration": [acc_info, acc_direction, acc_position]} + trail.entity_infos = {"velocity": [vel_value, vel_direction, vel_position], + "acceleration": [acc_value, acc_direction, acc_position]} + diff --git a/simulators/ursina/ursina_mesh.py b/simulators/ursina/ursina_mesh.py index 1c202bf..49eebe5 100644 --- a/simulators/ursina/ursina_mesh.py +++ b/simulators/ursina/ursina_mesh.py @@ -91,6 +91,13 @@ def create_arrow(height=0.5, width=0.1): return arrow_mesh +def create_label(parent, label, pos, color, scale=50, alpha=1.0): + text = Text(label, parent=parent, scale=scale, billboard=True, color=color, + position=Vec3(pos) + Vec3(1, 1, 1), alpha=alpha, + font=UrsinaConfig.CN_FONT, background=False) + return text + + def create_arrow_line(from_pos, to_pos, parent=None, label=None, set_light_off=True, alpha=1.0, len_scale=0.5, color=color.white, thickness=2, @@ -125,9 +132,8 @@ def create_arrow_line(from_pos, to_pos, parent=None, label=None, arrow.set_light_off() if label is not None: - text = Text(label, parent=line, scale=text_scale, billboard=True, color=color, - position=Vec3(to_pos) + Vec3(1, 1, 1), alpha=alpha, - font=UrsinaConfig.CN_FONT, background=False) + text = create_label(parent=line, label=label, pos=Vec3(to_pos) * len_scale * 1.2, + color=color, scale=text_scale, alpha=alpha) if set_light_off: text.set_light_off() else: -- GitLab