我刚刚发现这篇文章去年八月份的时候转载过一次了

https://blog.csdn.net/sinat_16643223/article/details/107874349

转载自:https://blog.csdn.net/iamqianrenzhan/article/details/78066369

PX4代码学习系列博客(6)——offboard模式位置控制代码分析

仟人斩 2017-09-22 19:49:03 2961 收藏 17

分类专栏: px4 文章标签: pixhawk PX4 offboard 位置控制

最后发布:2017-09-22 19:49:03首次发布:2017-09-22 19:49:03

版权声明:本文为博主原创文章,遵循<a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> CC 4.0 BY-SA </a>版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/iamqianrenzhan/article/details/78066369

版权

分析offboard模式的代码需要用到以下几个模块

local_position_estimator
mavlink
mc_pos_control
mc_att_control
mixer

程序数据走向

mavlink

一般的offboard模式需要给飞控发送两条mavlink消息:

//飞控在接收到mavlink设置点消息的时候执行下面函数
void MavlinkReceiver::handle_message_set_position_target_local_ned(mavlink_message_t *msg)
{//这个函数把消息解析后发布了两个消息://offboard_control_mode和position_setpoint_triplet
}
//飞控在接收到mavlink当前点消息用来进行外部位置估计的时候执行下面函数
void MavlinkReceiver::handle_message_att_pos_mocap(mavlink_message_t *msg)
{//这个函数把消息解析后发布消息://att_pos_mocap
}

首先分析handle_message_set_position_target_local_ned这个函数发出的两条消息各是什么内容
发出的offboard_control_mode_s结构体:

offboard_control_mode.timestamp = hrt_absolute_time();
offboard_control_mode.ignore_position = (bool)(set_position_target_local_ned.type_mask & 0x7);
offboard_control_mode.ignore_alt_hold = (bool)(set_position_target_local_ned.type_mask & 0x4);
offboard_control_mode.ignore_velocity = (bool)(set_position_target_local_ned.type_mask & 0x38);
offboard_control_mode.ignore_acceleration_force = (bool)(set_position_target_local_ned.type_mask & 0x1C0);
bool is_force_sp = (bool)(set_position_target_local_ned.type_mask & (1 << 9));
offboard_control_mode.ignore_attitude = (bool)(set_position_target_local_ned.type_mask & 0x400);
offboard_control_mode.ignore_bodyrate = (bool)(set_position_target_local_ned.type_mask & 0x800);

读取的vehicle_control_mode_s结构体判断当前是否是offboard模式,如果是则发送position_setpoint_triplet消息
发出的position_setpoint_triplet_s结构体:

pos_sp_triplet.current.type
pos_sp_triplet.timestamp = hrt_absolute_time();
pos_sp_triplet.previous.valid = false;
pos_sp_triplet.next.valid = false;
pos_sp_triplet.current.valid = true;
pos_sp_triplet.current.position_valid = true;
pos_sp_triplet.current.x = set_position_target_local_ned.x;
pos_sp_triplet.current.y = set_position_target_local_ned.y;
pos_sp_triplet.current.z = set_position_target_local_ned.z;
pos_sp_triplet.current.velocity_valid = true;
pos_sp_triplet.current.vx = set_position_target_local_ned.vx;
pos_sp_triplet.current.vy = set_position_target_local_ned.vy;
pos_sp_triplet.current.vz = set_position_target_local_ned.vz;
pos_sp_triplet.current.acceleration_valid = true;
pos_sp_triplet.current.a_x = set_position_target_local_ned.afx;
pos_sp_triplet.current.a_y = set_position_target_local_ned.afy;
pos_sp_triplet.current.a_z = set_position_target_local_ned.afz;
pos_sp_triplet.current.acceleration_is_force = is_force_sp;
pos_sp_triplet.current.yaw_valid = true;
pos_sp_triplet.current.yaw = set_position_target_local_ned.yaw;
pos_sp_triplet.current.yawspeed_valid = true;
pos_sp_triplet.current.yawspeed = set_position_target_local_ned.yaw_rate;

local_position_estimator

在Firmware\src\modules\local_position_estimator\sensors下的mocap.cpp中有这么一行

static const uint32_t       MOCAP_TIMEOUT =     200000; // 0.2 s

这代表att_pos_mocap消息的发送频率必须大于5Hz,不然就会timeout,但是在实际测试过程中,发送的频率在30Hz以上才能稳定不timeout,这是因为它的程序写的太苛刻,只要每两帧有效数据的时间戳间隔大于0.2s就会timeout。

在Firmware\src\modules\local_position_estimator下的BlockLocalPositionEstimator.cpp中有这么一段

if (mocapUpdated) {if (_sensorTimeout & SENSOR_MOCAP) {mocapInit();{mocapCorrect();}
}

只要超时就会重新初始化。

如果外部估计的位置足够精确,可以选择不用飞控上的其他传感器,可以在参数LPE_FUSION中设置。

mc_pos_control

然后转到旋翼的位置控制模块:
在目录E:\github\Firmware\src\modules\mc_pos_control下的mc_pos_control_main.cpp文件
打开task_main函数,发现

_pos_sp_triplet_sub = orb_subscribe(ORB_ID(position_setpoint_triplet));
_control_mode_sub = orb_subscribe(ORB_ID(vehicle_control_mode));

它订阅了position_setpoint_triplet和vehicle_control_mode这两个消息。
然后是

update_velocity_derivative();
//这个函数用来更新速度偏差,如果目标位置丢失,则速度偏差为0。
do_control(dt);
//这里面的一些分支判断用的是vehicle_control_mode_s这个结构体。

do_control调用了

control_non_manual(dt);

control_non_manual调用了

control_offboard(dt);
control_position();

control_offboard用来判断是位置控制还是姿态控制并把控制量获取并发布。
我这里用的是位置和偏航角控制,所以在这个函数中执行的内容有

_pos_sp(0) = _pos_sp_triplet.current.x;
_pos_sp(1) = _pos_sp_triplet.current.y;
_run_pos_control = true;
_hold_offboard_xy = false;
_att_sp.yaw_body = _pos_sp_triplet.current.yaw;

最后发布vehicle_local_position_setpoint这个消息

_local_pos_sp.timestamp = hrt_absolute_time();
_local_pos_sp.x = _pos_sp(0);
_local_pos_sp.y = _pos_sp(1);
_local_pos_sp.z = _pos_sp(2);
_local_pos_sp.yaw = _att_sp.yaw_body;
_local_pos_sp.vx = _vel_sp(0);
_local_pos_sp.vy = _vel_sp(1);
_local_pos_sp.vz = _vel_sp(2);
orb_advertise(ORB_ID(vehicle_local_position_setpoint), &_local_pos_sp);

control_position调用calculate_velocity_setpoint函数和calculate_thrust_setpoint函数,calculate_velocity_setpoint根据位置偏差计算速度偏差,里面代码不长,直接贴出

void MulticopterPositionControl::control_position(float dt)
{calculate_velocity_setpoint(dt);if (_control_mode.flag_control_climb_rate_enabled || _control_mode.flag_control_velocity_enabled ||_control_mode.flag_control_acceleration_enabled) {calculate_thrust_setpoint(dt);} else {_reset_int_z = true;}
}

在计算速度设置点函数calculate_velocity_setpoint中:

/* run position & altitude controllers, if enabled (otherwise use already computed velocity setpoints) */
if (_run_pos_control)
{// If for any reason, we get a NaN position setpoint, we better just stay where we are.if (PX4_ISFINITE(_pos_sp(0)) && PX4_ISFINITE(_pos_sp(1))) {_vel_sp(0) = (_pos_sp(0) - _pos(0)) * _params.pos_p(0);_vel_sp(1) = (_pos_sp(1) - _pos(1)) * _params.pos_p(1);} else {_vel_sp(0) = 0.0f;_vel_sp(1) = 0.0f;warn_rate_limited("Caught invalid pos_sp in x and y");}
}limit_altitude();if (_run_alt_control)
{if (PX4_ISFINITE(_pos_sp(2))) {_vel_sp(2) = (_pos_sp(2) - _pos(2)) * _params.pos_p(2);} else {_vel_sp(2) = 0.0f;warn_rate_limited("Caught invalid pos_sp in z");}
}
//后面是对起飞速度的设置和各个方向速度的一个限制。

calculate_thrust_setpoint函数根据速度设置点计算姿态设置点然后发布姿态设置点vehicle_attitude_setpoint。

mc_att_control

再转到姿态控制模块
它订阅了vehicle_control_mode和vehicle_attitude_setpoint这两个消息。

_v_control_mode_sub = orb_subscribe(ORB_ID(vehicle_control_mode));
_v_att_sp_sub = orb_subscribe(ORB_ID(vehicle_attitude_setpoint));

姿态控制模块把姿态设置点转换为需要的角速度。
从位置设置点到最后的三个方向的设置角速度,中间代码仔细分析比较复杂,具体的数学公式整理起来是一个浩大的工程,一个大概的思路是:

这个模块把姿态设置点转化为角速率设置点,然后在mixer中控制电机。

PX4代码学习系列博客(6)——offboard模式位置控制代码分析(之前转载过,这是第二次转载了)相关推荐

  1. PX4代码学习系列博客(5)——在px4中添加自己的模块

    怎么在px4中添加自己的模块 在"px4固件目录结构和代码风格"这一节,曾经说过NuttX是一个实时的嵌入式系统,上面可以像windows那样运行程序.那既然是应用程序,那我们应该 ...

  2. 点云深度学习系列博客(二): 点云配准网络PCRNet

    目录 一. 简介 二. 基础结构 三. 项目代码 四. 实验结果 总结 Reference 今天的点云深度学习系列博客为大家介绍一个用于点云配准的深度网络:PCRNet [1].凡是对点云相关应用有些 ...

  3. 点云深度学习系列博客(四): PointNet代码精讲

    目录 1. 代码解析 1.1 初始化 1.2 数据载入 1.3 模型载入 1.4 训练代码 2. 实验结果 Reference 最近开始上手点云深度学习项目,相比之前纸上谈兵的阶段,此时我将把更多的精 ...

  4. 点云深度学习系列博客(一): 点云特征学习网络PCPNet

    目录 一. 简介 二. 基础结构 三. 项目代码 四. 实验结果 总结 Reference 最近开始研究点云分析的相关项目,经过文献调研我发现,近几年比较热的方法,基本都是基于深度学习框架设计的.正好 ...

  5. 【技术博客】2020.04.28-简单塔防游戏和棋牌游戏构架学习 ——学习系列博客(一)构架初探

    序言,保卫萝卜项目作为自己学习整体游戏项目的开始,还是很有收获的. 项目初步实现了分管关卡地图编辑.场景结构.关卡选择.游戏地图等主要功能,同时内部构架采用了MVC加单例的构架,对我这种初学者还是很有 ...

  6. android中页面自动跳转,【学习笔记-安卓开发】8. Android Studio如何实现页面自动跳转(安卓学习系列博客)...

    先将上上一篇博客中写在页面里的button以及相关代码删除 8.如何让页面自动跳转 在安卓开发中有一个非常重要的Handler 当我们输入Handler会出现两个提示,一个是os中的,一个是loggi ...

  7. 博客园Markdown模式的MATLAB代码高亮方案

    前言 博客园随笔写作可以使用 Markdown 进行编辑,当展示代码时,可以使用下面的语法来对代码块进行展示: ​```language code-content ​``` 一般来说,指明了 lang ...

  8. flutter 返回指定界面_Flutter 即学即用系列博客——04 Flutter UI 初窥

    前面三篇可以算是一个小小的里程碑. 主要是介绍了 Flutter 环境的搭建.如何创建 Flutter 项目以及如何在旧有 Android 项目引入 Flutter. 这一篇我们来学习下 Flutte ...

  9. 项目体系架构设计——基于Spark平台的协同过滤实时电影推荐系统项目系列博客(四)

    系列文章目录 初识推荐系统--基于Spark平台的协同过滤实时电影推荐系统项目系列博客(一) 利用用户行为数据--基于Spark平台的协同过滤实时电影推荐系统项目系列博客(二) 项目主要效果展示--基 ...

最新文章

  1. 关于li标签之间的间隔如何消除!
  2. 【干货】Oracle数据库常用十一大操作指令
  3. nyoj66分数拆分
  4. 重新ICP,在没有Matlab的日子里
  5. Python中global和nolocal作用域的理解
  6. LEX和YACC的使用(例子)
  7. JSON字符串转换为Map
  8. 学 Win32 汇编[6]: 伪指令 DUP 与数组
  9. 浮点数运算中的舍入问题
  10. linux用openssl制作自签名数字证书
  11. 微商公社新兵连第五天
  12. 程序猿们,面对诱惑,你能hold住吗?
  13. english need study and insist 1
  14. Python助你抢红包
  15. webpy实时展示mysql数据库_webpy使用mysql数据库操作(web.database)
  16. 使用Office Tool Plus安装office、visio、project等--很实用
  17. SIM7600透传模式
  18. keras神经风格迁移_知识分享 | 神经风格迁移-把每一张图片都变成自己喜欢的样子...
  19. cocos2d 3.3 lua 代码加密 luac
  20. EditText的getText()方法

热门文章

  1. JavaWeb项目管理工具————Maven的使用
  2. ENVI教程:InSAR技术,自适应滤波及相干性
  3. 独立思考Justic:Putting a Price Tag on Life
  4. 【微信公众号】微信集成功能--扫描二维码完成用户登录操作
  5. 虚拟化服务器进入操作系统,虚拟化服务器的操作系统
  6. PLC-Recorder以2ms的高速采集西门子S7-1500数据的方法
  7. Android系统之ViewTree的创建与绘制
  8. 虚拟现实和增强现实技术_虚拟现实和增强现实如何改变当今的企业
  9. 计算机配机方案及理由报告,大学生社会调查计算机配机方案的报告范本.doc
  10. MYSQL 自定义函数,查询节点所有父节点、查询节点所有子节点