基于真实火星探测任务的实际轨道设计(Python版)

本文介绍了一个火星探测任务的轨道模拟程序,使用Python数值计算库模拟了从地球到火星的转移轨道。程序基于二体问题计算太阳引力作用下的航天器轨迹,采用Hohmann转移轨道理论设计初始轨道参数,并加入了五次轨道机动(包括深空机动和轨迹修正)。模拟结果显示:转移轨道半长轴1.262AU,偏心率0.207,总飞行时间202天,总ΔV预算约323.2m/s。程序输出了2D和3D可视化结果,展示了航天器从地球轨道出发,经多次机动后到达火星轨道的完整轨迹。该模拟为火星探测任务提供了轨道设计和机动规划的参考框架。

五、轨迹出现直线 / 错位问题的数学原因(原代码 bug 根源)

  1. 原积分未均匀布点 t_eval,仅用自适应步长,分段拼接时时间点稀疏,视觉出现直线段;
  2. 机动状态赋值顺序错误,先存轨迹再改速度,造成轨迹点与机动不同步,重复画线;
  3. 修正方案:每段积分均匀取时间采样点,先积分结束再统一更新速度状态,保证轨迹连续光滑。
python 复制代码
import numpy as np
from scipy.integrate import solve_ivp
import matplotlib.pyplot as plt
from matplotlib.patches import Circle
from mpl_toolkits.mplot3d import Axes3D

# ==================== Celestial Constants & Orbital Parameters ====================
# Astronomical Unit (AU) and time units (seconds)
AU = 1.495978707e11          # 1 AU [m]
DAY = 86400.0                # 1 day [s]
SIDEREAL_YEAR = 365.256363004 * DAY  # 1 sidereal year [s]

# Gravitational parameters
MU_SUN = 1.32712440018e20    # Sun gravitational parameter [m^3/s^2]
MU_EARTH = 3.986004418e14    # Earth gravitational parameter [m^3/s^2]
MU_MARS  = 4.282837e13       # Mars gravitational parameter [m^3/s^2]

# Sun radius (for visualization)
R_SUN = 6.957e8              # Sun radius [m]

# ==================== Mission Parameters ====================
T_FLIGHT = 202.0 * DAY       # Total flight time [s]

# ==================== Orbital Mechanics Helper Functions ====================
def norm(v):
    """Compute Euclidean norm of a vector"""
    return np.sqrt(np.dot(v, v))

def acceleration_sun(t, state):
    """
    Heliocentric two-body acceleration
    state: [x, y, z, vx, vy, vz]
    return: [vx, vy, vz, ax, ay, az]
    """
    r_vec = state[:3]
    r = norm(r_vec)
    a_grav = -MU_SUN / r**3 * r_vec
    return np.concatenate([state[3:], a_grav])

def hohmann_transfer(r1, r2):
    """
    Calculate Hohmann transfer orbit parameters
    r1: Earth orbit radius [m] (circular approximation)
    r2: Mars orbit radius [m] (circular approximation)
    return: semi-major axis, velocity increments, transfer time, velocities
    """
    a_trans = (r1 + r2) / 2.0
    v_earth = np.sqrt(MU_SUN / r1)
    v_perihelion = np.sqrt(2*MU_SUN/r1 - MU_SUN/a_trans)
    v_aphelion = np.sqrt(2*MU_SUN/r2 - MU_SUN/a_trans)
    v_mars = np.sqrt(MU_SUN / r2)
    delta_v1 = v_perihelion - v_earth
    delta_v2 = v_mars - v_aphelion
    T_trans = np.pi * np.sqrt(a_trans**3 / MU_SUN)
    return a_trans, delta_v1, delta_v2, T_trans, v_perihelion, v_aphelion

# ==================== Main Simulation ====================
def simulate_mars_mission():
    """
    Mars exploration mission trajectory simulation
    Includes: heliocentric transfer with deep space maneuver and trajectory corrections
    """
    # Simplified circular orbit parameters
    r_earth = 1.0 * AU
    r_mars  = 1.524 * AU
    
    # Hohmann transfer calculation
    a_trans, dv1, dv2, T_trans, v_perihelion, v_aphelion = hohmann_transfer(r_earth, r_mars)
    e_trans = 1.0 - r_earth / a_trans
    
    print("="*60)
    print("MARS EXPLORATION ORBIT SIMULATION PARAMETERS")
    print("="*60)
    print(f"Transfer semi-major axis:      {a_trans/AU:.4f} AU")
    print(f"Transfer eccentricity:         {e_trans:.4f}")
    print(f"Hohmann transfer time:         {T_trans/DAY:.2f} days")
    print(f"ΔV1 (Departure burn):          {dv1:.2f} m/s")
    print(f"ΔV2 (Arrival burn):            {dv2:.2f} m/s")
    print(f"Perihelion velocity:           {v_perihelion:.2f} m/s")
    print(f"Aphelion velocity:             {v_aphelion:.2f} m/s")
    print(f"Total flight time:             {T_FLIGHT/DAY:.2f} days")
    print("="*60)
    
    # Maneuver timeline
    t_dsm  = 0.40 * T_trans
    t_tcm1 = 0.15 * T_trans
    t_tcm2 = 0.25 * T_trans
    t_tcm3 = 0.70 * T_trans
    t_moi  = 0.98 * T_trans
    
    maneuvers = {
        "TCM-1": {"t": t_tcm1, "dv": np.array([15.0, 0.0, 0.0])},
        "TCM-2": {"t": t_tcm2, "dv": np.array([0.0, 10.0, 0.0])},
        "DSM":   {"t": t_dsm,  "dv": np.array([250.0, 0.0, -50.0])},
        "TCM-3": {"t": t_tcm3, "dv": np.array([8.0, 0.0, 0.0])},
        "MOI":   {"t": t_moi,  "dv": np.array([-dv2, 0.0, 0.0])},
    }
    
    print("\nManeuver Timeline:")
    print("-"*60)
    for name, m in maneuvers.items():
        print(f"  {name:6s}: t = {m['t']/DAY:8.2f} days, |ΔV| = {norm(m['dv']):8.2f} m/s")
    print("="*60)
    
    # Initial state
    v_earth = np.sqrt(MU_SUN / r_earth)
    r0 = np.array([r_earth, 0.0, 0.0])
    v0 = np.array([0.0, v_earth + dv1, 0.0])
    state0 = np.concatenate([r0, v0])
    
    print(f"\nInitial State:")
    print(f"  Position: [{r0[0]/AU:.4f}, {r0[1]/AU:.4f}, {r0[2]/AU:.4f}] AU")
    print(f"  Velocity: [{v0[0]:.2f}, {v0[1]:.2f}, {v0[2]:.2f}] m/s")
    print(f"  Departure ΔV: {dv1:.2f} m/s")
    
    # Segmented integration with smooth time points
    t_events = sorted([m["t"] for m in maneuvers.values()])
    t_events = [0.0] + t_events + [T_trans]
    
    trajectory_segments = []
    time_segments = []
    maneuver_points = []
    current_state = state0.copy()
    
    for i in range(len(t_events) - 1):
        t_start = t_events[i]
        t_end   = t_events[i + 1]
        
        # Generate smooth time points for continuous curve
        t_eval = np.linspace(t_start, t_end, 100)
        
        # Integrate trajectory segment
        sol = solve_ivp(
            acceleration_sun,
            [t_start, t_end],
            current_state,
            method='DOP853',
            t_eval=t_eval,
            rtol=1e-10,
            atol=1e-10
        )
        
        # Store segment data
        trajectory_segments.append(sol.y.T)
        time_segments.append(sol.t)
        
        # Update state and apply maneuver
        current_state = sol.y[:, -1].copy()
        
        if t_end < T_trans:
            for name, m in maneuvers.items():
                if abs(m["t"] - t_end) < 1.0:
                    r_pre = current_state[:3].copy()
                    v_pre = current_state[3:].copy()
                    
                    maneuver_points.append({
                        "name": name,
                        "t": t_end,
                        "r": r_pre.copy(),
                        "v_before": v_pre.copy(),
                        "dv": m["dv"].copy(),
                        "v_after": v_pre + m["dv"]
                    })
                    
                    print(f"\n>>> Maneuver [{name}] @ t = {t_end/DAY:.2f} days")
                    print(f"    Position: [{r_pre[0]/AU:.4f}, {r_pre[1]/AU:.4f}, {r_pre[2]/AU:.4f}] AU")
                    print(f"    Velocity before: [{v_pre[0]:.2f}, {v_pre[1]:.2f}, {v_pre[2]:.2f}] m/s")
                    print(f"    ΔV: [{m['dv'][0]:.2f}, {m['dv'][1]:.2f}, {m['dv'][2]:.2f}] m/s")
                    print(f"    |ΔV| = {norm(m['dv']):.2f} m/s")
                    
                    current_state[3:] = v_pre + m["dv"]
                    break
    
    # Combine all segments
    trajectory = np.vstack(trajectory_segments)
    time_array = np.hstack(time_segments)
    
    return trajectory, time_array, maneuver_points, r_earth, r_mars, T_trans

# ==================== Main Execution ====================
if __name__ == "__main__":
    # Run simulation
    trajectory, time_array, maneuver_points, r_earth, r_mars, T_trans = simulate_mars_mission()
    
    # ==================== 2D Heliocentric Trajectory Visualization ====================
    fig, ax = plt.subplots(1, 1, figsize=(12, 10))
    
    # Plot Sun
    sun = Circle((0, 0), 0.05, color='orange', label='Sun')
    ax.add_patch(sun)
    
    # Plot orbits
    theta = np.linspace(0, 2*np.pi, 360)
    earth_orbit_x = r_earth / AU * np.cos(theta)
    earth_orbit_y = r_earth / AU * np.sin(theta)
    ax.plot(earth_orbit_x, earth_orbit_y, 'b--', linewidth=0.8, alpha=0.5, label='Earth Orbit (1.0 AU)')
    
    mars_orbit_x = r_mars / AU * np.cos(theta)
    mars_orbit_y = r_mars / AU * np.sin(theta)
    ax.plot(mars_orbit_x, mars_orbit_y, 'r--', linewidth=0.8, alpha=0.5, label='Mars Orbit (1.524 AU)')
    
    # Plot smooth probe trajectory
    traj_x = trajectory[:, 0] / AU
    traj_y = trajectory[:, 1] / AU
    ax.plot(traj_x, traj_y, 'k-', linewidth=1.2, alpha=0.8, label='Probe Heliocentric Trajectory')
    
    # Plot maneuver points
    colors = {'TCM-1': 'green', 'TCM-2': 'cyan', 'DSM': 'magenta', 'TCM-3': 'orange', 'MOI': 'red'}
    for mp in maneuver_points:
        c = colors.get(mp["name"], 'blue')
        ax.plot(mp["r"][0]/AU, mp["r"][1]/AU, 'o', color=c, markersize=9,
                markeredgecolor='black', markeredgewidth=1.2, zorder=5)
        ax.annotate(mp["name"],
                    (mp["r"][0]/AU, mp["r"][1]/AU),
                    xytext=(8, 12), textcoords='offset points',
                    fontsize=9, fontweight='bold', color=c,
                    bbox=dict(boxstyle='round,pad=0.3', facecolor='white', alpha=0.8))
    
    # Plot launch and arrival points
    ax.plot(traj_x[0], traj_y[0], 'go', markersize=11, label='Launch (Earth)')
    ax.plot(traj_x[-1], traj_y[-1], 'ro', markersize=11, label='Arrival (Mars)')
    
    # Plot theoretical Hohmann ellipse
    a_trans_au = (r_earth + r_mars) / (2 * AU)
    c_au = (r_mars - r_earth) / (2 * AU)
    b_au = np.sqrt(a_trans_au**2 - c_au**2)
    center_x = -c_au
    ellipse_theta = np.linspace(0, np.pi, 200)
    ellipse_x = center_x + a_trans_au * np.cos(ellipse_theta)
    ellipse_y = b_au * np.sin(ellipse_theta)
    ax.plot(ellipse_x, ellipse_y, 'gray', linewidth=1.2, linestyle=':', alpha=0.6, label='Theoretical Hohmann Ellipse')
    
    # Plot settings
    ax.set_xlabel('X [AU]', fontsize=13)
    ax.set_ylabel('Y [AU]', fontsize=13)
    ax.set_title('Mars Exploration Heliocentric Transfer Trajectory\n(Tianwen-1 / MSL Reference with Maneuvers)',
                 fontsize=15, fontweight='bold')
    ax.legend(loc='upper right', fontsize=10)
    ax.set_aspect('equal')
    ax.grid(True, alpha=0.3)
    ax.set_xlim(-1.8, 1.8)
    ax.set_ylim(-1.8, 1.8)
    
    plt.tight_layout()
    plt.savefig('mars_mission_trajectory_2d.png', dpi=150)
    plt.show()
    
    # ==================== 3D Trajectory Visualization ====================
    fig3d = plt.figure(figsize=(14, 10))
    ax3d = fig3d.add_subplot(111, projection='3d')
    
    # 3D trajectory
    ax3d.plot(trajectory[:, 0]/AU, trajectory[:, 1]/AU, trajectory[:, 2]/AU,
              'k-', linewidth=1.2, alpha=0.8, label='Probe Trajectory')
    
    # 3D orbits
    ax3d.plot(earth_orbit_x, earth_orbit_y, np.zeros_like(earth_orbit_x),
              'b--', linewidth=0.8, alpha=0.5, label='Earth Orbit')
    ax3d.plot(mars_orbit_x, mars_orbit_y, np.zeros_like(mars_orbit_x),
              'r--', linewidth=0.8, alpha=0.5, label='Mars Orbit')
    
    # 3D maneuver points
    for mp in maneuver_points:
        c = colors.get(mp["name"], 'blue')
        ax3d.scatter(mp["r"][0]/AU, mp["r"][1]/AU, mp["r"][2]/AU,
                    color=c, s=90, edgecolors='black', linewidth=1.2, zorder=5)
        ax3d.text(mp["r"][0]/AU, mp["r"][1]/AU, mp["r"][2]/AU,
                 f'  {mp["name"]}', fontsize=9, fontweight='bold', color=c)
    
    # Sun
    ax3d.scatter(0, 0, 0, color='orange', s=300, label='Sun')
    
    # 3D plot settings
    ax3d.set_xlabel('X [AU]', fontsize=12)
    ax3d.set_ylabel('Y [AU]', fontsize=12)
    ax3d.set_zlabel('Z [AU]', fontsize=12)
    ax3d.set_title('Mars Exploration Heliocentric Transfer Trajectory (3D View)',
                   fontsize=14, fontweight='bold')
    ax3d.legend(loc='upper right', fontsize=9)
    
    max_range = 2.0
    ax3d.set_xlim(-max_range, max_range)
    ax3d.set_ylim(-max_range, max_range)
    ax3d.set_zlim(-0.5, 0.5)
    
    plt.tight_layout()
    plt.savefig('mars_mission_trajectory_3d.png', dpi=150)
    plt.show()
    
    # ==================== Simulation Summary ====================
    print("\n" + "="*60)
    print("SIMULATION SUMMARY")
    print("="*60)
    print(f"Total data points: {len(trajectory)}")
    print(f"Flight duration: {T_trans/DAY:.2f} days (~{T_trans/DAY/30.44:.1f} months)")
    print(f"Total maneuvers: {len(maneuver_points)}")
    total_dv = sum([norm(mp['dv']) for mp in maneuver_points])
    print(f"Total ΔV budget: {total_dv:.2f} m/s")
    
    print("\nManeuver Details:")
    for mp in maneuver_points:
        print(f"  {mp['name']:6s} | t={mp['t']/DAY:7.2f}d | |ΔV|={norm(mp['dv']):8.2f} m/s | "
              f"r=({mp['r'][0]/AU:.3f}, {mp['r'][1]/AU:.3f}, {mp['r'][2]/AU:.3f}) AU")
    print("="*60)
相关推荐
RSTJ_16251 小时前
PYTHON+AI LLM DAY FOURTY-SEVEN
开发语言·人工智能·python·深度学习
爱码小白2 小时前
MySQL运维篇
大数据·数据库·python
wang3zc2 小时前
HTML函数能否用外接显卡坞提升性能_eGPU对HTML函数帮助【汇总】
jvm·数据库·python
2301_781571422 小时前
mysql如何配置自增ID预留_mysql innodb_autoinc_lock_mode参数
jvm·数据库·python
子午2 小时前
校园课堂异常行为检测系统~Python+YOLOV8算法+深度学习+模型训练+人工智能
人工智能·python·yolo
dinglu1030DL2 小时前
CSS如何实现背景颜色的棋盘格分布_利用repeating-gradient
jvm·数据库·python
2zcode2 小时前
滚压表面强化过程中变形诱导位错演化与梯度晶粒细化机理的数值模拟研究
人工智能·python·算法
2303_821287382 小时前
Golang reflect反射怎么用_Golang反射教程【通俗】
jvm·数据库·python