Pixhawk原生固件PX4之位姿控制算法解读

本文详细解读了PX4中多旋翼无人机的姿态及位置控制机制,包括姿态控制的外环P控制与内环PID控制,以及位置控制的串级PID控制方式。特别关注了旋转向量的求取方法及其在不同旋转角度下的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

欢迎交流~ 个人 Gitter 交流平台,点击直达:Gitter


参考文献:Minimum Snap Trajectory Generation and Control for Quadrotors

PX4中多旋翼无人机的控制分为姿态控制和位置控制两个部分。

大致解读如下

姿态控制 mc_att_control

attc

角度控制(外环 P)

/**
 * Attitude controller.
 * 姿态角控制    外环 P
 * Input: 'vehicle_attitude_setpoint' topics (depending on mode)
 * 输入: 姿态设定值'vehicle_attitude_setpoint'
 * Output: '_rates_sp' vector, '_thrust_sp'
 * 输出: 角速度设定值  '_rates_sp'  油门设定值   '_thrust_sp'
 */

由于偏航轴的响应比横滚俯仰慢,这里采用的是倾转分离的解耦合进行姿态角控制:

先进行一个倾斜(对齐Z轴),然后旋转(对齐X轴),这样以保证能够将当前机体坐标系迅速地旋转到目标坐标系,通过这种方式求解旋转向量(详见《视觉SLAM十四讲》)仅适用于小角度情形;

small

对于旋转角度大于90度的情况( cos(z,Z)<0 )时,直接将目标姿态确定的四元数虚部(旋转瞬轴)作为现在旋转向量。

进而计算角速度设定值

_rates_sp = _params.att_p.emult(e_R);  // P控制

由于偏航响应较慢,加入前馈控制

_rates_sp(2) += _v_att_sp.yaw_sp_move_rate * yaw_w * _params.yaw_ff; // 偏航前馈

其中主要是旋转向量e_R的求取


/* try to move thrust vector shortest way, because yaw response is slower than roll/pitch */
// 以最短距离移动推力向量
math::Vector<3> R_z(R(0, 2), R(1, 2), R(2, 2));
math::Vector<3> R_sp_z(R_sp(0, 2), R_sp(1, 2), R_sp(2, 2));

/* axis and sin(angle) of desired rotation */
// 旋转向量(轴  角)
math::Vector<3> e_R = R.transposed() * (R_z % R_sp_z); // 向量叉乘即误差

/* calculate angle error */
float e_R_z_sin = e_R.length(); // R_z 和 R_sp_z皆为单位向量, |x|=1
float e_R_z_cos = R_z * R_sp_z;

/* calculate weight for yaw control */
float yaw_w = R_sp(2, 2) * R_sp(2, 2);

/* calculate rotation matrix after roll/pitch only rotation */
math::Matrix<3, 3> R_rp;

if (e_R_z_sin > 0.0f) {
    /* get axis-angle representation */
    float e_R_z_angle = atan2f(e_R_z_sin, e_R_z_cos);
    math::Vector<3> e_R_z_axis = e_R / e_R_z_sin;

    e_R = e_R_z_axis * e_R_z_angle; // 旋转向量: 长度为 theta角大小

    /* cross product matrix for e_R_axis */
    math::Matrix<3, 3> e_R_cp;
    e_R_cp.zero();
    e_R_cp(0, 1) = -e_R_z_axis(2);
    e_R_cp(0, 2) = e_R_z_axis(1);
    e_R_cp(1, 0) = e_R_z_axis(2);
    e_R_cp(1, 2) = -e_R_z_axis(0);
    e_R_cp(2, 0) = -e_R_z_axis(1);
    e_R_cp(2, 1) = e_R_z_axis(0);

    /* rotation matrix for roll/pitch only rotation */
    // 罗德里格斯公式
    // R = cos(theta) * I + (1 - cos(theta)) * n * n^T + sin(theta) * skewmatrix(n)
    R_rp = R * (_I + e_R_cp * e_R_z_sin + e_R_cp * e_R_cp * (1.0f - e_R_z_cos));

} else {
    /* zero roll/pitch rotation */
    R_rp = R;
}

////////////// 对齐X轴
/* R_rp and R_sp has the same Z axis, calculate yaw error */
math::Vector<3> R_sp_x(R_sp(0, 0), R_sp(1, 0), R_sp(2, 0));
math::Vector<3> R_rp_x(R_rp(0, 0), R_rp(1, 0), R_rp(2, 0));
e_R(2) = atan2f((R_rp_x % R_sp_x) * R_sp_z, R_rp_x * R_sp_x) * yaw_w; //tan = sin / cos

////////////////////////  大角度旋转 ///////////////////////
if (e_R_z_cos < 0.0f) {
    /* for large thrust vector rotations use another rotation method:
     * calculate angle and axis for R -> R_sp rotation directly */
     // 大的推力向量:直接计算 R->R_sp 的旋转向量(轴、角)
    math::Quaternion q_error;
    // 四元数组成为旋转轴 转过的角度  
    q_error.from_dcm(R.transposed() * R_sp);
    // 四元数实部为 cos(theta)  虚部为 u_x*sin(theta) u_y*sin  u_z*sin
    math::Vector<3> e_R_d = q_error(0) >= 0.0f ? q_error.imag()  * 2.0f : -q_error.imag() * 2.0f;

    /* use fusion of Z axis based rotation and direct rotation */
    // 使用基于Z轴的旋转和直接旋转的融合
    float direct_w = e_R_z_cos * e_R_z_cos * yaw_w;
    e_R = e_R * (1.0f - direct_w) + e_R_d * direct_w;
}

角速度控制(内环PID)

/*
 * Attitude rates controller.
 * 角速度控制环     内环 PID
 * Input: '_rates_sp' vector, '_thrust_sp'
 * 输入: 角速度设定值'_rates_sp'   推力设定值 '_thrust_sp'
 * Output: '_att_control' vector
 * 输出: 姿态控制量  '_att_control'
 */

角速度控制过程比较直观,需要注意的是一个系数tpa(Throttle PID Attenuation,油门PID衰减)

/* throttle pid attenuation factor */
float tpa =  fmaxf(0.0f, fminf(1.0f, 1.0f - _params.tpa_slope * (fabsf(_v_rates_sp.thrust) - _params.tpa_breakpoint)));
// 衰减因子范围在 0 ~ 1 之间

在得到角速度误差后

/* angular rates error */
// 角速度误差
math::Vector<3> rates_err = _rates_sp - rates;

进行角速度PID控制(加前馈)

_att_control = _params.rate_p.emult(rates_err * tpa) + _params.rate_d.emult(_rates_prev - rates) / dt + _rates_int +
               _params.rate_ff.emult(_rates_sp);

这里有几点需要注意的:

  1. 微分控制环节的误差量选取

    标准的PID微分项 D=Kd×(e(k)e(k1)) ,但是这里因为角度的微分就是角速度,而陀螺仪可以直接测出角速度。此处没有将微分项作为偏差的差可能是有此考虑,直接使用 D=kd×ΔGyro/t 可以增强稳定性。

    问:串级PID外环可以只用PI吗?

    答:可以,因为内环相当于外环的D。

  2. TPA的作用

    TPA在此处使用是考虑到了抗积分饱和。

    当系统存在一个方向的误差时,由于积分的累加作用会使控制量一直增大,可能会使控制量达到执行器的执行阈值,如果此时误差的方向发生改变,控制量会逐渐减小,控制量也会退出饱和区,执行器也会在阈值内执行;如果此时误差方向还是没有改变,控制量会继续增大但是执行器会一直保持在阈值,此时控制量就进入了饱和区。进入饱和区越深,退出饱和区时间就会越长,在饱和区时执行器会一直在阈值位置,如果误差发生反向,执行器不会立刻有反应,控制量会慢慢减小,等执行器推出饱和区才会有反应。这样就会使控制的动态响应变差,控制性能变差。
    抗积分饱和算法
    若 u(k-1)>Umax,只累加负的误差;若u(k-1)

位置控制mc_pos_control

位置控制同样采用的是串级PID控制。外环为位置P控制,内环为速度PID控制。

整体控制流程入下。

mc_pos_ctrl

保方向饱和


                                          By Fantasy

<think>好的,我现在需要回答用户关于PX4飞控中超声波模块的使用教程或配置方法的问题。首先,我得回忆一下用户提供的引用内容,看看有没有相关的信息。根据引用[2],用户提到PX4原生代码不支持某些超声波模块,所以他们自己开发了驱动,特别是针对HC-SR04-PWM模块。这可能涉及到硬件连接和软件配置两方面。 首先,硬件连接部分。用户可能需要将超声波模块连接到飞控的某个接口。引用[3]提到机载电脑和飞控的连接,可能涉及USB转TTL模块,但不确定是否适用于超声波模块。通常,超声波模块可能使用PWM或GPIO接口。比如HC-SR04可能需要触发和回波引脚,而PWM版本可能不同。需要确认模块的具体接口类型,然后连接到飞控的相应端口,比如GPIO或PWM输入。 然后是软件配置。引用[2]指出,原生PX4不支持某些模块,所以可能需要自行开发驱动或者修改参数。用户可能需要修改飞控的参数,指定使用的距离传感器类型。例如,设置SENS_EN_HC-SR04为启用,或者调整对应的参数如EKF2_HGT_MODE来选择超声波作为高度源。此外,引用[4]提到了一些参数设置,如MNT相关参数,但那是关于云台的,可能不相关。不过,参数设置的思路可能类似,需要找到与距离传感器相关的参数。 另外,引用[1]提到光流模块的调试,其中涉及distance参数的查看,可能和超声波测距的数据显示有关。用户可能需要通过QGroundControl来查看超声波模块的数据,或者在终端中使用命令检查传感器是否正常工作。例如,使用`distance_sensor status`命令来查看数据流。 还需要考虑多个超声波模块的使用。引用[2]提到,原生代码可能不支持同时连接多个相同模块,因此如果用户需要多方向避障,可能需要修改驱动以支持多个实例,或者使用不同的接口。这可能需要修改UAVCAN或口配置,分配不同的总线地址。 最后,测试和验证部分。用户需要确保超声波数据被飞控正确接收,并用于导航或避障算法。可能需要调整滤波参数,如EKF2的最小距离和最大距离,以确保数据可靠。同时,注意环境因素对超声波的影响,比如噪声和反射面。 总结一下,回答需要涵盖硬件连接步骤、软件参数配置、数据验证方法以及可能的避障应用配置。要确保用户按照步骤操作,并参考PX4官方文档或社区资源,同时提醒可能遇到的常见问题,比如传感器不支持或数据不稳定等。</think>关于PX4飞控中超声波模块的配置与使用,以下是系统化的配置方法及注意事项: --- ### 一、硬件连接 1. **模块选择** - 推荐兼容型号:HC-SR04-PWM(需自行开发驱动)或PX4原生支持的US-100、MB12xx系列[^2] - 确保模块支持3.3V-5V电平,与飞控I/O口匹配 2. **接线方案** - **PWM型超声波模块**(如HC-SR04-PWM): ``` VCC → 5V电源 GND → 飞控GND PWM信号线 → 飞控GPIO/PWM输入引脚(如AUX1-6) ``` - **口型超声波模块**(如US-100): ``` TX → 飞控UART接收端(如TELEM2 RX) RX → 飞控UART发送端(如TELEM2 TX) ``` - 注:若需多模块连接,需分配不同GPIO或UART通道[^2] --- ### 二、软件配置 1. **启用超声波驱动** - 通过QGroundControl修改参数: ``` SENS_EN_HC-SR04 = 1 # 若使用自定义驱动 SENS_EN_US-100 = 1 # 若使用原生支持模块 ``` - 设置高度融合源为超声波: ``` EKF2_HGT_MODE = 2 # 使用距离传感器作为主要高度源 ``` 2. **多模块配置** - 修改`/ROMFS/px4fmu_common/init.d/rcS`文件,为每个模块指定独立总线地址 - 示例代码段: ```bash distance_sensor start -X -t hc-sr04 -r 1 distance_sensor start -Y -t hc-sr04 -r 2 ``` 3. **避障功能激活** - 设置避障触发阈值: ``` CP_DIST = 2.0 # 安全距离(米) CP_GO_NO_DATA = 0 # 无数据时停止飞行 ``` - 通过MAVLink消息接收数据(需机载电脑处理)[^3] --- ### 三、数据验证 1. **实时监测** - 在QGroundControl的**MAVLink控制台**输入: ``` distance_sensor status ``` - 查看`distance`字段是否输出有效值[^1] 2. **日志分析** - 使用Flight Review工具检查`distance_sensor`主题数据流,确认采样率与噪声水平 --- ### 四、常见问题 1. **数据不稳定** - 调整滤波参数: ``` EKF2_MIN_RNG = 0.1 # 最小有效距离 EKF2_MAX_RNG = 4.0 # 最大有效距离 ``` - 避免强光/复杂反射环境 2. **模块未被识别** - 检查飞控固件版本(需≥v1.13) - 确认驱动是否编译进固件(需修改`default.px4board`文件)[^2] ---
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值