import numpy as np
import plotly.graph_objects as go
class OrbitPlotter:
def __init__(self):
self.fig = go.Figure()
def add_vector(self, start_point, end_point, color='black'):
# コーンと線の色
# color = 'blue'
# ベクトルの方向を求める
u = end_point[0] - start_point[0]
v = end_point[1] - start_point[1]
w = end_point[2] - start_point[2]
# ベクトルの長さを計算
length = np.linalg.norm([u, v, w])
# コーンのサイズ調整(ベクトルの長さに応じてスケーリング)
cone_size = length * 0.1
cone_size=300
if length <= 500:
cone_size = cone_size * 0.5
# コーンの追加
self.fig.add_trace(go.Cone(
x=[end_point[0]], y=[end_point[1]], z=[end_point[2]], # コーンの位置(先端)
u=[u * 0.1], v=[v * 0.1], w=[w * 0.1], # コーンの向き
showscale=False,
colorscale=[[0, color], [1, color]], # コーンの色を設定
# hoverinfo='skip',
sizemode='absolute', # 絶対サイズモードに設定
sizeref=cone_size, # サイズのスケールを調整
anchor="tip" # コーンをベクトルの先端に配置
))
# ベクトル(線分)の追加
self.fig.add_trace(go.Scatter3d(
x=[start_point[0], end_point[0]], y=[start_point[1], end_point[1]], z=[start_point[2], end_point[2]],
mode='lines',
line=dict(color=color, width=2), # 線の太さを調整し、色を設定
hoverinfo='skip',
))
def add_orbit(self, semi_major_axis, eccentricity, inclination, raan, arg_periapsis, true_anomaly, num_points=1000):
print(type(num_points))
# 注意: 春分点方向は+Xの方向に一致していると思う
# semi_major_axis: 長半径: 楕円軌道の長い方の軸の半分の長さで、軌道のサイズを表します。
# eccentricity: 離心率: 楕円の形状を示す無次元数で、円からの偏り具合を表します。
# inclination: 軌道傾斜角: 軌道面が基準面(通常は地球の赤道面)に対して傾いている角度。
# raan: 昇交点赤経: 昇交点(軌道が赤道面を北向きに通過する点)と基準方向(通常は春分点)との間の角度。
# arg_periapsis: 近日点引数: 軌道の昇交点から近日点までの角度。
# true_anomaly: 真近点離角: 衛星の現在位置と近日点との間の角度。
# 平均運動の計算
mu = 398600.436 # 地球の標準重力定数(km^3/s^2)
n = np.sqrt(mu / semi_major_axis**3)
# 時間配列の計算
periods = 1 # 計算する軌道周期の数
t = np.linspace(0, periods * 2 * np.pi / n, num_points)
# ケプラー軌道要素の計算
mean_anomaly = n * t
eccentric_anomaly = mean_anomaly.copy()
for _ in range(10): # 離心近似の反復計算
eccentric_anomaly = mean_anomaly + eccentricity * np.sin(eccentric_anomaly)
true_anomaly_calculated = 2 * np.arctan(np.sqrt((1 + eccentricity) / (1 - eccentricity)) * np.tan(eccentric_anomaly / 2))
# 軌道面内の位置の計算
r = semi_major_axis * (1 - eccentricity**2) / (1 + eccentricity * np.cos(true_anomaly_calculated))
x_orbital_plane = r * np.cos(true_anomaly_calculated)
y_orbital_plane = r * np.sin(true_anomaly_calculated)
# 慣性フレームへの回転
x = x_orbital_plane * (np.cos(arg_periapsis) * np.cos(raan) - np.sin(arg_periapsis) * np.cos(inclination) * np.sin(raan)) - \
y_orbital_plane * (np.sin(arg_periapsis) * np.cos(raan) + np.cos(arg_periapsis) * np.cos(inclination) * np.sin(raan))
y = x_orbital_plane * (np.cos(arg_periapsis) * np.sin(raan) + np.sin(arg_periapsis) * np.cos(inclination) * np.cos(raan)) + \
y_orbital_plane * (np.cos(arg_periapsis) * np.cos(inclination) * np.cos(raan) - np.sin(arg_periapsis) * np.sin(raan))
z = x_orbital_plane * np.sin(arg_periapsis) * np.sin(inclination) + y_orbital_plane * np.cos(arg_periapsis) * np.sin(inclination)
# 軌道をプロット
self.fig.add_trace(go.Scatter3d(
x=x, y=y, z=z,
mode='lines',
name='Orbit'
))
# 使用例
plotter = OrbitPlotter()
plotter.add_vector([0,0,0], [5000, 0, 0])
# 軌道パラメータの定義(半長軸、離心率、軌道傾斜角、昇交点赤経、近日点引数、真近点角)
semi_major_axis = 7000 # キロメートル単位
eccentricity = 0.1
inclination = np.radians(60) # ラジアン単位
raan = np.radians(30) # ラジアン単位
arg_periapsis = np.radians(45) # ラジアン単位
true_anomaly = np.radians(0) # ラジアン単位
# プロットする点の数
num_points = 1000
# 軌道の計算と描写
plotter.add_orbit(semi_major_axis, eccentricity, inclination, raan, arg_periapsis, true_anomaly)
# 軌道パラメータの定義(半長軸、離心率、軌道傾斜角、昇交点赤経、近日点引数、真近点角)
semi_major_axis = 7000 # キロメートル単位
eccentricity = 0.1
inclination = np.radians(60) # ラジアン単位
raan = np.radians(90) # ラジアン単位
arg_periapsis = np.radians(0) # ラジアン単位
true_anomaly = np.radians(0) # ラジアン単位
# プロットする点の数
num_points = 1000
# 軌道の計算と描写
num_points = 10
plotter.add_orbit(semi_major_axis, eccentricity, inclination, raan, arg_periapsis, true_anomaly)
# プロットの表示
plotter.fig.update_layout(scene=dict(aspectratio=dict(x=1, y=1, z=1)), scene_aspectmode='cube')
plotter.fig.update_layout(
width=1000, # グラフの幅と高さの設定
height=1000,
hoverlabel_font_size=20
)
plotter.fig.show()
Register as a new user and use Qiita more conveniently
- You get articles that match your needs
- You can efficiently read back useful information
- You can use dark theme