1. 导引头视场约束下的比例导引律设计
任务定义
设计一种考虑导引头视场角约束的比例导引律,使导弹在攻击固定或匀速直线运动目标的过程中,目标始终保持在导引头视场角极限以内。要求:当视线角速率趋于零但目标仍处于视场边缘时,导引指令能够主动将目标拉回视场中心区域,避免因视场丢失导致制导中断。
制导律设计
传统比例导引律指令加速度为 a = N·V·λ̇,其中N为导航比,V为导弹速度,λ̇为视线角速率。该律在目标大机动或初始指向偏差较大时,可能导致视线角超出导引头视场极限±θ_max。本案例采用带视场约束项的修正比例导引律:
a_cmd = N·V·λ̇ + K·(θ_max² - λ²)·λ
其中λ为当前视线角,K为视场恢复增益。当|λ|接近θ_max时,第二项产生将视线角拉回零位的附加指令;当|λ|远小于θ_max时,该附加项趋近于零,不影响正常比例导引。该修正项在数学上等价于在视线角偏差上施加非线性比例反馈,保证视场约束始终满足。
仿真代码实现
import numpy as np
from scipy.integrate import solve_ivp
import matplotlib.pyplot as plt
# 参数定义
V_m = 300.0 # 导弹速度 m/s
V_t = 50.0 # 目标速度 m/s
N = 4.0 # 导航比
K = 0.02 # 视场恢复增益
theta_max = np.deg2rad(30.0) # 导引头视场半角 rad
# 初始条件: [x_m, y_m, vx_m, vy_m, x_t, y_t, vx_t, vy_t]
# 导弹初始位置(0,0),速度方向沿x轴;目标初始位置(3000, 800),速度方向沿x轴
init_state = [0.0, 0.0, V_m, 0.0, 3000.0, 800.0, V_t, 0.0]
def guidance_law(t, state):
"""带视场约束的比例导引律"""
x_m, y_m, vx_m, vy_m, x_t, y_t, vx_t, vy_t = state
# 相对位置与速度
rx = x_t - x_m
ry = y_t - y_m
r = np.sqrt(rx**2 + ry**2)
# 视线角
lam = np.arctan2(ry, rx)
# 视线角速率
v_rel_x = vx_t - vx_m
v_rel_y = vy_t - vy_m
lam_dot = (rx*v_rel_y - ry*v_rel_x) / (r**2)
# 导弹速度方向角
theta_m = np.arctan2(vy_m, vx_m)
# 传统比例导引项
a_png = N * V_m * lam_dot
# 视场约束修正项
a_fov = K * (theta_max**2 - lam**2) * lam
# 总指令加速度(垂直于速度方向)
a_cmd = a_png + a_fov
# 状态导数
dx_m = vx_m
dy_m = vy_m
dvx_m = -a_cmd * np.sin(theta_m)
dvy_m = a_cmd * np.cos(theta_m)
dx_t = vx_t
dy_t = vy_t
dvx_t = 0.0
dvy_t = 0.0
return [dx_m, dy_m, dvx_m, dvy_m, dx_t, dy_t, dvx_t, dvy_t]
def impact_condition(t, state):
"""脱靶量判定:相对距离小于10m视为命中"""
x_m, y_m, _, _, x_t, y_t, _, _ = state
return np.sqrt((x_t-x_m)**2 + (y_t-y_m)**2) - 10.0
impact_condition.terminal = True
impact_condition.direction = -1
# 仿真求解
t_span = (0, 30)
sol = solve_ivp(guidance_law, t_span, init_state,
events=impact_condition, max_step=0.01, rtol=1e-8, atol=1e-8)
# 提取结果
t = sol.t
x_m = sol.y[0]; y_m = sol.y[1]
x_t = sol.y[4]; y_t = sol.y[5]
# 计算视线角序列
los_angles = []
for i in range(len(t)):
rx = x_t[i] - x_m[i]
ry = y_t[i] - y_m[i]
los_angles.append(np.arctan2(ry, rx))
los_angles = np.array(los_angles)
# 输出结果
print(f"仿真结束时间: {t[-1]:.2f}s")
print(f"最终脱靶量: {np.sqrt((x_t[-1]-x_m[-1])**2 + (y_t[-1]-y_m[-1])**2):.2f}m")
print(f"最大视线角: {np.max(np.abs(los_angles))*180/np.pi:.2f}°")
print(f"视场约束: ±{np.degrees(theta_max):.0f}°")
print(f"视场约束满足: {'是' if np.max(np.abs(los_angles)) <= theta_max else '否'}")
# 绘制结果
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
ax1.plot(x_m, y_m, 'b-', label='导弹轨迹')
ax1.plot(x_t, y_t, 'r--', label='目标轨迹')
ax1.plot(x_m[0], y_m[0], 'bo', label='导弹起点')
ax1.plot(x_t[0], y_t[0], 'ro', label='目标起点')
ax1.set_xlabel('x (m)'); ax1.set_ylabel('y (m)')
ax1.legend(); ax1.grid(True); ax1.set_title('弹道轨迹')
ax1.axis('equal')
ax2.plot(t, np.degrees(los_angles), 'b-', label='视线角')
ax2.axhline(y=np.degrees(theta_max), color='r', linestyle='--', label='视场边界')
ax2.axhline(y=-np.degrees(theta_max), color='r', linestyle='--')
ax2.set_xlabel('时间 (s)'); ax2.set_ylabel('视线角 (°)')
ax2.legend(); ax2.grid(True); ax2.set_title('视线角随时间变化')
plt.tight_layout()
plt.savefig('fov_guidance_result.png', dpi=150)
plt.show()
运行与验证
运行方式:将上述代码保存为 fov_guidance.py,在已安装 numpy、scipy、matplotlib 的Python环境中执行 python fov_guidance.py。
验证方法:观察终端输出的最大视线角是否小于等于30°视场半角,以及最终脱靶量是否小于10m。同时检查生成的 fov_guidance_result.png 图中视线角曲线是否始终位于±30°边界线以内。
判定标准:若最大视线角不超过θ_max且脱靶量小于10m,则证明该制导律在满足视场约束的前提下完成了精确拦截。可调整初始条件(如增大目标初始横向偏移)测试制导律在更严苛条件下的视场保持能力。