1. 比例导引律基础仿真
任务定义
在二维平面内建立导弹—目标相对运动模型,目标以匀速直线运动飞行,导弹采用纯比例导引律(PPN)控制速度方向。通过数值积分仿真弹道,对比不同导航常数 N 下的拦截效果,观察过载需求与弹道弯曲程度的变化。
数学模型
采用极坐标系描述相对运动。设视线角为 λ,弹目相对距离为 r,导弹速度 Vm,目标速度 Vt。纯比例导引律指令加速度垂直于视线方向:
acmd = N · Vm · λ̇
其中 λ̇ 为视线角速率,N 为导航常数(通常取 3~5)。导弹速度大小恒定,方向由航迹角 γm 控制,其变化率为:
γ̇m = acmd / Vm
仿真中直接对导弹和目标的位置进行积分,每步更新视线角及其速率,计算指令加速度并更新导弹航迹角。
仿真代码
import numpy as np
import matplotlib.pyplot as plt
# 仿真参数
dt = 0.001 # 积分步长 (s)
t_end = 30.0 # 最大仿真时间 (s)
N_list = [2, 3, 4, 5] # 导航常数
# 初始条件
r0 = 5000.0 # 初始距离 (m)
lambda0 = np.deg2rad(30.0) # 初始视线角 (rad)
Vm = 300.0 # 导弹速度 (m/s)
Vt = 150.0 # 目标速度 (m/s)
theta_t = np.deg2rad(180.0) # 目标航向 (rad),朝正西飞行
# 目标初始位置
xt0 = r0 * np.cos(lambda0)
yt0 = r0 * np.sin(lambda0)
# 导弹初始位置(原点)
xm0, ym0 = 0.0, 0.0
# 导弹初始航迹角(指向目标)
gamma_m0 = lambda0
def simulate(N):
xm, ym = xm0, ym0
xt, yt = xt0, yt0
gamma_m = gamma_m0
t = 0.0
hit = False
miss_dist = 0.0
while t < t_end:
# 相对位置
dx = xt - xm
dy = yt - ym
r = np.hypot(dx, dy)
if r < 10.0: # 脱靶量小于10m视为命中
hit = True
miss_dist = r
break
# 视线角与视线角速率
lambda_cur = np.arctan2(dy, dx)
# 目标位置更新(匀速直线)
xt_new = xt0 + Vt * np.cos(theta_t) * (t + dt)
yt_new = yt0 + Vt * np.sin(theta_t) * (t + dt)
lambda_next = np.arctan2(yt_new - ym, xt_new - xm)
lambda_dot = (lambda_next - lambda_cur) / dt
# 比例导引指令
a_cmd = N * Vm * lambda_dot
# 限幅(最大过载 5g)
a_max = 5 * 9.8
a_cmd = np.clip(a_cmd, -a_max, a_max)
# 更新导弹航迹角和位置
gamma_m += (a_cmd / Vm) * dt
xm += Vm * np.cos(gamma_m) * dt
ym += Vm * np.sin(gamma_m) * dt
# 更新目标位置
xt = xt_new
yt = yt_new
t += dt
return xm, ym, xt, yt, t, hit, miss_dist, gamma_m
# 运行仿真
plt.figure(figsize=(10, 8))
colors = ['r', 'g', 'b', 'm']
for i, N in enumerate(N_list):
xm, ym, xt, yt, t_final, hit, miss, gamma_f = simulate(N)
# 重新生成完整弹道用于绘图
xm_arr, ym_arr = [xm0], [ym0]
xm, ym = xm0, ym0
xt, yt = xt0, yt0
gamma_m = gamma_m0
t = 0.0
while t < t_end:
dx = xt - xm
dy = yt - ym
r = np.hypot(dx, dy)
if r < 10.0:
break
lambda_cur = np.arctan2(dy, dx)
xt_new = xt0 + Vt * np.cos(theta_t) * (t + dt)
yt_new = yt0 + Vt * np.sin(theta_t) * (t + dt)
lambda_next = np.arctan2(yt_new - ym, xt_new - xm)
lambda_dot = (lambda_next - lambda_cur) / dt
a_cmd = N * Vm * lambda_dot
a_max = 5 * 9.8
a_cmd = np.clip(a_cmd, -a_max, a_max)
gamma_m += (a_cmd / Vm) * dt
xm += Vm * np.cos(gamma_m) * dt
ym += Vm * np.sin(gamma_m) * dt
xt, yt = xt_new, yt_new
t += dt
xm_arr.append(xm)
ym_arr.append(ym)
plt.plot(xm_arr, ym_arr, colors[i], linewidth=1.5, label=f'N={N}')
print(f'N={N}: 仿真时间={t:.2f}s, 命中={hit}, 最终脱靶量={np.hypot(xt-xm, yt-ym):.2f}m')
# 目标轨迹
t_plot = np.linspace(0, 20, 100)
xt_plot = xt0 + Vt * np.cos(theta_t) * t_plot
yt_plot = yt0 + Vt * np.sin(theta_t) * t_plot
plt.plot(xt_plot, yt_plot, 'k--', linewidth=2, label='目标轨迹')
plt.plot(xm0, ym0, 'ko', markersize=8)
plt.plot(xt0, yt0, 'ks', markersize=8)
plt.xlabel('X (m)')
plt.ylabel('Y (m)')
plt.title('比例导引律弹道仿真')
plt.legend()
plt.grid(True)
plt.axis('equal')
plt.savefig('ppn_trajectories.png', dpi=150)
plt.show()
运行与验证
运行环境需安装 numpy 和 matplotlib。执行代码后,终端输出各导航常数对应的仿真时间与最终脱靶量,同时显示弹道曲线图。
判定标准:
- N=2 时弹道弯曲较大,可能需要更长仿真时间或无法命中(脱靶量较大);
- N=3~5 时弹道逐渐平直,命中时间缩短,最终脱靶量小于 10m;
- 图中可见 N 越大,导弹初始段转弯越平缓,弹道越接近直线。
预期结果分析
导航常数 N 是比例导引律的核心增益。N 较小时(如 N=2),视线角速率反馈弱,导弹需持续大过载转弯,弹道弯曲明显,拦截时间较长;N 增大后,导弹对视线旋转的响应更灵敏,弹道趋于平直,所需过载峰值下降。但 N 过大会导致对视线角速率噪声敏感,工程上通常取 3~5。仿真中可通过修改 N_list 中的数值观察弹道变化趋势,并记录不同 N 值下的命中时间与脱靶量进行定量对比。