This commit is contained in:
2026-02-02 14:32:39 +08:00
parent 2bfb64c855
commit 833b094e58
24 changed files with 2328 additions and 624 deletions

View File

@@ -45,9 +45,9 @@ class PhysicalConstants:
@dataclass
class EngineParams:
"""发动机/推进系统参数"""
name: str = "液氧液氢"
isp: float = 450 # 比冲 (秒)
specific_energy: float = 15.5e6 # 燃料比能量 (J/kg)
name: str = "液氧甲烷"
isp: float = 363 # 比冲 (秒) - LOX/CH4 (Raptor-class)
specific_energy: float = 11.9e6 # 燃料比能量 (J/kg)
@property
def exhaust_velocity(self) -> float:
@@ -505,17 +505,21 @@ def plot_latitude_effects(
engine: EngineParams = EngineParams(),
mission: MissionParams = MissionParams(),
constants: PhysicalConstants = PhysicalConstants(),
save_path: str = '/Volumes/Files/code/mm/20260130_b/latitude_effects.png',
save_path: str = '/Volumes/Files/code/mm/20260130_b/p1/latitude_effects.png',
lunar_mission: bool = True
):
"""
绘制纬度影响图表
Plot fuel ratio vs launch latitude.
参数:
lunar_mission: 如果True使用月球任务场景不需要轨道平面改变
Args:
engine: Engine parameters
mission: Mission parameters
constants: Physical constants
save_path: Output file path
lunar_mission: If True, use lunar mission scenario (no orbital plane change penalty)
"""
# 月球任务场景:设置高目标倾角,避免轨道平面改变惩罚
# Lunar mission scenario: set high target inclination to avoid plane change penalty
if lunar_mission:
mission_plot = MissionParams(
alpha=mission.alpha,
@@ -523,124 +527,50 @@ def plot_latitude_effects(
delta_v_ground_to_leo_base=mission.delta_v_ground_to_leo_base,
delta_v_tli=mission.delta_v_tli,
delta_v_loi=mission.delta_v_loi,
target_inclination=90.0, # 允许任意倾角
target_inclination=90.0, # Allow any inclination
elevator_length=mission.elevator_length
)
title_suffix = "\n(Lunar Mission - 无轨道平面改变)"
title_suffix = " (Lunar Mission)"
else:
mission_plot = mission
title_suffix = "\n(目标: 赤道轨道)"
title_suffix = " (Target: Equatorial Orbit)"
fig, axes = plt.subplots(2, 2, figsize=(16, 14))
# Golden ratio aspect: width=10, height=10*0.618
fig, ax = plt.subplots(figsize=(10, 10 * 0.618))
# 连续纬度范围
# Continuous latitude range
latitudes = np.linspace(0, 65, 100)
# ========== 图1: 自转速度 vs 纬度 ==========
ax1 = axes[0, 0]
rotation_velocities = [earth_rotation_velocity(lat, constants) for lat in latitudes]
ax1.plot(latitudes, rotation_velocities, 'b-', linewidth=2)
# 标记发射场 (使用绝对值纬度)
for name, site in LAUNCH_SITES.items():
abs_lat = abs(site.latitude)
v = earth_rotation_velocity(abs_lat, constants)
ax1.plot(abs_lat, v, 'ro', markersize=8)
# 简化标签显示
label = site.name.split('(')[0].strip()
ax1.annotate(label, (abs_lat, v), textcoords="offset points",
xytext=(3, 3), fontsize=8, rotation=15)
ax1.set_xlabel('Latitude |φ| (°)', fontsize=12)
ax1.set_ylabel('Rotation Velocity (m/s)', fontsize=12)
ax1.set_title('Earth Surface Rotation Velocity vs Latitude\nv = ω×R×cos(φ)', fontsize=13)
ax1.grid(True, alpha=0.3)
ax1.set_xlim(0, 65)
# ========== 图2: ΔV损失 vs 纬度 ==========
ax2 = axes[0, 1]
dv_losses = [delta_v_rotation_loss(lat, constants) for lat in latitudes]
ax2.plot(latitudes, dv_losses, 'r-', linewidth=2)
for name, site in LAUNCH_SITES.items():
abs_lat = abs(site.latitude)
dv = delta_v_rotation_loss(abs_lat, constants)
ax2.plot(abs_lat, dv, 'bo', markersize=8)
label = site.name.split('(')[0].strip()
ax2.annotate(label, (abs_lat, dv), textcoords="offset points",
xytext=(3, 3), fontsize=8, rotation=15)
ax2.set_xlabel('Latitude |φ| (°)', fontsize=12)
ax2.set_ylabel('ΔV Loss (m/s)', fontsize=12)
ax2.set_title('Rotation Velocity Loss vs Latitude\n(Relative to Equator)', fontsize=13)
ax2.grid(True, alpha=0.3)
ax2.set_xlim(0, 65)
# ========== 图3: 燃料比 vs 纬度 ==========
ax3 = axes[1, 0]
# Calculate fuel ratio for each latitude
fuel_ratios = []
for lat in latitudes:
site = LaunchSite("temp", lat)
result = ground_launch_specific_energy_with_latitude(engine, mission_plot, site, constants)
fuel_ratios.append(result['fuel_ratio'])
ax3.plot(latitudes, fuel_ratios, 'g-', linewidth=2, label='Fuel Ratio vs Latitude')
# Plot continuous curve
ax.plot(latitudes, fuel_ratios, 'g-', linewidth=2, label='Fuel Ratio vs Latitude')
# Mark launch sites
for name, site in LAUNCH_SITES.items():
abs_lat = abs(site.latitude)
site_temp = LaunchSite(site.name, abs_lat)
result = ground_launch_specific_energy_with_latitude(engine, mission_plot, site_temp, constants)
ax3.plot(abs_lat, result['fuel_ratio'], 'mo', markersize=8)
ax.plot(abs_lat, result['fuel_ratio'], 'mo', markersize=8)
# Simplified label
label = site.name.split('(')[0].strip()
ax3.annotate(label, (abs_lat, result['fuel_ratio']),
ax.annotate(label, (abs_lat, result['fuel_ratio']),
textcoords="offset points", xytext=(3, 3), fontsize=8, rotation=15)
ax3.set_xlabel('Latitude |φ| (°)', fontsize=12)
ax3.set_ylabel('Fuel / Payload Mass Ratio', fontsize=12)
ax3.set_title(f'Fuel Requirement vs Launch Latitude{title_suffix}', fontsize=13)
ax3.grid(True, alpha=0.3)
ax3.set_xlim(0, 65)
# ========== 图4: 能量对比柱状图 ==========
ax4 = axes[1, 1]
# 按纬度绝对值排序
results = []
for name, site in LAUNCH_SITES.items():
abs_lat = abs(site.latitude)
site_temp = LaunchSite(site.name, abs_lat)
result = ground_launch_specific_energy_with_latitude(engine, mission_plot, site_temp, constants)
result['abs_latitude'] = abs_lat
results.append(result)
results = sorted(results, key=lambda x: x['abs_latitude'])
# 简化标签
sites = [r['launch_site'].split('(')[0].strip() for r in results]
fuel_ratios_bar = [r['fuel_ratio'] for r in results]
abs_lats = [r['abs_latitude'] for r in results]
# 颜色映射:纬度越高颜色越深
colors = plt.cm.RdYlGn_r(np.array(abs_lats) / 65)
bars = ax4.bar(range(len(sites)), fuel_ratios_bar, color=colors)
ax4.set_ylabel('Fuel / Payload Mass Ratio', fontsize=12)
ax4.set_title(f'Fuel Requirement by Launch Site{title_suffix}', fontsize=13)
ax4.set_xticks(range(len(sites)))
ax4.set_xticklabels(sites, rotation=45, ha='right', fontsize=9)
ax4.grid(True, alpha=0.3, axis='y')
# 添加数值标签和纬度
for i, (bar, ratio, lat) in enumerate(zip(bars, fuel_ratios_bar, abs_lats)):
ax4.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.3,
f'{ratio:.1f}', ha='center', fontsize=9, fontweight='bold')
ax4.text(bar.get_x() + bar.get_width()/2, 1,
f'{lat:.0f}°', ha='center', fontsize=8, color='white')
ax.set_xlabel('Latitude |φ| (°)', fontsize=12)
ax.set_ylabel('Fuel / Payload Mass Ratio', fontsize=12)
ax.set_title(f'Fuel Requirement vs Launch Latitude{title_suffix}', fontsize=13)
ax.grid(True, alpha=0.3)
ax.set_xlim(0, 65)
plt.tight_layout()
plt.savefig(save_path, dpi=150, bbox_inches='tight')
print(f"纬度影响图表已保存至: {save_path}")
print(f"Latitude effects plot saved to: {save_path}")
return fig
@@ -886,6 +816,7 @@ def plot_comparison(
engines = [
EngineParams(name="固体火箭", isp=280, specific_energy=5e6),
EngineParams(name="液氧煤油", isp=350, specific_energy=10.3e6),
EngineParams(name="液氧甲烷", isp=363, specific_energy=11.9e6),
EngineParams(name="液氧液氢", isp=450, specific_energy=15.5e6),
]
@@ -922,11 +853,11 @@ def plot_comparison(
if __name__ == "__main__":
# 可以在这里修改参数
# 发动机参数
# 发动机参数 - 液氧甲烷 (LOX/CH4, Raptor-class)
engine = EngineParams(
name="液氧液氢",
isp=450, # 比冲 (秒)
specific_energy=15.5e6 # 燃料比能量 (J/kg)
name="液氧甲烷",
isp=363, # 比冲 (秒)
specific_energy=11.9e6 # 燃料比能量 (J/kg)
)
# 任务参数