PX4_mixer通道分配的深度解析

2023-05-16

        上文写了PIXHAWK的姿态控制算法,该文主要对姿态控制输出到电机输出的通道分配环节进行深入解析。PX4的通道分配环节查看mixer_multirotor.cpp(对应多旋翼的通道分配)。

        PX4的mixer策略:

/* Summary of mixing strategy:
1) mix roll, pitch and thrust without yaw.
2) if some outputs violate range [0,1] then try to shift all outputs to minimize violation ->
increase or decrease total thrust (boost). The total increase or decrease of thrust is limited
(max_thrust_diff). If after the shift some outputs still violate the bounds then scale roll & pitch.
In case there is violation at the lower and upper bound then try to shift such that violation is equal
on both sides.
3) mix in yaw and scale if it leads to limit violation.
4) scale all outputs to range [idle_speed,1]           
 */

        先融合横滚、俯仰、油门值,然后依据得到的结果对其横滚、俯仰进行比率钳位,最后融合航向值,对航向进行比率钳位,最后对整体做限幅和怠速处理。(从处理的顺序可以看出横滚/俯仰的响应优先级大于航向)

其中比率钳位的意思可看下图讲解:

这里思考一下,是比例钳位好?还是整体都减去四个电机的最大值越界的部分好呢?(有待后续进一步实验验证)

        实际代码执行细节会相对更加丰富一些,接下来讲解一下代码结构。

        首先从姿态控制器输出获得roll,pitch, yaw, thrust:

float roll    = constrain(get_control(0, 0) * _roll_scale, -1.0f, 1.0f);
float pitch   = constrain(get_control(0, 1) * _pitch_scale, -1.0f, 1.0f);
float yaw     = constrain(get_control(0, 2) * _yaw_scale, -1.0f, 1.0f);
float thrust  = constrain(get_control(0, 3), 0.0f, 1.0f);

然后在忽略yaw的情况下,计算融合后结果的最大最小值

        /* perform initial mix pass yielding unbounded outputs, ignore yaw */

具体代码:

for (unsigned i = 0; i < _rotor_count; i++) {
    float out = roll * _rotors[i].roll_scale +pitch * _rotors[i].pitch_scale +thrust;
    out *= _rotors[i].out_scale;
    /* calculate min and max output values */
    if (out < min_out) {
    min_out = out;
    }
    if (out > max_out) {
    max_out = out;
    }
    outputs[i] = out;
}

其中_rotors[i].roll_scale,_rotors[i].pitch_scale等参数可见"mixer_multirotor.generated.h"中相关定义,如下:

const MultirotorMixer::Rotor _config_quad_x[] = {
    { -0.707107,  0.707107,  1.000000,  1.000000 },    
    //四行对应四个电机,第一行中的四个参数分别对应roll/pitch/yaw/throw的权重系数。
    {  0.707107, -0.707107,  1.000000,  1.000000 },
    {  0.707107,  0.707107, -1.000000,  1.000000 },
    { -0.707107, -0.707107, -1.000000,  1.000000 },
};

对计算得到的最大最小值进行判断输出是否会饱和(不在[0,1]区间内则饱和)对应代码见下文,若饱和则对相应寄存器状态进行处理,该处理结果将会作为角速度环是否积分的一个标志(if (_thrust_sp > MIN_TAKEOFF_THRUST && !_motor_limits.lower_limit && !_motor_limits.upper_limit )其中_motor_limits.lower_limit与_motor_limits.upper_limit 便是对应其标志)。

if (min_out < 0.0f) {
    if (status_reg != NULL) {
      (*status_reg) |= PX4IO_P_STATUS_MIXER_LOWER_LIMIT;
    }
}
if (max_out > 1.0f) {
    if (status_reg != NULL) {
      (*status_reg) |= PX4IO_P_STATUS_MIXER_UPPER_LIMIT;
    }
}

接着根据得到的最大最小值,进行了一系列的分类处理求得boost 和roll_pitch_scale(两变量对应下文解释)

float boost = 0.0f; // value added to demanded thrust (can also be negative)

float roll_pitch_scale = 1.0f; // scale for demanded roll and pitch

其中具体分了一下5种情况:

 if (min_out < 0.0f && max_out < 1.0f && -min_out <= 1.0f - max_out) {
    float max_thrust_diff = thrust * thrust_increase_factor - thrust;
    if (max_thrust_diff >= -min_out) {
        boost = -min_out;    //对应out [0,max-min]
    } else {
        boost = max_thrust_diff;
        roll_pitch_scale = (thrust + boost) / (thrust - min_out);
    }
} else if (max_out > 1.0f && min_out > 0.0f && min_out >= max_out - 1.0f) {
    float max_thrust_diff = thrust - thrust_decrease_factor * thrust;
    if (max_thrust_diff >= max_out - 1.0f) {
        boost = -(max_out - 1.0f);     //对应out [1-max+min,1]
    } else {
        boost = -max_thrust_diff;
        roll_pitch_scale = (1 - (thrust + boost)) / (max_out - thrust);   
    }
} else if (min_out < 0.0f && max_out < 1.0f && -min_out > 1.0f - max_out) {
    float max_thrust_diff = thrust * thrust_increase_factor - thrust;
    boost = constrain(-min_out - (1.0f - max_out) / 2.0f, 0.0f, max_thrust_diff);
    roll_pitch_scale = (thrust + boost) / (thrust - min_out);    //对应out [0,2max-1]

} else if (max_out > 1.0f && min_out > 0.0f && min_out < max_out - 1.0f) {
    float max_thrust_diff = thrust - thrust_decrease_factor * thrust;
    boost = constrain(-(max_out - 1.0f - min_out) / 2.0f, -max_thrust_diff, 0.0f);
    roll_pitch_scale = (1 - (thrust + boost)) / (max_out - thrust); //对应out [2min,1]
} else if (min_out < 0.0f && max_out > 1.0f) {
    boost = constrain(-(max_out - 1.0f + min_out) / 2.0f,
        thrust_decrease_factor * thrust - thrust,
            thrust_increase_factor * thrust - thrust);
    roll_pitch_scale = (thrust + boost) / (thrust - min_out);    //对应out [0,1]
}

        即当outputs饱和时,会将roll_pitch_scale 缩小(<1),同时根据min_out 和max_out 来决定boost 的大小,其中使用的额相关参数:

// thrust boost parameters
float thrust_increase_factor = 1.5f;
float thrust_decrease_factor = 0.6f;

接着重新将thrust,boost, 变比例后的roll/pitch和yaw进行融合:

// mix again but now with thrust boost, scale roll/pitch and also add yaw

float out = (roll * _rotors[i].roll_scale + pitch * _rotors[i].pitch_scale) 
                * roll_pitch_scale + yaw * _rotors[i].yaw_scale + thrust + boost;

然后根据输出是否饱和,对航向进行比率钳位,使其输出在[0,1]范围内:

// scale yaw if it violates limits. inform about yaw limit reached

if (out < 0.0f) {
    yaw = -((roll * _rotors[i].roll_scale + pitch * _rotors[i].pitch_scale) 
                *roll_pitch_scale + thrust + boost) / _rotors[i].yaw_scale;
        //yaw值变化,从而整个yaw作用内容进行比率钳位
    if (status_reg != NULL) {
        (*status_reg) |= PX4IO_P_STATUS_MIXER_YAW_LIMIT;
    }
} else if (out > 1.0f) {
    // allow to reduce thrust to get some yaw response
    //(这里减小油门应该是为下一循环的yaw预留响应)
    float thrust_reduction = fminf(0.15f, out - 1.0f);
    thrust -= thrust_reduction;
    yaw = (1.0f - ((roll * _rotors[i].roll_scale + pitch * _rotors[i].pitch_scale) 
            * roll_pitch_scale + thrust + boost)) / _rotors[i].yaw_scale;
        //(感觉这里yaw变成0了)
    if (status_reg != NULL) {
        (*status_reg) |= PX4IO_P_STATUS_MIXER_YAW_LIMIT;
    }

}

同时PX4IO_P_STATUS_MIXER_YAW_LIMIT也会对角速度环的积分进行影响。

        最后加上比率钳位后的航向值,将最后输出限幅到[idle_speed,1]。

/* add yaw and scale outputs to range idle_speed...1 */
for (unsigned i = 0; i < _rotor_count; i++) {
    outputs[i] = (roll * _rotors[i].roll_scale +pitch * _rotors[i].pitch_scale) 
* roll_pitch_scale +yaw * _rotors[i].yaw_scale +thrust + boost;
    outputs[i] = constrain(_idle_speed 
                    + (outputs[i] * (1.0f - _idle_speed)), _idle_speed, 1.0f);
}

        如此便得到了对应驱动电调的输入值,另外电调的PWM频率设定值需要快于角速度输出的频率或与其保持同步,推荐设置400Hz,这样响应跟得上计算输出值,响应更加及时。至此,PX4的总体控制框架总结完毕,PX4的精华当然不止于此,这只是冰山一角,学习PX4代码,建议先把操作系统(UCOS、FreeRTOS之类)学习一下,这样更加系统的了解整个程序的运行机制。

推荐扫码享购最速飞控学习视频

欢迎加入欣飞鸽总动员一起交流讨论,qq群聊号码:879466897

更多无人机知识分享,请关注微信公众号:欣飞鸽
开心飞翔,灵动如鸽。愿与无人机爱好者,共创一片蓝天梦!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PX4_mixer通道分配的深度解析 的相关文章

  • PX4 Offboard Control with MAVROS--Takeoff(一键起飞)

    警告 xff1a 请先在仿真环境下进行测试 xff0c 能达到预期效果后在进行实际飞行测试 xff0c 以免发生意外 本篇文章只是用作学习交流 xff0c 实际飞行时如出现意外情况作者不予以负责 所需材料 1 PIXhawk或者Pixrac
  • 编译PX4固件

    PX4编译 文章目录 PX4编译疑难杂症bug1bug2catkin build isolated 官方脚本Step1Step2 安装常用依赖Step3 创建并运行脚本Step4 补全代码子模块Step5 验证仿真 官方offboard 例
  • PX4 GAZEBO无人机添加相机并进行图像识别

    PX4 GAZEBO无人机添加摄像头并进行图像识别 在之前完成了ROS的安装和PX4的安装 xff0c 并可以通过roslaunch启动软件仿真 接下来为无人及添加相机 xff0c 并将图像用python函数读取 xff0c 用于后续操作
  • PX4飞控之PWM输出控制

    PX4飞控之PWM输出控制 多旋翼电调如好盈XRotor xff0c DJI通用电调等都支持PWM信号来传输控制信号 常用的400Hz电调信号对应周期2500us xff0c 一般使用高电平时间1000us 2000us为有效信号区间 xf
  • 初学PX4之环境搭建

    文章转自 xff1a http www jianshu com p 36dac548106b 前言 前段时间linux崩溃了 xff0c 桌面进去后只有背景 xff0c 折腾好久没搞定 xff0c 为了节省时间索性重装了系统 xff0c 同
  • PX4 -- EKF2

    文章目录 EKF2参数高度估计Range Finder滤波 单变量更新单变量更新对多变量的影响 EKF2 参数 EKF2 中有一类 GATE 参数 当测量值在 VAR GATE 范围内才会更新值 高度估计 四种高度控制方法 xff1a 气压
  • PX4模块设计之一:SITL & HITL模拟框架

    PX4模块设计之一 xff1a SITL amp HITL模拟框架 1 模拟框架1 1 SITL模拟框架1 2 HITL模拟框架 2 模拟器类型3 MAVLink API4 总结 基于PX4开源软件框架简明简介的框架设计 xff0c 逐步分
  • PX4模块设计之三十:Hysteresis类

    PX4模块设计之三十 xff1a Hysteresis类 1 Hysteresis类简介2 Hysteresis类成员变量介绍3 Hysteresis类迟滞逻辑4 Hysteresis类重要方法4 1 Hysteresis bool ini
  • PX4模块设计之三十一:ManualControl模块

    PX4模块设计之三十一 xff1a ManualControl模块 1 ManualControl模块简介2 模块入口函数2 1 主入口manual control main2 2 自定义子命令custom command 3 Manual
  • PX4模块设计之三十三:Sensors模块

    PX4模块设计之三十三 xff1a Sensors模块 1 Sensors模块简介2 模块入口函数2 1 主入口sensors main2 2 自定义子命令custom command2 3 模块状态print status 重载 3 Se
  • PX4模块设计之三十六:MulticopterPositionControl模块

    PX4模块设计之三十六 xff1a MulticopterPositionControl模块 1 MulticopterPositionControl模块简介2 模块入口函数2 1 主入口mc pos control main2 2 自定义
  • PX4模块设计之四十三:icm20689模块

    PX4模块设计之四十三 xff1a icm20689模块 1 icm20689模块简介2 模块入口函数2 1 主入口icm20689 main2 2 自定义子命令custom command2 3 模块状态print status 重载 3
  • PX4-4-任务调度

    PX4所有的功能都封装在独立的模块中 xff0c uORB是任务间数据交互和同步的工具 xff0c 而管理和调度每个任务 xff0c PX4也提供了一套很好的机制 xff0c 这一篇我们分享PX4的任务调度机制 我们以PX4 1 11 3版
  • px4无人机常识介绍(固件,px4等)

    专业名词解释 aircraft 任何可以飞或者可以携带物品还是搭载旅客的飞行器统称为飞机 航空器 uav 无人驾驶飞机 vehicle 飞行器 airplane plane aero plane 有机翼和一个或多个引擎的飞行器统称为飞机 D
  • PX4软件在环仿真注意点

    注 xff1a 最新内容参考PX4 user guide 点击此处 PX4下载指定版本代码和刷固件的三种方式 点击此处 PX4sitl固件编译方法 点击此处 PX4开发指南 点击此处 PX4无人机仿真 Gazebo 点击此处 px4仿真 知
  • PX4通过参数脚本给飞控导入参数

    PX4通过参数脚本给飞控导入参数 先找一架正常能飞的无人机连接地面站 在参数页面右上角点击工具 gt 保存到文件 保存的时候文件名注明参数的相关信息 然后将需要加载参数的无人机连接至地面站 xff0c 注意需要加载参数的无人机必须和保存的参
  • 飞行姿态解算(三)

    继之前研究了一些飞行姿态理论方面的问题后 又找到了之前很流行的一段外国大神写的代码 来分析分析 第二篇文章的最后 讲到了文章中的算法在实际使用中有重大缺陷 大家都知道 分析算法理论的时候很多情况下我们没有考虑太多外界干扰的情况 原因是很多情
  • 获取单个 Windows 应用程序当前音量输出级别,如音频混合器中所示

    我正在尝试编写一个 C 代码 该代码从每个访问声音输出的 Windows 应用程序输出当前的音频输出级别 如音量混合器不断变化的绿色条所示 该程序将每 10 毫秒检查一次 并输出如下内容 Windows Media Player 30 Mo
  • 使用 Java 进行音频混合(没有 Mixer API)

    我正在尝试混合几种不同的音频流并尝试让它们同时播放代替一次一个 下面的代码一次播放一个 我无法找出不使用 Java Mixer API 的解决方案 不幸的是 我的声卡不支持使用 Mixer API 进行同步 我被迫找出一种通过代码来实现同步
  • 如何在 Unity 中将混音器的音量设置为滑块的音量?

    我正在尝试进行一些音频设置 这是我的脚本 public AudioMixer masterMixer public float masterLvl public float musicLvl public float sfxLvl publ

随机推荐

  • 将LFS系统通过grub装到优盘上启动

    最近在搞LFS xff0c 就是通过自己动手 xff0c 亲自编译源代码的方式 xff0c 建立自己的linux发行版 通过这个过程可以详细的深入了解linux内部的工作方式 xff0c 对理解操作系统的机制有很大的帮助 做这个项目 xff
  • kali linux 解决风扇猛转

    之前玩ubuntu的时候 xff0c 就感觉风扇猛转个不停 xff0c 之前是通过安装nvidia的闭源驱动 xff0c 然后再安装一个管理双显卡的工具解决的 xff0c 确实风扇及立马安静了下来 http www linuxidc com
  • PHP下十六位数值转IP地址

    PHP函数提供的long2ip和ip2long是IP和整形数值之间的转换 xff0c 没有和十六位数值的转换 xff0c 所以写下这个函数 function ntoip iphex len 61 strlen iphex 得到16进制字符串
  • linux系统备份命令

    tar cvpzf backup tgz exclude 61 proc exclude 61 lost 43 found exclude 61 backup tgz exclude 61 mnt exclude 61 sys exclud
  • 硬盘寻址能力的变换

    1 8G限制 硬盘寻址的限制 硬盘最初使用的寻址方法是柱面 磁头 扇区CHS xff08 Cylinder Head Sector xff09 xff0c 也称为3D模式 xff0c 是硬盘最早采用的寻址模式 通过分别指定柱面 磁头 扇区来
  • 关于动态new二维数组的问题

  • Linux 调节并自动保存屏幕亮度,重启有效

    用过几个Linux的发行版 xff0c 发现在笔记本上每次调节亮度后 xff0c 不能固定下来 xff0c 重新开机后就又恢复最大亮度了 之前一直用的是网上流行的方法 xff0c 即往etc rc local文件写入命令 xff0c 使其每
  • kali linux 安装Pidgin QQ

    首先 xff0c 需要kali开启PPA源 PPA xff08 Personal Package Archives xff1a 个人软件包档案 xff09 是Ubuntu Launchpad网络提供的一项服务 xff0c 允许个人用户上传软
  • 教你如何用Kali Linux制作windows 10安装优盘

    最近win10发布了 xff0c 看样子挺不错 虽然我一直用的是Linux xff0c 但是还是想体验一把win10 主要是尼玛我想看百度云里存放的教学视频 xff0c 但是里面的视频还需要特殊的播放器 xff0c 也是不得己 xff0c
  • kali linux安装搜狗输入法

    昨天安装了kali linux2 0 xff0c 感觉输入法没有以前好了 于是查资料安装搜狗输入法 xff0c 还是搜狗输入法好使 有几篇文章倒是谈到如何在kali上安装搜狗了 xff0c 但是一方面是文章太老了 xff0c 二是还得自己下
  • 关于android系统对AndroidManifest文件的解析机制

    最近在学习android的过程中一直在思考一个问题 xff0c 我们都知道 xff0c 在android的AndroidManifest xml 是每个android程序中必须的文件 它位于整个项目的根目录 xff0c 描述了package
  • Android对xml文件的解析

    今天阅读android sdk官方文档时 xff0c 看到这么一段话 xff1a 感觉深受启发 xff1a 1 android的图形界面内部逻辑结构是树形结构 xff0c 这个从xml文件的结构可以直观的看出来 如果我们要使用java代码来
  • kail linux 安装QQ

    腾讯QQ 下载地址 xff1a http www ubuntukylin com appli p lang 61 cn amp id 61 23 下载后解压得到wine qqintl文件夹 xff0c 里面有三个deb包 xff1a fon
  • ubuntu kylin下宽带拨号

    用pppoeconf这个命令 xff0c 一般来说 xff0c 里面已经安装好了的 按照提示过程处理即可 xff0c 要提供adsl用户名和密码 一般很多用户会配置成开机自动启动adsl xff0c 也可以手动 xff1a pon dsl
  • linux主机远程桌面

    利用xrdp 43 rdesktop可以实现
  • 把vim打造成C++ IDE

    目录 准备工作第一个插件pathogenauto pairsNERDTreeMiniBufExplorerctagstaglistomnicppcomplete ctagstaglistOmniCppCompleteSuperTab 最终的
  • MatConvNet compiled with '-R2018a' and linked with '-R2017b'

    modify line 620 to args 61 horzcat 39 outdir 39 mex dir flags base flags mexlink 39 R2018a 39 39 LDFLAGS 61 LDFLAGS 39 s
  • Java篇 - 聊聊Serializable (常见问题集锦)

    接着来聊聊Serializable xff0c Serializable的意思是序列化 1 序列化的概念 序列化 Serialization 将对象的状态信息转换为可以存储或传输的形式的过程 在序列化期间 xff0c 对象将其当前状态写入到
  • 总结:在树莓派中安装Ubuntu后无法连接WiFi的问题

    采用Raspberry官方的工具 官方提供的镜像 官方的配置方法 xff0c 结果发现系统启动后无法连接无线网 xff0c 也没办法配置后续的更新 xff0c 陷入沉思和懵逼 于是不断的换方法 换镜像 换工具 xff0c 依然没有解决问题
  • PX4_mixer通道分配的深度解析

    上文写了PIXHAWK的姿态控制算法 xff0c 该文主要对姿态控制输出到电机输出的通道分配环节进行深入解析 PX4的通道分配环节查看mixer multirotor cpp xff08 对应多旋翼的通道分配 xff09 PX4的mixer