【RL+空战】学习记录03:基于JSBSim构造简易空空导弹模型,并结合python接口调用测试

JSBSim 导弹气动模型 xml 文件

xml 复制代码
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="http://jsbsim.sourceforge.net/JSBSim.xsl"?>

<!--
    JSBSim 飞行动力学模型配置文件
    模型名称: AIM-9
    用途: 高机动红外制导空空导弹的标准物理基线模型
    特点:
      - 无机翼气动布局 (小展弦比)
      - 高过载、高舵效
      - 火箭发动机推进
    注意: 所用数据并非真实数据,部分数据是接合 DeepSeek 生成的假数据,仅用于模拟学习
-->
<fdm_config name="AIM-9X" version="2.0" release="BETA"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="http://jsbsim.sourceforge.net/JSBSim.xsd">

    <!-- ================= 文件头信息 ================= -->
    <fileheader>
        <!-- UP -->
        <author>昵称已被吞噬QAQ</author>

        <!-- 模型描述,JSBSim GUI / 日志中可见 -->
        <description>AIM-9X Standard Physics Baseline</description>
    </fileheader>

    <!-- ================= 几何与参考面积 ================= -->
    <!--
        metrics 定义的是"等效气动几何参数"
        并不一定是真实几何,而是用于气动力计算的参考量
    -->
    <metrics>
        <!-- 等效参考面积 Sw,用于升力 / 阻力 / 侧力 -->
        <wingarea  unit="FT2"> 0.85 </wingarea>

        <!-- 等效翼展 b,用于滚转 / 偏航力矩 -->
        <wingspan  unit="FT" > 0.92 </wingspan>

        <!-- 等效平均气动弦长 c̄,用于俯仰力矩 -->
        <chord     unit="FT" > 3.0  </chord>

        <!-- 等效水平尾翼面积(主要影响俯仰稳定) -->
        <htailarea unit="FT2"> 0.25 </htailarea>

        <!-- 等效垂直尾翼面积(主要影响偏航稳定) -->
        <vtailarea unit="FT2"> 0.25 </vtailarea>
    </metrics>

    <!-- ================= 质量与惯性 ================= -->
    <!--
        mass_balance 决定刚体动力学行为
        对导弹而言:
          - 转动惯量远比飞机重要
          - Iyy / Izz 决定过载能力和转弯半径
    -->
    <mass_balance>
        <!-- 空重 (不含燃料变化),单位磅 -->
        <emptywt unit="LBS" > 175.0 </emptywt>

        <!--
           转动惯量估算说明:
           - Ixx: 沿弹体轴线(滚转)
                  导弹细长,对滚转不敏感
           - Iyy/Izz: 俯仰 / 偏航惯量
                  决定最大角加速度和瞬态响应
           注意: 这部分是瞎给的,为了平衡一些东西进行了调整
        -->
        <ixx unit="SLUG*FT2"> 1600.0 </ixx>
        <iyy unit="SLUG*FT2"> 1600.0 </iyy>
        <izz unit="SLUG*FT2"> 1600.0 </izz>

        <!--
            质心位置
            这里设在机体系原点
            对导弹建模是常见简化
        -->
        <location name="CG" unit="IN">
            <x> 0 </x>
            <y> 0 </y>
            <z> 0 </z>
        </location>
    </mass_balance>

    <!-- ================= 地面接触模型 ================= -->
    <!--
        ground_reactions 仅用于:
          - 发射前
          - 地面测试
        对空中飞行基本无影响
    -->
    <ground_reactions>
        <contact type="STRUCTURE" name="Belly">

            <!-- 接触点位置(机腹) -->
            <location unit="IN">
                <x>60</x>
                <y>0</y>
                <z>-3</z>
            </location>

            <!-- 导弹无滑跑需求,摩擦设为 0 -->
            <static_friction> 0.0 </static_friction>
            <dynamic_friction> 0.0 </dynamic_friction>

            <!-- 接触弹簧刚度 -->
            <spring_coeff unit="LBS/FT"> 1000.0 </spring_coeff>

            <!-- 接触阻尼,防止数值震荡 -->
            <damping_coeff unit="LBS/FT/SEC"> 100.0 </damping_coeff>
        </contact>
    </ground_reactions>

    <!-- ================= 外部作用力 ================= -->
    <!--
        external_reactions 用于:
          - 火箭发动机
          - 推进器
          - 非气动外力
    -->
    <external_reactions>

        <!-- 火箭推力 -->
        <force name="RocketThrust" frame="BODY">

            <!-- 推力作用点,靠近尾部 -->
            <location unit="IN">
                <x>118</x>
                <y>0</y>
                <z>0</z>
            </location>

            <!-- 推力方向:沿机体 X 正方向 -->
            <direction>
                <x>1</x>
                <y>0</y>
                <z>0</z>
            </direction>

            <!--
                推力时间函数:
                  - 恒定推力
                  - 5 秒后自动归零
            -->
            <function>
                <product>
                    <!-- 推力大小 (lbs) -->
                    <value> 2500.0 </value>

                    <!-- 燃烧时间限制 -->
                    <lt>
                        <property>simulation/sim-time-sec</property>
                        <value> 5.0 </value>
                    </lt>
                </product>
            </function>
        </force>
    </external_reactions>

    <!-- ================= 飞控系统 (FCS) ================= -->
    <!--
        飞控系统职责:
          - 将归一化指令 (-1 ~ 1)
          - 映射为真实舵面偏转角 (rad)
    -->
    <flight_control name="FCS">

        <!-- 俯仰控制通道 -->
        <channel name="Pitch">
            <pure_gain name="Elevator Control">
                <input> fcs/elevator-cmd-norm </input>
                <gain> 0.2 </gain>
                <output> fcs/elevator-pos-rad </output>
            </pure_gain>
        </channel>

        <!-- 滚转控制通道 -->
        <channel name="Roll">
            <pure_gain name="Aileron Control">
                <input> fcs/aileron-cmd-norm </input>
                <gain> 0.01 </gain>
                <output> fcs/left-aileron-pos-rad </output>
            </pure_gain>
        </channel>

        <!-- 偏航控制通道 -->
        <channel name="Yaw">
            <pure_gain name="Rudder Control">
                <input> fcs/rudder-cmd-norm </input>
                <gain> 0.2 </gain>
                <output> fcs/rudder-pos-rad </output>
            </pure_gain>
        </channel>
    </flight_control>

    <!-- ================= 气动力模型 ================= -->
    <!--
        aerodynamics:
          - 所有气动力/力矩均通过 q̄*S*(...) 构造
          - 系数已"物理化",避免纯数值炸飞
    -->
    <aerodynamics>

        <!-- ========== 升力轴 ========== -->
        <axis name="LIFT">

            <!-- α 升力 -->
            <function name="aero/coefficient/CLalpha">
                <product>
                    <property>aero/qbar-psf</property>
                    <property>metrics/Sw-sqft</property>
                    <property>aero/alpha-rad</property>
                    <!-- 高升力斜率,适配高迎角导弹 -->
                    <value> 12.0 </value>
                </product>
            </function>

            <!-- 升降舵升力 -->
            <function name="aero/coefficient/CLde">
                <product>
                    <property>aero/qbar-psf</property>
                    <property>metrics/Sw-sqft</property>
                    <property>fcs/elevator-pos-rad</property>
                    <value> 3.0 </value>
                </product>
            </function>
        </axis>

        <!-- ========== 阻力轴 ========== -->
        <axis name="DRAG">

            <!-- 基础阻力,随马赫数变化 -->
            <function name="aero/coefficient/CD0">
                <product>
                    <property>aero/qbar-psf</property>
                    <property>metrics/Sw-sqft</property>
                    <table>
                        <independentVar lookup="row">velocities/mach</independentVar>
                        <!--
                            体现跨音阻力突增
                        -->
                        <tableData>
                            0.00  0.04
                            0.80  0.04
                            0.95  0.09
                            1.05  0.10
                            1.20  0.08
                            2.00  0.06
                            4.00  0.05
                        </tableData>
                    </table>
                </product>
            </function>

            <!-- 诱导阻力 ~ α² -->
            <function name="aero/coefficient/CDi">
                <product>
                    <property>aero/qbar-psf</property>
                    <property>metrics/Sw-sqft</property>
                    <property>aero/alpha-rad</property>
                    <property>aero/alpha-rad</property>
                    <value> 3.0 </value>
                </product>
            </function>
        </axis>

        <!-- ========== 侧向力 ========== -->
        <axis name="SIDE">

            <!-- 侧滑稳定 -->
            <function name="aero/coefficient/CYbeta">
                <product>
                    <property>aero/qbar-psf</property>
                    <property>metrics/Sw-sqft</property>
                    <property>aero/beta-rad</property>
                    <value> -12.0 </value>
                </product>
            </function>

            <!-- 偏航舵侧力 -->
            <function name="aero/coefficient/CYdr">
                <product>
                    <property>aero/qbar-psf</property>
                    <property>metrics/Sw-sqft</property>
                    <property>fcs/rudder-pos-rad</property>
                    <value> 3.0 </value>
                </product>
            </function>
        </axis>

        <!-- ========== 滚转力矩 ========== -->
        <axis name="ROLL">

            <!-- 滚转阻尼 -->
            <function name="aero/coefficient/Clp">
                <product>
                    <property>aero/qbar-psf</property>
                    <property>metrics/Sw-sqft</property>
                    <property>metrics/bw-ft</property>
                    <property>aero/bi2vel</property>
                    <property>velocities/p-aero-rad_sec</property>
                    <value> -20.0 </value>
                </product>
            </function>

            <!-- 副翼滚转 -->
            <function name="aero/coefficient/Clda">
                <product>
                    <property>aero/qbar-psf</property>
                    <property>metrics/Sw-sqft</property>
                    <property>metrics/bw-ft</property>
                    <property>fcs/left-aileron-pos-rad</property>
                    <value> 10.0 </value>
                </product>
            </function>
        </axis>

        <!-- ========== 俯仰力矩(核心) ========== -->
        <axis name="PITCH">

            <!-- 静稳定 -->
            <function name="aero/coefficient/Cmalpha">
                <product>
                    <property>aero/qbar-psf</property>
                    <property>metrics/Sw-sqft</property>
                    <property>metrics/cbarw-ft</property>
                    <property>aero/alpha-rad</property>
                    <value> -8.0 </value>
                </product>
            </function>

            <!-- 升降舵俯仰 -->
            <function name="aero/coefficient/Cmde">
                <product>
                    <property>aero/qbar-psf</property>
                    <property>metrics/Sw-sqft</property>
                    <property>metrics/cbarw-ft</property>
                    <property>fcs/elevator-pos-rad</property>
                    <value> -15.0 </value>
                </product>
            </function>

            <!-- 俯仰阻尼 -->
            <function name="aero/coefficient/Cmq">
                <product>
                    <property>aero/qbar-psf</property>
                    <property>metrics/Sw-sqft</property>
                    <property>metrics/cbarw-ft</property>
                    <property>aero/ci2vel</property>
                    <property>velocities/q-aero-rad_sec</property>
                    <value> -100.0 </value>
                </product>
            </function>
        </axis>

        <!-- ========== 偏航力矩 ========== -->
        <axis name="YAW">

            <!-- 方向稳定 -->
            <function name="aero/coefficient/Cnbeta">
                <product>
                    <property>aero/qbar-psf</property>
                    <property>metrics/Sw-sqft</property>
                    <property>metrics/bw-ft</property>
                    <property>aero/beta-rad</property>
                    <value> 8.0 </value>
                </product>
            </function>

            <!-- 偏航舵 -->
            <function name="aero/coefficient/Cndr">
                <product>
                    <property>aero/qbar-psf</property>
                    <property>metrics/Sw-sqft</property>
                    <property>metrics/bw-ft</property>
                    <property>fcs/rudder-pos-rad</property>
                    <value> -15.0 </value>
                </product>
            </function>

            <!-- 偏航阻尼 -->
            <function name="aero/coefficient/Cnr">
                <product>
                    <property>aero/qbar-psf</property>
                    <property>metrics/Sw-sqft</property>
                    <property>metrics/bw-ft</property>
                    <property>aero/bi2vel</property>
                    <property>velocities/r-aero-rad_sec</property>
                    <value> -100.0 </value>
                </product>
            </function>
        </axis>

    </aerodynamics>
</fdm_config>

测试用 Python 代码

python 复制代码
import jsbsim
import os
import math
import numpy as np

def run_straight_test():
    root_dir = os.path.abspath(os.getcwd())
    fdm = jsbsim.FGFDMExec(root_dir)
    fdm.set_aircraft_path(os.path.join(root_dir, "aircraft"))

    fdm.load_model("aim9x")

    fdm['ic/lat-gc-deg'] = 37.2
    fdm['ic/long-gc-deg'] = -115.8
    fdm['ic/h-sl-ft'] = 15000.0
    fdm['ic/psi-true-deg'] = 90.0
    fdm['ic/theta-deg'] = 0.0
    
    target_init_vel = 928.0 
    fdm['ic/u-fps'] = target_init_vel
    
    fdm.run_ic()

    # ACMI
    acmi_file = open("straight_test.acmi", "w", encoding="utf-8")
    acmi_file.write("FileType=text/acmi/tacview\n")
    acmi_file.write("FileVersion=2.1\n")
    acmi_file.write("0,ReferenceTime=2023-10-27T12:00:00Z\n")
    acmi_file.write("1,Name=AIM-9X-Basic,Type=Missile,Color=White\n")
    
    dt = 1 / 60
    fdm.set_dt(dt)
    total_times = 180

    print(
        f"{'Time':>5} | {'Mach':>4} | {'Alt':>6} | "
        f"{'Pitch':>6} | {'AoA':>6} | "
        f"{'Nx':>6} | {'Ny':>6} | {'Nz':>6} | {'NT':>6}"
    )
    print("-" * 80)

    for i in range(int(total_times / dt)): 
        t = fdm['simulation/sim-time-sec']

        # === 测试逻辑 ===
        if t < 5.0:
            cmd = [0.0, 0.0, 0.0] # 平飞(发动机点火加速阶段)
        elif t < 10.0:
            cmd = [-0.2, 0.0, 1.0]  # 测试偏航(左)
        elif t < 15.0:
            cmd = [-0.2, 0.0, -1.0] # 测试偏航(右)
        elif t < 24.0:
            cmd = [-0.2, 0.0, 0.0] # 测试俯仰(上)
        elif t < 40.0:
            cmd = [0.2, 0.0, 0.0] # 测试俯仰(下,拉平)
        elif t < 68:
            cmd = [-0.2, 0.0, 1.0] # 测试偏航(左)
        elif t < 78:
            cmd = [-0.2, 0.0, -1.0] # 测试偏航(右)
        elif t < 120:
            cmd = [0.2, 0.0, 0.0] # 测试俯仰(拉平)
        elif t < 150:
            cmd = [1.0, 1.0, -1.0] # 测试滚转
        else:
            cmd = [-1.0, 0.0, 0.0]  # 失速,触底爆炸,boom!!!

        cmd = np.array(cmd)
        fdm['fcs/elevator-cmd-norm'] = cmd[0]
        fdm['fcs/aileron-cmd-norm'] = cmd[1]
        fdm['fcs/rudder-cmd-norm'] = cmd[2]

        fdm.run()
        
        # 记录
        if i % 20 == 0:
            mach = fdm['velocities/mach']
            alt = fdm['position/h-sl-ft']
            pitch = fdm['attitude/theta-deg']
            aoa = fdm['aero/alpha-deg']

            nx = fdm['accelerations/n-pilot-x-norm']
            ny = fdm['accelerations/n-pilot-y-norm']
            nz = fdm['accelerations/n-pilot-z-norm']
            
            n_total = math.sqrt(nx*nx + ny*ny + nz*nz)

            print(
                f"{t:5.1f} | {mach:4.2f} | {alt:6.0f} | "
                f"{pitch:6.1f} | {aoa:6.1f} | "
                f"{nx:6.1f} | {ny:6.1f} | {nz:6.1f} | {n_total:6.1f}"
            )
            
        # ACMI
        m_lon = fdm['position/long-gc-deg']
        m_lat = fdm['position/lat-gc-deg']
        m_alt = fdm['position/h-sl-meters']
        roll = fdm['attitude/phi-deg']
        pitch = fdm['attitude/theta-deg']
        yaw = fdm['attitude/psi-deg']
        
        acmi_file.write(f"#{t:.2f}\n")
        acmi_file.write(f"1,T={m_lon:.7f}|{m_lat:.7f}|{m_alt:.2f}|{roll:.2f}|{pitch:.2f}|{yaw:.2f}\n")

if __name__ == "__main__":
    run_straight_test()

TacView 可视化

相关推荐
曲幽11 分钟前
FastAPI压力测试实战:Locust模拟真实用户并发及优化建议
python·fastapi·web·locust·asyncio·test·uvicorn·workers
Mintopia31 分钟前
OpenClaw 对软件行业产生的影响
人工智能
陈广亮1 小时前
构建具有长期记忆的 AI Agent:从设计模式到生产实践
人工智能
会写代码的柯基犬1 小时前
DeepSeek vs Kimi vs Qwen —— AI 生成俄罗斯方块代码效果横评
人工智能·llm
Mintopia2 小时前
OpenClaw 是什么?为什么节后热度如此之高?
人工智能
爱可生开源社区2 小时前
DBA 的未来?八位行业先锋的年度圆桌讨论
人工智能·dba
叁两5 小时前
用opencode打造全自动公众号写作流水线,AI 代笔太香了!
前端·人工智能·agent
敏编程5 小时前
一天一个Python库:jsonschema - JSON 数据验证利器
python
前端付豪5 小时前
LangChain记忆:通过Memory记住上次的对话细节
人工智能·python·langchain