ArduPilot 直升机 MATLAB Simulink SITL 仿真模型:Heli 示例的物理建模、初始化与运行全解析
2026/9/15 16:19:03 网站建设 项目流程

ArduPilot 直升机 MATLAB Simulink SITL 仿真模型:Heli 示例的物理建模、初始化与运行全解析

【免费下载链接】ardupilotArduPlane, ArduCopter, ArduRover, ArduSub source项目地址: https://gitcode.com/GitHub_Trending/ar/ardupilot

ArduPilot 在 libraries/SITL/examples/JSON/MATLAB/Heli 目录下提供了一套基于 MATLAB Simulink 的直升机(Helicopter)软件在环(SITL)仿真示例。它通过 JSON SITL 接口与 ArduPilot 自动驾驶仪通信,具备贴近真实的飞行动力学物理,可直接接入 EKF 估计器,并已内置 ArduPilot 参考坐标系的转换逻辑。读完本文,你将掌握该模型的文件构成、heli_init.m初始化脚本中状态矩阵与风场模型的具体含义、Simulink 模型与 SITL 的对接方式,以及如何复用其中的模块构建其他机型的物理后端。

一、模型定位:JSON SITL 生态中的直升机物理后端

ArduPilot 的 SITL 不仅内置了 C++ 实现的直升机模型(SIM_Helicopter.cpp),还通过 JSON 接口开放了外部物理引擎接入能力。JSON 后端允许任意软件(MATLAB、Simulink、pybullet 等)作为"物理后端"替 ArduPilot 计算机体状态,二者通过 UDP 交换数据。

启动 JSON 后端的方式在 JSON readme 中有明确说明:

sim_vehicle.py -v ArduCopter -f octaquad --model JSON:127.0.0.1 --map --console

其中127.0.0.1替换为物理后端实际运行的 IP。物理后端在 UDP 端口 9002 上监听,SITL 每 10 秒会发送一次输出帧用于自动探测。数据流向为:

  • SITL 输出(二进制)uint16 magic = 18458uint16 frame_rateuint32 frame_countuint16 pwm[16],其中 magic 常量在 SIM_JSON.h 中定义,用于协议校验(SIM_JSON_Master.cpp中同样以18458校验接收帧)。若设置SERVO_32_ENABLE = 1,通道数扩展为 32,magic 变为29569
  • 物理后端输入(JSON 文本):包含timestampimu.gyroimu.accel_bodypositionvelocity,以及二选一的attitude(欧拉角)或quaternion(四元数)。

frame_rate表示 SITL 期望的仿真步长,可通过 ArduPilot 的SIM_RATE_HZ参数修改(见 SITL.cpp 的参数注册,以及 SITL.h 中AP_Int16 loop_rate_hz的声明),frame_count用于检测丢帧与重复帧——SITL 重启时计数清零,物理后端据此复位机体状态。

本 Heli 示例正是这一 JSON 生态中的一员:它用 Simulink 搭建直升机气动模型,通过 SITL_connector.m(MATLAB 脚本方式)或 AP_Conector.slx(Simulink 连接器方式)完成与 SITL 的双向通信。

二、模型特性与已知限制

根据 Heli readme 的说明,该模型的核心特性与限制可以总结如下:

特性说明
物理精度采用准确的气动与飞行动力学物理模型,可用于 EKF 估计器闭环验证
参考系处理模型中已内置 ArduPilot 参考坐标系的转换逻辑,无需自行换算
可复用性模型中的模块(Blocks)可移植到其他机型,省去参考系转换工作
地面交互被刻意忽略——起飞后模型无法执行降落流程
前置条件必须先运行heli_init.m完成初始化,模型才能运行

其中"起飞后无法降落"是一个需要特别重视的约束:由于起落架/地面接触力未建模,直升机在飞行结束后的着陆阶段会因失去地面支撑反馈而失去物理真实性,因此该模型适用于悬停、航线飞行、姿态控制等飞行品质验证,不适用于起降流程测试。

三、文件构成与初始化脚本heli_init.m深度解析

该示例目录下包含两个核心文件:

  • heli.slx:直升机 Simulink 模型本身
  • heli_init.m:模型初始化脚本,定义全局状态/输入矩阵、初始条件与风场模型

heli_init.m的第一行addpath(genpath('../../MATLAB'))将上层 MATLAB 目录下的连接与收发工具加入 MATLAB 路径,随后声明两个全局变量:

global A global B A = zeros(6,6); B = zeros(6,7);

3.1 状态矩阵 A:六自由度线性化气动导数

矩阵A描述直升机在配平点附近的线性化状态方程,状态向量为[u v w p q r]'(体轴三个线速度与三个角速度):

Xu=-0.02; Zw=-2.0; Mq=-2.0; Mu=0.001; Yv=-0.4; Lp=-6.0; Nr=-8.0; Lv=-0.02; A = [ Xu 0 0 0 0 0;... 0 Yv 0 0 0 0;... 0 0 Zw 0 0 0;... 0 Lv 0 Lp 0 0;... Mu 0 0 0 Mq 0;... 0 0 0 0 0 Nr];

这些系数是典型的直升机稳定导数:Xu为前向速度阻尼(-0.02,注释为 "barn door" 平板气动近似),Zw为垂向速度阻尼(-2.0),Mq为俯仰阻尼(-2.0),Lp为滚转阻尼(-6.0),Nr为偏航阻尼(-8.0),耦合项MuLv则体现了前向速度对俯仰力矩、侧滑对滚转力矩的交叉影响。注释还给出M=1(质量),说明导数已按单位质量归一。

3.2 输入矩阵 B:操纵通道

矩阵B描述四个操纵输入(lat 横向周期变距、long 纵向周期变距、coll 总距、ped 尾桨脚蹬)对力和力矩的增益:

Zcoll=-60; Mlong = 1; Llat = 1; Nped = 2; B = [ 0 0 0 0;... 0 0 0 0;... 0 0 Zcoll 0;... Llat 0 0 0;... 0 Mlong 0 0;... 0 0 0 Nped ];

总距(coll)产生垂向力增益Zcoll = -60(与机体 z 轴向下定义一致),纵向/横向周期变距分别驱动俯仰、滚转力矩,脚蹬驱动偏航力矩。

3.3 初始条件与坐标系变换

脚本随后定义了飞行初始条件:初始欧拉角Psi = 353*pi/180Roll_ic=0Pit_ic=0,初始线速度ic_u=ic_v=ic_w=0,并通过经典的 ZYX 欧拉角序列构建初始方向余弦矩阵DCM_0(先滚转、再俯仰、后偏航的三次旋转矩阵乘积),供 Simulink 中 Aerospace Blockset 的 6DOF 运动学模块使用:

DCM_0 = [1 0 0; 0 cphi sphi; 0 -sphi cphi] * ... [ctht 0 -stht; 0 1 0; stht 0 ctht] * ... [cpsi spsi 0; -spsi cpsi 0; 0 0 1];

脚本还按力/力矩将AB拆分为A_Fxyz_uvw_pqrA_Mxyz_uvw_pqrB_Fxyz_u_contB_Mxyz_u_cont四个子矩阵,供 Simulink 的力/力矩计算模块分别消费。

3.4 风场与湍流模型

模型内置了随高度变化的风廓线(6 个断点、单调递增的高度表)与湍流/阵风模型:

hw=[0 200 5000 10000 15000 20000]; % 高度断点(ft) Vw=15*[1 1 1 1 1 1]; % 风速幅值(fps) Dir_w=0*[1 1 1 1 1 1]; % 风向(deg) W_GUST=.8; K_gust=0; % 阵风带宽与增益

脚本中还包含舰载起降场景的预留参数(h_deck=21h_islandTh_wind_limit=40),暗示该模型的雏形源自舰载直升机作业仿真需求。最后Ts=2000用于设置仿真运行时间,并打印Init Loaded表示初始化完成。

四、与 SITL 的对接:连接器协议与状态字段

MATLAB 侧提供了两种对接方式,均在 MATLAB readme 中有详细说明。

4.1 脚本方式:SITL_connector

SITL_connector.m 基于 Peter Rydesäter 的 TCP/UDP/IP Toolbox 2.0.6(自带 pnet.c 及预编译 mex 文件)实现 UDP 通信,相比 MATLAB 仪器控制工具箱的官方函数快约 10 倍且免费。其函数签名与用法为:

SITL_connector(state, init_function, physics_function, max_timestep)
  • state:机体的持久物理状态结构体,必须包含以下字段:
state.gyro(roll, pitch, yaw) % rad/s,体轴角速度 state.attitude(roll, pitch, yaw) % rad,欧拉角 state.accel(x, y, z) % m/s^2,体轴加速度 state.velocity(north, east, down) % m/s,地轴速度 state.position(north, east, down) % m,地轴位置

结构体还可附带物理模型所需的任意其他字段(如电机转速、电池状态等)。

  • init_function:初始化函数句柄,在首次运行及 SITL 重启(frame_count回绕)时被调用,用于复位机体状态:
function state = init(state) init_function = @init;
  • physics_function:单步物理推进函数,接收 16 路 PWM 输入(单位 μs,典型范围 1000~2000)并返回更新后的状态:
function state = physics_step(pwm_in, state) physics_function = @physics_step;
  • max_timestep:最大允许步长,实际步长取1/frame_ratemax_timestep的较小值;期望步长由 ArduPilot 的SIM_RATE_HZ参数决定。以 Copter/SIM_multicopter.m 为例,多旋翼示例设置max_timestep = 1/50

连接器内部实现了锁步(lock-step)调度:MATLAB 侧按帧序号严格依次处理 SITL 发来的每个输出帧,检测到控制器复位(帧号回绕)时自动重新调用init_function并打印Controller reset,因此 MATLAB 断点可以正常工作,调试体验与本地脚本一致。每 1000 帧会打印一次实时性能:

xxx.xx fps, xx.xx% of realtime

官方数据表明,该连接方案可达到 >1500 fps 的通信速率;对 400 Hz 的物理步长而言,最大可实现约 4~5 倍实时加速。需要提醒的是,固定翼与地面车辆可承受更大的物理步长、获得更高的加速比,但过大的加速可能使地面站(GCS)跟不上仿真进度。

4.2 Simulink 方式:AP_Conector.slx

AP_Conector.slx 提供 Simulink 输入/输出模块:

  • Receive 模块:接收 SITL 的 16 路 PWM,以 16 元素数组输出,并带有一个 reset 信号——SITL 重启时该信号拉高,可用于将 Simulink 模型复位到初始状态;
  • Output 模块:按上述 state 约定输出机体状态。

与脚本连接器不同,Simulink 的仿真步长不能由 ArduPilot 动态调整,必须在 Simulink 中手工设置(支持变步长)。MATLAB 2018b Legacy目录下还保留了旧版 AP_Conector.slx 供旧版本用户参考;注意现有连接器与示例均基于 MATLAB 2020a 开发。

五、运行步骤与故障排查

完整的运行流程为:

  1. 启动 ArduPilot SITL 并指定 JSON 模型(如sim_vehicle.py -v ArduCopter --model JSON:127.0.0.1);
  2. 在 MATLAB 中进入 Heli 目录,先执行heli_init.m完成全局矩阵、初始条件与风场模型的加载(终端输出Init Loaded即成功);
  3. 打开并运行 heli.slx,或编写调用SITL_connector的入口脚本(参照多旋翼示例的结构);
  4. 若使用脚本连接器且 pnet mex 无法加载,连接器会自动调用mex编译 pnet.c(Windows 下链接ws2_32.lib,Unix/Mac 直接编译),失败时报错提示参考其内部编译说明手动处理;
  5. 观察 SITL 侧输出的 "JSON received" 字段清单(见 JSON readme 的 Debugging 小节),确认timestampgyroaccel_bodypositionattitudevelocity等必选字段均被正确接收;若必选字段缺失,SITL 会停止运行。

常见问题包括:magic值不匹配时连接器打印incorrect magic value(检查 SITL 是否启用了 32 通道输出导致 magic 变为 29569);缓冲区长时间暂停后被填满会触发Buffer reset,属预期行为。

六、参考系约定与扩展复用

整个 MATLAB JSON 示例(libraries/SITL/examples/JSON/MATLAB)遵循同一套状态约定:角速度与加速度为机体坐标系(前右下的 NED 体轴),速度与位置为地球坐标系(北东地 NED)。这也是 ArduPilot JSON 协议 readme 对输入帧字段的硬性要求。

Heli 模型的最大价值在于:其 Simulink 模块已经完成了从"物理方程"到"ArduPilot 参考系"的全部转换,开发者可以直接复用这些模块构建其他机型(如倾转旋翼、共轴双桨等),而无须重新推导坐标变换;同理,Copter/SIM_multicopter.m 中的update dynamics函数实现了"由力和力矩积分出 ArduPilot 所需状态"的通用时间积分方案,也可迁移到任意机型的 MATLAB 后端中,避免重复实现积分器。

物理方程(气动导数/操纵增益) │ heli.slx 中的力与力矩模块 ▼ 机体/地轴状态(gyro, accel, attitude, velocity, position) │ AP_Conector.slx 或 SITL_connector.m ▼ JSON over UDP (端口 9002) ───► ArduPilot SITL (magic=18458, pwm[16])

七、总结

ArduPilot 的 Heli MATLAB Simulink 示例是一个可直接用于直升机飞控算法验证的物理后端:heli_init.m以紧凑的线性化导数组装出直升机动力学,内置高度相关的风场与阵风模型,并通过锁步 UDP 连接器与 ArduPilot SITL 保持严格帧同步。使用时需牢记"必须先行运行heli_init.m"与"模型忽略地面交互、起飞后无法降落"两个前提。对于希望在 MATLAB 生态中为 ArduPilot 搭建自定义飞行器模型的开发者而言,该示例既是一份坐标变换与数据协议的参考实现,也是一个可以按需裁剪复用的模块化起点。

进一步参考:

  • JSON 协议完整说明
  • MATLAB 连接器说明
  • 多旋翼 MATLAB 后端示例
  • C++ 版 JSON 客户端示例

【免费下载链接】ardupilotArduPlane, ArduCopter, ArduRover, ArduSub source项目地址: https://gitcode.com/GitHub_Trending/ar/ardupilot

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询