首先说明一下本篇文章是讲解什么的,是制作一个飞行器,但是不算是旋翼类型,也不是固定翼类型,属于,自定义的控制类型,因为需要飞行,所以在px4这个开源平台上会很方便,调用内部的传感器,陀螺仪,气压计,gps,等等都已经集成好了,很方便前期的验证和测试
硬件:cuav x7+
配置:
-
机架配置: ROMFS/px4fmu_common/init.d/airframes/8010_hetero_10pwm
-
混合器: `ROMFS/px4fmu_common/mixers/hetero_10pwm.main.mix`
-
控制模块: src/systemcmds/hetero_passthrough/
1 .确定机架类型和需求,根据项目和自己需求来选择
2.创建机架配置文件,就是配置对应的电机参数,以及飞控外设的各个参数等等,比较多,可以参考其他机架
3 创建混合器文件,混控器就是"控制指令 → 执行器"的分配表
4 配置控制分配参数,每个电机的位置和力矩系数,电机数量
5创建自定义控制模块,存放自己写的逻辑和相关处理
5 配置参数文件,参数表
7编译和测试
1.第一步:配置px4的编译环境
px4在windows的编译环境有点难安装,所以我是使用linux的环境来进行编译,编译烧录会更加友好,使用虚拟机也可以。
bash ./Tools/setup/ubuntu.sh

这是对应的配置环境的脚本,似乎还支持arch-linux和mac和docker的一键配置脚本
我的是ubuntu,所以我使用的是ubuntu的脚本,然后第一步,配置px4的编译环境就ok了
2.第二步:编译对应的开发板
以下是不同飞控开发板的编译和烧录
## 1. 编译命令(针对不同硬件)
make cuav_x7pro_default -j4 # 编译CUAV X7 Pro固件
make px4_fmu-v5_default -j4 # 编译Pixhawk 4 (FMUv5)固件
make px4_fmu-v4_default -j4 # 编译Pixhawk 2.4.8 (FMUv4)固件
make px4_fmu-v3_default -j4 # 编译Pixhawk 1 (FMUv3)固件
make holybro_kakuteh7_default -j4 # 编译Holybro Kakute H7固件
make omnibus_f4sd_default -j4 # 编译Omnibus F4 SD固件
make radiolink_PIX6_default -j4 # 编译Radiolink Pix6固件
make bitcraze_crazyflie_default -j4 # 编译Crazyflie 2.0固件
## 2. 烧录命令
make cuav_x7pro_default upload -j1 # 烧录CUAV X7 Pro固件
make px4_fmu-v5_default upload # 烧录Pixhawk 4固件
make holybro_kakuteh7_default upload # 烧录Holybro Kakute H7固件
make omnibus_f4sd_default upload # 烧录Omnibus F4 SD固件
make radiolink_PIX6_default upload # 烧录Radiolink Pix6固件
make bitcraze_crazyflie_default upload # 烧录Crazyflie 2.0固件
px4支持很多厂家的开发板

3dr,raspberrypi,cuav等等厂家的开发板,例如cuav下面还有对应的开发板固件

比如我使用的是cuav的x7+,固件和x7pro是一样的,编译
make cuav_x7pro_default -j4
就是使用四线程来编译cuav_x7_default ,注意这个编译过程,需要从github上拉取一些模块,需要魔法上网,不然会编译失败。

为什么是编译cuav_x7pro_default,因为是编译这个配置,你也可以写一个自己的对应开发板的配置,比如命名为a.px4board,那么编译就会变成make cuav_x7pro_a -j4
烧录指令:对应开发板对应烧录指令
make cuav_x7pro_default upload -j1
3.第三步,写一个自定义机架
机架ID分配规则
4000-4099: 四旋翼
5000-5099: 六旋翼
6000-6099: 八旋翼
8000-8099: 特殊/异构机架
13000-13999: VTOL机架
50000-59999: 地面车辆

首先找到airframes,这个是存放各种机架的参数,我们随便复制一个机架参数,然后粘贴,然后改名为你对应机架的命名。这个是在qgc上可以选取到你新建的机架,要是你想要在qgc上也添加对应的图表,需要编译qgc,在南京超维的博客上有教程,可以找来试试,我这里是存放在八旋翼下面的一个机型,虽然是在八旋翼的机型下面,但是飞行原理和八旋翼区别很大

#!/bin/sh
#
# @name My Custom Frame
# @type Octorotor x
# @class Copter
# @maintainer Your Name <your.email@example.com>
#
# ====================
# 基础配置
# ====================
# 设置混合器
set MIXER my_custom_mixer
set VEHICLE_TYPE mc
# ====================
# EKF2配置
# ====================
param set-default EKF2_EN 1
param set-default EKF2_MULTI_IMU 1
param set-default SENS_IMU_MODE 1
param set-default EKF2_MAG_TYPE 0
param set-default EKF2_GPS_CTRL 0
# ====================
# 安全配置(根据需求调整)
# ====================
# 解锁安全检查
param set-default COM_ARM_WO_GPS 1
param set-default COM_ARM_MAG_ANG 180
param set-default ARMING_CHECK 0
# 禁用不必要的检查
param set-default CBRK_SUPPLY_CHK 894281
param set-default CBRK_IO_SAFETY 22027
param set-default CBRK_USB_CHK 197848
# ====================
# 控制分配配置
# ====================
# 电机和舵机数量
param set-default CA_AIRFRAME 15
param set-default CA_ROTOR_COUNT 8
param set-default CA_SV_COUNT 2
# 电机1-8配置(根据实际布局调整)
# 格式:CA_ROTOR{编号}_PX, _PY, _KZ, _KM
# PX, PY: 电机位置(米)
# KZ: 垂直力系数
# KM: 力矩系数
param set-default CA_ROTOR0_PX 0.5
param set-default CA_ROTOR0_PY 0.5
param set-default CA_ROTOR0_KZ 1.0
param set-default CA_ROTOR0_KM 0.0
# ... 配置其他电机
# 舵机配置
param set-default CA_SV0_PX 0.0
param set-default CA_SV0_PY 0.0
param set-default CA_SV0_KM 0.0
param set-default CA_SV0_ANGLE 180.0
# ====================
# PWM输出配置
# ====================
# 主PWM通道
param set-default PWM_MAIN_MIN 1000
param set-default PWM_MAIN_MAX 2000
param set-default PWM_MAIN_DISARM 900
param set-default PWM_MAIN_FAIL 900
# 扩展通道(舵机)
param set-default PWM_MAIN_MIN11 500
param set-default PWM_MAIN_MAX11 2500
param set-default PWM_MAIN_TRIM11 1500
param set-default PWM_MAIN_FUNCTION11 41
param set-default PWM_MAIN_MIN12 500
param set-default PWM_MAIN_MAX12 2500
param set-default PWM_MAIN_TRIM12 1500
param set-default PWM_MAIN_FUNCTION12 44
# ====================
# 控制参数
# ====================
# 姿态控制参数
param set-default MC_ROLLRATE_MAX 180
param set-default MC_PITCHRATE_MAX 180
param set-default MC_YAWRATE_MAX 90
# 油门参数
param set-default MPC_THR_HOVER 0.5
param set-default MPC_THR_MAX 0.9
param set-default MPC_THR_MIN 0.0
# ====================
# 启动自定义模块
# ====================
# 启动自定义控制模块
# my_custom_controller start
# ====================
# 设置混合器
# ====================
set MIXER my_custom_mixer
我们需要在这个新建的机架里面设置对应的参数,这个参数就是和你在qgc上面那个参数列表设置参数是一样的,一开始可以参考其他机架设置参数
第四步:新建一个文件给我们自己的机架存放逻辑以及相关处理
模块目录结构
src/systemcmds/my_custom_controller/
├── CMakeLists.txt
├── my_custom_controller.cpp
├── my_custom_controller_params.yaml
├── Control.hpp
├── Control.cpp
└── README.md
然后我们就可以在systemcmds这个文件下面新建一个hetero_passthrough文件夹,这个文件夹

第五步:新建文件之后,第一步就是编写cmakelist

px4_add_module( //添加px4的模块,也就是把我们的代码添加到模块去
MODULE systemcmds__hetero_passthrough //后面是模块的名字,前面说明是哪个板块的模块
MAIN hetero_passthrough //主模块
SRCS //对应依赖的代码文件
hetero_passthrough.cpp //逻辑代码
Control.cpp
vector_angles.cpp
EvPositionManager.cpp
OpticalFlowProcessor.cpp
MODULE_CONFIG //模块的配置文件,可以设值配置文件,然后可以在qgc的参数设置的位置进行调整
hetero_passthrough_params.yaml
DEPENDS
px4_work_queue //加入到px4的线程
)
第六步:编写kconfig
编写这个kconfig的作用是用来给px4,判断使用编译这个模块,要是不编译就是default,给n,然后,就不会把这些代码编译到飞控

第七步:编写混控器
编写这个混空器,是来判断你的控制是怎么控制的,是使用矩阵控制还是什么,我在这里是写成使用遥控器直接控制,跳过矩阵分配

-`R`: 旋转翼混合器
-`16x`: 16个通道
`10000 10000 10000 0`: 直通系数(roll, pitch, yaw, thrust)
然后在机架参数那设置

8.编写参数配置文件(可选,方便调试)
`src/systemcmds/my_custom_controller/my_custom_controller_params.yaml`

编写参数配置文件,可以实现,在qgc上实现调试
9.常用指令
# 清理旧构建
make clean
# 编译固件
make px4_fmu-v5_default
# 或单独编译模块
make px4_fmu-v5_default systemcmds__my_custom_controller
# 使用PX4上传工具
make px4_fmu-v5_default upload
10. PX4常见数据名称、变量和概念解释
1. 传感器数据
1.1 光流(Optical Flow)
消息主题:`vehicle_optical_flow`
// 在hetero_passthrough.cpp中的使用
#include <uORB/topics/vehicle_optical_flow.h>
// 订阅光流数据
uORB::Subscription _optical_flow_sub{ORB_ID(vehicle_optical_flow)};
// 关键变量
vehicle_optical_flow_s flow;
flow.pixel_flow[0]; // X方向像素流(弧度/秒)
flow.pixel_flow[1]; // Y方向像素流(弧度/秒)
flow.integration_timespan; // 积分时间(微秒)
flow.quality; // 数据质量(0-100%)
flow.max_flow_rate; // 最大流率
flow.min_ground_distance;// 最小地面距离
flow.max_ground_distance;// 最大地面距离
# 光流参数
param show EKF2_OPTICAL_CTRL # 光流控制使能
param show EKF2_OF_POS_X # 光流X位置
param show EKF2_OF_POS_Y # 光流Y位置
param show EKF2_OF_QMIN # 最小质量阈值
1.2 GPS数据
消息主题:`vehicle_gps_position`
#include <uORB/topics/vehicle_gps_position.h>
// 订阅GPS数据
uORB::Subscription _gps_sub{ORB_ID(vehicle_gps_position)};
// 关键变量
vehicle_gps_position_s gps;
gps.lat; // 纬度(度 * 1e7)
gps.lon; // 经度(度 * 1e7)
gps.alt; // 海拔高度(毫米)
gps.alt_ellipsoid; // 椭球高度(毫米)
gps.vel_n_m_s; // 北向速度(米/秒)
gps.vel_e_m_s; // 东向速度(米/秒)
gps.vel_d_m_s; // 地向速度(米/秒)
gps.fix_type; // 定位类型(0-5)
gps.satellites_used; // 使用卫星数
gps.hdop; // 水平精度因子
gps.vdop; // 垂直精度因子
# GPS参数
param show EKF2_GPS_CTRL # GPS控制使能
param show EKF2_GPS_P_NOISE # GPS位置噪声
param show EKF2_GPS_V_NOISE # GPS速度噪声
param show COM_ARM_WO_GPS # 无GPS解锁
1.3 本地位置数据(EKF2输出)
消息主题:`vehicle_local_position`
#include <uORB/topics/vehicle_local_position.h>
// 在hetero_passthrough中的使用
uORB::Subscription _vehicle_local_position_sub{ORB_ID(vehicle_local_position)};
// 关键变量
vehicle_local_position_s local_pos;
local_pos.x; // X位置(米,NED坐标系)
local_pos.y; // Y位置(米,NED坐标系)
local_pos.z; // Z位置(米,NED坐标系,向下为正)
local_pos.vx; // X速度(米/秒)
local_pos.vy; // Y速度(米/秒)
local_pos.vz; // Z速度(米/秒)
local_pos.ax; // X加速度(米/秒²)
local_pos.ay; // Y加速度(米/秒²)
local_pos.az; // Z加速度(米/秒²)
// 有效性标志
local_pos.xy_valid; // XY位置有效
local_pos.z_valid; // Z位置有效
local_pos.v_xy_valid; // XY速度有效
local_pos.v_z_valid; // Z速度有效
local_pos.xy_global; // XY是全局坐标(GPS)
local_pos.z_global; // Z是全局坐标
2. 控制数据
2.1 遥控器输入
消息主题:`manual_control_setpoint`
#include <uORB/topics/manual_control_setpoint.h>
// 在hetero_passthrough中的使用
uORB::Subscription _manual_sub{ORB_ID(manual_control_setpoint)};
// 关键变量
manual_control_setpoint_s manual;
manual.throttle; // 油门(-1.0到1.0)
manual.roll; // 横滚(-1.0到1.0)
manual.pitch; // 俯仰(-1.0到1.0)
manual.yaw; // 偏航(-1.0到1.0)
manual.timestamp_sample;// 采样时间戳
2.2 电机控制输出
消息主题:`actuator_motors`
#include <uORB/topics/actuator_motors.h>
// 在hetero_passthrough中的使用
uORB::Publication<actuator_motors_s> _motors_pub{ORB_ID(actuator_motors)};
// 关键变量
actuator_motors_s motors;
motors.timestamp; // 时间戳
motors.timestamp_sample;// 采样时间戳
motors.control[0]; // 电机1控制量(0.0-1.0)
motors.control[1]; // 电机2控制量
// ... 最多16个电机
2.3控制舵机
消息主题:`actuator_outputs`
#include <uORB/topics/actuator_outputs.h>
// 用于舵机输出
actuator_outputs_s outputs;
outputs.output[0]; // 输出通道1(-1.0到1.0)
outputs.output[1]; // 输出通道2
// ... 最多16个输出
3. 状态数据
3.1 飞行器状态
消息主题:`vehicle_status`
#include <uORB/topics/vehicle_status.h>
// 在hetero_passthrough中的使用
uORB::Subscription _vehicle_status_sub{ORB_ID(vehicle_status)};
// 关键变量
vehicle_status_s vstatus;
vstatus.arming_state; // 解锁状态
vstatus.nav_state; // 导航状态
vstatus.system_type; // 系统类型
vstatus.system_id; // 系统ID
vstatus.component_id; // 组件ID
vstatus.vehicle_type; // 车辆类型
解锁状态常量
// 在vehicle_status.h中定义
vehicle_status_s::ARMING_STATE_INIT
vehicle_status_s::ARMING_STATE_STANDBY
vehicle_status_s::ARMING_STATE_ARMED
vehicle_status_s::ARMING_STATE_STANDBY_ERROR
vehicle_status_s::ARMING_STATE_SHUTDOWN
3.2 姿态数据
消息主题:`vehicle_attitude`
#include <uORB/topics/vehicle_attitude.h>
// 在hetero_passthrough中的使用
uORB::Subscription _vehicle_attitude_sub{ORB_ID(vehicle_attitude)};
// 关键变量
vehicle_attitude_s attitude;
attitude.q[0]; // 四元数w
attitude.q[1]; // 四元数x
attitude.q[2]; // 四元数y
attitude.q[3]; // 四元数z
attitude.timestamp; // 时间戳
// 转换为欧拉角
matrix::Eulerf euler_angles(matrix::Quatf(attitude.q));
float roll = euler_angles.phi(); // 横滚角(弧度)
float pitch = euler_angles.theta(); // 俯仰角(弧度)
float yaw = euler_angles.psi(); // 偏航角(弧度)
3.3 角速度数据
消息主题:`vehicle_angular_velocity`
#include <uORB/topics/vehicle_angular_velocity.h>
// 在hetero_passthrough中的使用
uORB::Subscription _vehicle_angular_velocity_sub{ORB_ID(vehicle_angular_velocity)};
// 关键变量
vehicle_angular_velocity_s angular_velocity;
angular_velocity.xyz[0]; // X角速度(横滚,弧度/秒)
angular_velocity.xyz[1]; // Y角速度(俯仰,弧度/秒)
angular_velocity.xyz[2]; // Z角速度(偏航,弧度/秒)
常见参数前缀
# 控制参数
MC_ # 多旋翼控制参数
FW_ # 固定翼控制参数
VT_ # VTOL控制参数
R_ # 地面车辆控制参数
# 估计器参数
EKF2_ # EKF2估计器参数
LPE_ # 本地位置估计器参数
# 传感器参数
SENS_ # 传感器参数
CAL_ # 校准参数
# 系统参数
SYS_ # 系统参数
COM_ # 通信/命令参数
NAV_ # 导航参数
# 安全参数
CBRK_ # 安全检查绕过
5. 坐标系和单位
### 5.1 坐标系
- __NED坐标系__:北-东-地(North-East-Down)
- X: 北向(正北)
- Y: 东向(正东)
- Z: 地向(正下)
- __机体坐标系__:前-右-下(FRD)
- X: 前向(机头方向)
- Y: 右向(机翼右侧)
- Z: 下向(机身下方)
### 5.2 角度单位
- __弧度(rad)__:内部计算使用
- __度(°)__:显示和参数使用
- 转换:`度 = 弧度 × 180 / π`
### 5.3 时间单位
- __秒(s)__:控制周期
- __毫秒(ms)__:`1ms = 0.001s`
- __微秒(μs)__:`1μs = 0.000001s`
- __纳秒(ns)__:`1ns = 0.000000001s`
6. 常见缩写和术语
6.1 传感器相关
-
IMU: 惯性测量单元(Inertial Measurement Unit)
-
EKF: 扩展卡尔曼滤波器(Extended Kalman Filter)
-
EKF2: PX4的第二代EKF
-
GPS: 全球定位系统(Global Positioning System)
-
RTK: 实时动态定位(Real-Time Kinematic)
-
UWB: 超宽带(Ultra-Wideband)
-
LIDAR: 激光雷达(Light Detection and Ranging)
6.2 控制相关
-
PID: 比例-积分-微分控制
-
LQR: 线性二次调节器
-
MPC: 模型预测控制
-
CA: 控制分配(Control Allocation)
-
MIXER: 混控器
6.3 系统相关
-
uORB: 微对象请求代理(micro Object Request Broker)
-
MAVLink: 微型飞行器链接协议
-
QGC: QGroundControl地面站
-
SITL: 软件在环仿真(Software-In-The-Loop)
-
HITL: 硬件在环仿真(Hardware-In-The-Loop)