PX4飞控之位置控制(1)整体架构

2023-05-16

位置控制是无人机飞控的核心算法之一,一方面根据commander中的flag标志位和Navigator中提供的航点信息进行控制(自主模式下),另一方面得到期望姿态角(setpoint)的四元数信息,给到姿态控制模块进行姿态控制。本文重点PX4飞控的位置控制的代码整体架构(mc_pos_control),具体的控制算法将在后续文章中陆续奉上。
位置控制模块的主函数:task_main()
1.订阅结构体orb_subscribe()。
2.参数更新parameters_update(true)
3.while (!_task_should_exit){}进入位置控制循环
(1)加锁解锁控制参数重置
if (_control_mode.flag_armed && !was_armed)则重置位置和高度sp,速度sp归零。
_control_mode.flag_armed=armed.armed;飞机启动后为真。while初始定义时bool was_armed = false;初始化为假,意味着在飞机启动时进行位置和速度sp的重置。
注:根据加锁和解锁的判断,保证重新解锁后时位置参数被重置。
(2)获取当前位置和速度信息,作为反馈信息,进行之后的PID控制

if (PX4_ISFINITE(_local_pos.x) &&
    PX4_ISFINITE(_local_pos.y) &&
    PX4_ISFINITE(_local_pos.z)) {
    _pos(0) = _local_pos.x;
    _pos(1) = _local_pos.y;
    if (_params.alt_mode == 1 &&_local_pos.dist_bottom_valid) {
        _pos(2) = -_local_pos.dist_bottom;
    } else {
        _pos(2) = _local_pos.z;
    }
}//更新当前位置坐标
if (PX4_ISFINITE(_local_pos.vx) &&
    PX4_ISFINITE(_local_pos.vy) &&
    PX4_ISFINITE(_local_pos.vz)) {
    _vel(0) = _local_pos.vx;
    _vel(1) = _local_pos.vy;
    if (_params.alt_mode == 1 && _local_pos.dist_bottom_valid) {
        _vel(2) = -_local_pos.dist_bottom_rate;
    } else {
        _vel(2) = _local_pos.vz;
    }
}

注:_params.alt_mode 是MPC_ALT_MODE,默认为0,代表高度跟随,1代表地形跟随。地形跟随模式下,垂直方向上的参考基准为地面。
(3)位置sp
根据commander中不同的标志位选择不同的控制方式。
control_manual(dt);//手动模式
control_offboard(dt);//外部模式
control_auto(dt);//自动模式
得到_pos_sp和yaw_sp.
在control_auto中
起飞时_do_reset_alt_pos_flag = false;其它情况为真。貌似只有在manual中用到。从auto切换到manual时。
进行起落架控制
4.速度SP
(1)非手动控制下,怠速模式下,不进行控制
姿态角的俯仰、横滚为0,航向为当前航向,油门为0.

_att_sp.roll_body = 0.0f;
_att_sp.pitch_body = 0.0f;
_att_sp.yaw_body = _yaw;
_att_sp.thrust = 0.0f;

(2)手动控制,落地之后
对位置和高度sp、三个方向上的积分量进行重置,同时姿态角sp为0,油门sp为0,航向角为当前角度。

_att_sp.roll_body = 0.0f;
_att_sp.pitch_body = 0.0f;
_att_sp.yaw_body = _yaw;
_att_sp.thrust = 0.0f;

注:落地之后,为防止手动打杆翻机,将姿态角和油门都归零,航向角保持不变。
(3)正常情况的水平位置控制:
①_run_pos_control为真时,(初始化为真,只有在手动模式中和offboard中会赋值为假)
水平位置P控制,得到水平速度sp

_vel_sp(0) = (_pos_sp(0) - _pos(0)) * _params.pos_p(0);
_vel_sp(1) = (_pos_sp(1) - _pos(1)) * _params.pos_p(1);

②目标跟随模式下
目标水平速度:ft_vel(_pos_sp_triplet.current.vx, _pos_sp_triplet.current.vy, 0);
if (cos_ratio > 0) {

    ft_vel *= (cos_ratio);//目标速度在无人setpoint速度方向上投影
    ft_vel += ft_vel.normalized() * 1.5f;} 

实际上ft_vel =ft_vel * (cos_ratio)+ft_vel * (cos_ratio).normalized() * 1.5(比投影速度多一点)

_vel_sp(0) = fabs(ft_vel(0)) > fabs(_vel_sp(0)) ? ft_vel(0) : _vel_sp(0);
vel_sp(1) = fabs(ft_vel(1)) > fabs(_vel_sp(1)) ? ft_vel(1) : _vel_sp(1);

二者取较大的速度
③当前目标位置无效,速度有效时,速度sp就等于航点设定速度

_vel_sp(0) = _pos_sp_triplet.current.vx;
_vel_sp(1) = _pos_sp_triplet.current.vy;

(4)正常情况的高度位置控制

_vel_sp(2) = (_pos_sp(2) - _pos(2)) * _params.pos_p(2);

(5)速度限幅(在control auto 中也有进行限幅的控制)
水平方向的和速度,不能大于水平方向上的最大速度,大于之后,对水平的xy方向上的速度进行等比例缩小。合速度等于最大速度。

                float vel_norm_xy = sqrtf(_vel_sp(0) * _vel_sp(0) +
                              _vel_sp(1) * _vel_sp(1));

                if (vel_norm_xy > _params.vel_max(0)) {
                    /* note assumes vel_max(0) == vel_max(1) */
                    _vel_sp(0) = _vel_sp(0) * _params.vel_max(0) / vel_norm_xy;
                    _vel_sp(1) = _vel_sp(1) * _params.vel_max(1) / vel_norm_xy;
                }

                /* make sure velocity setpoint is saturated in z*/
                if (_vel_sp(2) < -1.0f * _params.vel_max_up) {
                    _vel_sp(2) = -1.0f * _params.vel_max_up;
                }

                if (_vel_sp(2) >  _params.vel_max_down) {
                    _vel_sp(2) = _params.vel_max_down;
                }

垂直方向上的速度,在最大上升速度和最小下降速度之间。
(6)对于需要reset的情况,位置、高度、速度重置(在mission等自主模式中不会触发)

if (!_control_mode.flag_control_position_enabled) {
    _reset_pos_sp = true;
}

if (!_control_mode.flag_control_altitude_enabled) {
    _reset_alt_sp = true;
}
if (!_control_mode.flag_control_velocity_enabled) {
    _vel_sp_prev(0) = _vel(0);
    _vel_sp_prev(1) = _vel(1);
    _vel_sp(0) = 0.0f;
    _vel_sp(1) = 0.0f;
    control_vel_enabled_prev = false;
}
if (!_control_mode.flag_control_climb_rate_enabled) {
    _vel_sp(2) = 0.0f;
}

(7)降落速度控制(见下一篇博客)
(8)起飞速度控制(见下一篇博客)
(9)加速度最大值对速度sp的限幅

水平:

math::Vector<2> acc_hor;
acc_hor(0) = (_vel_sp(0) - _vel_sp_prev(0)) / dt;
acc_hor(1) = (_vel_sp(1) - _vel_sp_prev(1)) / dt;
if ((acc_hor.length() > _params.acc_hor_max) & !_reset_pos_sp) {
    acc_hor.normalize();
    acc_hor *= _params.acc_hor_max;
    math::Vector<2> vel_sp_hor_prev(_vel_sp_prev(0), _vel_sp_prev(1));
    math::Vector<2> vel_sp_hor = acc_hor * dt + vel_sp_hor_prev;
    _vel_sp(0) = vel_sp_hor(0);
    _vel_sp(1) = vel_sp_hor(1);
}

垂直:

float acc_v = (_vel_sp(2) - _vel_sp_prev(2)) / dt;

if ((fabsf(acc_v) > 2 * _params.acc_hor_max) & !_reset_alt_sp) {
    acc_v /= fabsf(acc_v);
    _vel_sp(2) = acc_v * 2 * _params.acc_hor_max * dt + _vel_sp_prev(2);
}

5.油门sp
(1)积分项
(2)加速度控制时,直接根据目标航点加速度得到油门值
非加速度控制,利用PID参数得到thrust sp。(对于mission模式,都是非加速度控制)

if (_control_mode.flag_control_acceleration_enabled && _pos_sp_triplet.current.acceleration_valid) {
    thrust_sp = math::Vector<3>(_pos_sp_triplet.current.a_x, _pos_sp_triplet.current.a_y, _pos_sp_triplet.current.a_z);
} else {
    thrust_sp = vel_err.emult(_params.vel_p) + _vel_err_d.emult(_params.vel_d) + thrust_int;
}

(3)起飞、降落油门控制
(4)最大加速度限幅
水平:

if (thrust_sp_xy_len > thrust_xy_max) {
    float k = thrust_xy_max / thrust_sp_xy_len;
    thrust_sp(0) *= k;
    thrust_sp(1) *= k;
    saturation_xy = true;
}

(5)重力补偿(垂直油门)

if (_control_mode.flag_control_climb_rate_enabled && !_control_mode.flag_control_velocity_enabled) {
    float att_comp;
    if (_R(2, 2) > TILT_COS_MAX) {
        att_comp = 1.0f / _R(2, 2);
    } else if (_R(2, 2) > 0.0f) {
        att_comp = ((1.0f / TILT_COS_MAX - 1.0f) / TILT_COS_MAX) * _R(2, 2) + 1.0f;
        saturation_z = true;
    } else {
        att_comp = 1.0f;
        saturation_z = true;
    }
    thrust_sp(2) *= att_comp;
}

(6)总油门限幅,加速度超过最大值thrust_abs > thr_max
垂直方向上的 推力向上,同时超过最大值 thr_max时(0.9),水平方向上为0,垂直方向上等于最大值。
垂直方向上的推力向上,没有超过最大值 thr_max时,优先保证垂直推力,得到水平上的最大推力合力,对水平进行限幅。
垂直方向上加速度向下时,则同时对三个方向上进行等比例限幅
(7)更新积分项
速度控制有效同时没有进行推力限幅时。
由速度误差得到积分值,水平和垂直两个方向。
6.姿态角sp与四元数
(1)body_z = -thrust_sp / thrust_abs;机体z轴与推力轴重合,
求机体坐标系三个轴单位向量在地面坐标系下的坐标
先求body_z= -thrust_sp / thrust_abs;
(2)机体坐标系y轴在水平面上的投影向量

y_C(-sinf(_att_sp.yaw_body), cosf(_att_sp.yaw_body), 0.0f);

由偏航角求得,
叉乘得到机体坐标系的x轴向量

body_x = y_C % body_z;

(3)机体x轴和机体z轴叉乘的到真正的机体y轴向量。

body_y = body_z % body_x;

(4)这三个向量组成旋转矩阵R=euler
_att_sp.roll_body = euler(0);_att_sp.pitch_body = euler(1);
得到四元数,给到姿态sp
7.手动控制下的姿态角sp


_att_sp.yaw_sp_move_rate = _manual.r * yaw_rate_max;
yaw_target = _wrap_pi(_att_sp.yaw_body + _att_sp.yaw_sp_move_rate * dt);
_att_sp.roll_body = _manual.y * _params.man_roll_max;
_att_sp.pitch_body = -_manual.x * _params.man_pitch_max;//x为正时,摇杆往前推,俯仰角为负
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PX4飞控之位置控制(1)整体架构 的相关文章

随机推荐

  • MCB MCCB ACB ELCB RCCB的区别和特性

    如有错误 xff0c 欢迎指正 先说结论 xff0c 基本可以把MCB xff0c MCCB xff0c VCB以及ACB看成过流保护断路器 xff0c 是为了保护电路电器的 xff0c 他们之间的区别一个是工作原理 xff0c 另一个就是
  • ROS学习笔记—— tf 工具包介绍

    1 准备工作 安装一些工具包 sudo apt get install ros melodic ros tutorials ros melodic geometry tutorials ros melodic rviz ros melodi
  • ROS “is neither a launch file in package”报错

    一般是没找着你的package配置文件 xff0c 运行 rospack find package 名 查看能否找到包 xff0c 找不到的话把你的包拷贝到workspace路径下 xff0c cd到你的workspace路径 然后运行 c
  • bvh-converter将bvh文件输出为csv文件失败,原因竟是numpy版本不匹配

    最近做的东西需要将bvh数据处理成xyz坐标 xff0c 在下面这篇文章找到了方法 xff1a 57条消息 人体动作捕捉格式BVH及其与三维坐标的转换 三维视频转bvh 零度蛋花粥的博客 CSDN博客 通过pip导入bvh converte
  • C++实验:多态性与虚函数

    C 43 43 实验 xff1a 多态性与虚函数 1 实验目的 xff08 1 xff09 了解多态性的概念 xff08 2 xff09 了解虚函数的作用及使用方法 xff08 3 xff09 了解静态关联和动态关联的概念和用法 xff08
  • 2014流水账

    欢迎转载 xff0c 转载请注明出处 本文地址 xff1a http blog csdn net zhenggaoxing article details 42386821 三天元旦小长假结束了 xff0c 先来回顾下三天的假期 xff1a
  • IOS中文排序学习

    前言 xff1a 最近有中文排序的需要 xff0c 发现系统没有提供中文排序的方法 xff0c 于是参考学习了网上前辈的代码实现了中文排序功能 xff0c 本文记录的就是学习实现中文排序的过程 实现英文排序 系统提供了英文排序的方法 写了一
  • IOS 定制中间突出UItabBar

    前言 xff1a 公司的项目需要定制一个中间突出的TabBar xff0c 在github 上找到一份可以参考的代码 xff08 虽然是四年前的 xff0c 但是还是很有参考价值 xff09 网址 xff1a https github co
  • Xcode删除所有断点

    问题是这样的 xff1a 接手新的项目 xff0c 顿时吓尿了 xff1a 整个程序有无数个断点 xff0c 那么如何一次性删除呢 xff1f 如下图 xff1a 点击Belete Breakpoints 就可以了
  • VSCode重新启用“错误波形提示”

    2020 06 09 更新常见问题 昨天晚上写伪码的时候 xff0c 看着VSCode的错误提示实在是心烦 xff0c 就手贱点了一下 禁用错误波形提示 xff0c 也就是disable error squiggles xff0c 但写完之
  • TortoiseSVN使用教程[多图超详细]

    安装及下载client 端 下载Windows 端程序 xff1a http tortoisesvn net downloads 一般而言 xff0c 如果是32 bit的Windows XP 应该使用TortoiseSVN 1 4 x x
  • 将UIColor转换为RGB值

    objc view plain copy 将UIColor转换为RGB值 NSMutableArray changeUIColorToRGB UIColor color NSMutableArray RGBStrValueArr 61 NS
  • 业余时间你在做什么,你就会变成什么样的人?

    改变 xff0c 从业余时间开始 博客定位 xff1a 技术 43 思考 其余统统不要 2017 xff0c 我来了 xff01
  • Xcode9 无证书真机调试

    写在前面 公司分配了新的测试机 证书99台名额已满 所以上网找教程 学习了一下如何使用Xcode无证书进行真机调试 一 创建证书 1 运行Xcode xff0c Xcode Preference 添加账号 xff08 能在appstore下
  • CSP考试复习:第一单元 C++语言基础 1.1 程序结构

    第一单元 C 43 43 语言基础 1 1 程序结构 1 程序框架 注释 xff1a 注释有两种 xff0c 一种是 xff0c 另一种是 必须单独放置一行 xff0c 或代码所在行 的后面 xff1b 而 成对存在 xff0c 可以插入到
  • Intel Realsense T265开箱测试

    前言 xff1a 最近因为要做VIO xff0c 在实验室蹭到一个Realsense T265来用 xff0c 仅此记录下简单测试过程 xff08 官方文档写非常清楚 xff0c 建议详细阅读 xff0c 链接 xff1a https gi
  • posix thread介绍

    xfeff xfeff posix thread是 操作系统级 xff08 OS level xff09 的API规范 xff0c 主要用来定义线程及线程间同步的相关操作 xff0c 采用C语言定义 posix规范主要在unix like类
  • PX4飞控之自主起飞Takeoff控制逻辑

    本文主要以PX4飞控1 5 5版本为例 xff0c 介绍Navigator中自主起飞 xff08 Takeoff xff09 算法控制逻辑 注 xff1a mission任务中的自主起飞与此模块不同 Takeoff与导航中的其他模块类似 x
  • PX4飞控之导航及任务架构

    本文重点介绍PX4飞控的Navigator和mission控制框架和逻辑 Navigator导航部分是无人机自主飞行控制的核心所在 xff0c 其中包括自主起飞 自主降落 自主返航 自主任务以及GPS失效保护等各个部分 搞懂这个部分有助于理
  • PX4飞控之位置控制(1)整体架构

    位置控制是无人机飞控的核心算法之一 xff0c 一方面根据commander中的flag标志位和Navigator中提供的航点信息进行控制 xff08 自主模式下 xff09 xff0c 另一方面得到期望姿态角 xff08 setpoint