大神浅谈无人机飞控软件设计 系统性总结

2023-05-16

写在前面

深感自己对飞控软件、算法的知识点过于杂乱,很久没有进行系统的总结了,因此决定写几篇文章记录一些飞控开发过程的知识点。主要是针对一些软件、算法部分进行讨论,如内容有错误,欢迎指出。

飞控软件的基本模块

无人机能够飞行主要是依靠传感器系统获取位姿信息并反馈到微处理器进行控制系统的运算。所以飞控软件设计主要负责搭建合理软件流程,使各功能模块协调有效的工作。

一个飞控系统的基本工作主要有:

1、CPU接收遥控器的操作指令和传感器信号;

2、传感器的数据处理和数据融合算法运算,得到位置、姿态信息;

3、根据控制指令完成相应的控制器(姿态、位置)计算,得出控制量并输出到电机驱动;

软件设计方法的讨论

刚接触飞控的时候,实验室在设计之初,为了方便快捷,软件系统的编写采用前后台操作的方式。这个方式的应用程序是在放在mian主函数里面无限循环,调用相应的处理子函数。这称为后台程序。而前台程序指的就是中断程序处理异步触发事件的程序。故前台程序称为中断级程序,而后台程序称为任务级程序。因此有些固定周期执行的任务都要靠中断服务程序来完成,以保证时间的精确性。但是在中断处理程序中只标记事件的发生,不做任何处理,转而由后台系统调度处理,这是为了避免在中断程序执行时间过长影响后续和其他中断事件。

这种设计方法的优点:

1、实现简单,特别是对于笔者这样的编程渣,照着stm32的库函数写代码,也可简单实现;

2、类似单片机的编程,没有OS,因此CPU的性能要求不算高,不太关注ROM/RAM;

3、如果设计得当,相较于带OS的飞控,系统运行更加稳定,听说很多工业级的飞控是不带OS的;

缺点:

由于是用在飞行控制系统中,对整个系统的实时性有着很高的要求,如果逻辑和时序出现偏差,将出现无法估计的严重后果。而在初始开发过程中,发现采用此前后台系统带来两大问题:

1、设计不当的话,比如某个周期的函数执行超时,后面所有的程序都会受到影响。如果飞控程序执行时间变得不够准确,不利于对飞行器的控制,严重时发生飞机失控的现象。

2、移植性和扩展性差,给整个程序后续改动和维护带来不便,由于各种任务都是相关的子函数,往往一个任务需要调用多个子函数。在程序改动或者维护的时候变得非常繁琐复杂。经常由于忽略某一细节而导致功能无法实现,最后导致程序的可读性降低,不利于他人做程序修改。

最近几年也接触了一些开源飞控,看了有关带OS的飞控设计。这种设计方法是在某一操作系统上进行二次开发,OS通过一个内核的调度来管理CPU,使得所有的模块也就是任务都能正常运行,达到相对意义的“并行”。同时采用基于优先级的可剥夺性调度算法来保证实时性。RTOS 将应用层软件分成多个任务,简化了应用软件的设计,同时使得飞行控制的实时性得到保证。

完整的飞控系统组成模块

当设计一个商业飞控的软件时,就不仅仅是让飞机飞起来那么简单了,也就是说软件模块除了基本要素外,还需有其他扩展,如下图所示。

飞控数据流分析

当熟悉了飞控系统中常用的软件模块,那这些模块互相之间又是怎样的关系?又是如何互相通信,各自需要什么数据来完成飞行任务?

以pixhawk飞控的原生固件为例,如下图所示。这图是很早期的代码记录下来的,与最新的代码相比,有些误差,不过差不多,能解释问题,所以笔者懒得更新,重新画图了。

示例分析

掌握了以上所描述的几个知识点,这样基本上在初次阅读一份飞控代码时,能有起码的认知了。下面简单介绍两款开源的飞控代码,都是网上找的代码,主要看下软件架构。

5.1 恒拓开源飞控

基于MDK的开发环境,使用C语言,基于STM32的官方库。

代码结构:

STARTUPCODE:stm32的启动文件;

StdPeriph_Driver:基于3.5版本的库函数的驱动文件;

USB-FS-Device_Driver:USB设备驱动文件;

usb_virture_com:USB的板级支持驱动;

Driver:板级驱动层,包含一些总线和外设的驱动程序;

Modules:传感器模块的驱动程序;

Algorithm:算法程序,包含滤波、数学库等;

Function:飞行应用层,关键模块,比如姿态估计、姿态控制等;

User:主程序和中断应用程序;

ANO_DT:支持匿名地面站协议;

Heigh:高度控制程序;

整个代码的模块化非常细致,比较清晰。

代码设计就是前面所讲的裸机代码的一般实现方法。

先看main文件:

非常简单,上电进行各种初始化,然后大循环,循环执行任务调度。

下面看下loop的函数内容。

将整个飞控代码分成了几个周期分别为5ms,10ms,25ms、50ms和100ms的任务。而每个任务的时间标志flag是由一个时间片函数进行管理的。设了一个tick节拍,2.5ms一次,所以比如计数达到2次,则5ms的定时任务即可执行。

而这个时间片函数是一个定时中断,每隔2.5ms执行一次。

这种程序设计方法如下图所示。定时中断的影响只在任务调度模块里起作用,依次让不同的任务按不同的周期进行执行。要注意的是所设计的每个任务运行时间不能超过设定的周期。

笔者也看了国内有名的匿名飞控,也是同样的调度设计方法,另开源ardupilot飞控,因历史原因,是继承APM飞控而来,也是采用这种类OS的伪调度器方式,代码全部顺序执行,根据定时的计数标志去分别安排飞控任务。

5.2 PX4飞控 - Pixhawk原生固件

开源PX4飞控相对复杂多了,很多软件的细节笔者也不甚了解,所以就简单描述下。

PX4飞控从软件架构上可以分为四层。在每一层里,各个驱动程序或上层的控制/估计算法都是一个独立模块,能够在运行期间互相通信。这种模块化的设计不仅有助于支持更多机型(因为不存在特定机型的主循环),同时使得代码具有高度的可移植性

1、 应用层:该层是整个飞控系统运行的核心。飞控日常飞行所用到的模块基本上都在这层,包括姿态控制,状态估计,导航模块等等来完成多旋翼和固定翼完全自主的航点飞行。应用层可以使用其他的控制软件,如APM:Plane、APM:Copter,但必须运行于中间层之上。

2、 中间层: 通讯的中间层运行于操作系统之上,提供设备驱动和一个微对象请求代理(micro object request broker ,uORB)用于飞控上运行的单个任务之间的异步通信。

3、 NuttX操作系统层:提供给用户操作环境,进行底层的任务调度。

4、 底层驱动层: 提供系统运行所需要的硬件驱动,如一些传感器、执行器等。

板载程序模块:

uorb通信功能描述

在飞控系统中,应用层所有的功能被独立以进程模块为单位进行实现并工作,而进程间的数据交互就由为重要。为了确保通讯符合实时、有序的特点,需要一种安全的通讯机制。Px4飞控系统采用uORB通讯方式。

uORB(Micro Object Request Broker,微对象请求代理器)是非常重要且关键的一个模块,它肩负了整个系统的数据传输任务,所有的传感器数据、GPS、PPM信号等都要从芯片获取后通过uORB进行传输到各个模块进行计算处理。实际上uORB是一套跨进程的IPC(Inter Process Communication)通讯模块。

uORB的发布-订阅设计模式(publish–subscribepattern

飞控系统是基于NuttX实时ARM系统,而uORB对于NuttX而言,它仅仅是一个普通的文件设备对象,这个设备支持Open、Close、Read、Write、Ioctl以及Poll机制。通过这些接口的实现,uORB提供了一套“点对多”的跨进程广播通讯机制,“点”指的是通讯消息的“源”,“多”指的是一个源可以有多个用户来接收、处理。而“源”与“用户”的关系在于,源不需要去考虑用户是否可以收到某条被广播的消息或什么时候收到这条消息。它只需要单纯的把要广播的数据推送到uORB的消息“总线”上。对于用户而言,源推送了多少次的消息也不重要,重要的是取回最新的这条消息。

uORB实际上是多个进程打开同一个设备文件,进程间通过此文件节点进行数据交互和共享。

飞控中每个进程都可以通过Publish/Subscribe(发布/订阅)模式与其他进程以及驱动进行连接。以传感器应用程序发送传感器数据到姿态估计应用程序为例。进程(或者称节点)通过命名的总线交换的消息称之为“主题”,在系统中,一个主题仅包含一种消息类型,例如:vehicle_attitude 主题传输包含姿态角(滚转、俯仰和偏航)的消息。节点可以在总线、主题上发布一条消息(Send data) 或者订阅总线、主题(Receive Data)。通讯双方之间并不知道在与谁通讯,可以存在多个发布者或一条消息有多个订阅者,进程的发布和订阅可以在同一时间,主题对象在自身状态变化时,会通知所有订阅者对象,使它们能够自动更新自己的状态。这种设计模式可以防止锁定的问题,常用于机器人技术。为了保证高效,一条总线上始终只有一条消息,并且不使用队列存放。

Px4官网给出的几种常用通讯机制时间延迟对比:

uORB的实现位于固件源码的src/modules/uORB/uORB.cpp文件,它通过重载CDev基类来组织一个uORB的设备实例。并且完成Read/Write等功能的重载。uORB 的入口点是uorb_main函数,在这里它检查uORB的启动参数来完成对应的功能,uORB支持start/test/status这3条启动参数,在飞控系统的rcS启动脚本中,使用start参数来进行初始化,其他2个参数分别用来进行uORB功能的自检和列出uORB的当前状态。

在rcS中使用start参数启动uORB后,uORB会创建并初始化它的设备实例, 其中的实现大部分都在CDev基类完成。通过init调用完成设备的创建,节点注册以及派遣例程的设置等。

下图是一个设备订阅/发布uorb消息的流程图。

底层驱动中类的概念

PX4中不少程序是用C++写的,大量使用了类的概念。如MPU6000这个芯片,与STM32的SPI接口相连(几个传感器都是通过同一个SPI与STM32相连,只是用CS引脚来加一区分)。在src/drivers/device/spi.cpp中定义了SPI类,而在MPU6000的驱动源文件(src/drivers/mpu6000/mpu6000.cpp)中,使用了继承的方法创建了mpu6000

class MPU6000 :public device::SPI。其他几个与SPI相连的传感器也是如此进行初始化。

有关px4飞控的软件设计,可以看下官网给出的论文:

Lorenz Meier,Dominik Honegger and Marc Pollefeys. PX4: A Node-Based Multithreaded OpenSource Robotics Framework for Deeply Embedded Platforms, ICRA (Int. Conf. onRobotics and Automation) 2015. (to appear)

几个思考

飞控软件中哪些任务优先级高?

很显然就是前面所讲的基本模块,包括遥控输入、传感器数据读取、姿态估计/控制这一类。当然这也设计到飞控的各个控制回路所需的更新速率问题等,后续会详细阐述下飞控中的各个控制回路。关于优先级可以参看px4飞控:

1.(中断级)快速传感器驱动程序

2.看门狗/系统状态监控

3.驱动器输出(PWM输出驱动器线程,IOCOMMS发送命令线程)

4.姿态控制器

5.更新速率慢的传感器驱动程序(不能阻塞姿态控制器)

6.航路/位置控制器

7.默认优先级 - 通用用户代码,shell命令等

8.日志记录,参数同步程序

9.空闲进程

飞控软件的更新周期设计?

飞控中有两个基本的计时:更新周期和延迟。要想获得良好的系统性能,就必须减少延迟。一般情况下,延迟甚至比更新周期更重要—因为大延迟产生相移。延迟造成的相移会让你输出错误的控制量。

所以飞控中,除了设计一个固定的更新周期,还需关注延迟。一个固定频率的控制循环,有时会因为延迟,导致性能很差。举个例子:假设你以100Hz采样速率读取传感器,状态估计和控制器也都是100Hz。那每一步输入的最大延迟/延迟是10ms?

另外,如果分别设计3个循环,传感器读取,状态估计,控制或者将3者放在一个任务循环里,有什么区别?

500hz的读取数据,状态估计,再进行控制和500hz读取数据,状态估计,250hz控制两种方式有区别吗?这3个问题,目前笔者也没有确切的答案,因此就不写了,留作大家思考,可以互相交流看法。

测量函数运行时间?

在飞控算法中,需要用到更新周期这个变量,当然,如果算法运行是固定周期,则变量的值就是所设定的周期,还可以代码自行测量,如下所示。

当然,对算法而言,采用固定的采样率还是计算出来的采样率,个人觉得理论上来讲,计算出来的更准确,应该是更好,当然如果固定的周期不出错,应该也无大的影响。

测量固定周期?

笔者曾经在编写裸机飞控代码时,想确认下所设计的固定周期是否准确,采用了一个笨办法。在周期里,配置一个输出引脚,每执行一次,引脚的电平取反,然后用示波器观察波形,看显示的周期是否与设定的一致,是否会波动变化。如果波动变化很大,说明代码中有任务超时了,整个代码运行出错。

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

大神浅谈无人机飞控软件设计 系统性总结 的相关文章

  • Git查看分支的创建人

    开发小组人多的时候 xff0c 仓库里会有跟多分支 xff0c 需要看下某个分支具体是谁创建的 命令 xff1a git for each ref format 61 39 committerdate 09 authorname 09 re
  • kotlin的this关键字几种用法

    与java不同的是 xff0c 原先MainActivity this这种写法在kotlin中会报错 如下 正确的写法有许多 xff0c 直接就写this也可以识别到 xff0c 如下 xff1a span class token clas
  • Android之ScrollView嵌套ListView解决工具

    public class Utility public void setListViewHeightBasedOnChildren ListView listView 获取ListView对应的Adapter ListAdapter lis
  • kotlin中匿名内部类的写法

    原本java开发安卓常用的setOnClickListener xff0c 用kotlin写 xff0c 也变得五花八门了 span class token keyword var span view span class token op
  • Spring与SpringMVC的区别和联系是啥?

    Spring Spring是一个开源容器框架 xff0c 可以接管web层 xff0c 业务层 xff0c dao层 xff0c 持久层的组件 xff0c 并且可以配置各种bean 和维护bean与bean之间的关系 其核心就是控制反转 I
  • “在XML文件中给代码加注释”请注意注释的位置

    先科普一下eclipse加注释的快捷键 xff1a eclipse中编辑Java文件时 xff0c 注释和取消注释的快捷键都是 xff1a 34 CTRL 43 34 编辑xml文件时 xff0c 注释 xff1a CTRL 43 SHIF
  • “无法识别的USB设备”如何解决

    昨天 xff0c 我把USB数据线插入笔记本电脑做真机调试 xff0c 电脑右下角提示显示 无法识别的USB设备 xff0c 我开始百度 xff08 还不会搭梯子用google xff09 xff0c 搜索结果大多说是要更新驱动 xff0c
  • 解决Android studio 模拟器闪烁黑屏问题

    首先 xff0c 必须感谢csdn大神给我的启示 xff0c 但是原文并没有解决我的问题 我在看 第一行代码 的时候 xff0c 跟着郭霖大神的思路 xff0c 想利用cmd命令查看虚拟机中的 db文件中的数据表 因为真机需要root才能查
  • 关于使用SDKManager刷机出现No SDKs are available for your account的解决办法

    今天刷机出现 No SDKs are available for your account 这个错误 xff0c 所以连第一步都进不去 xff08 下图是用别人的错误图 xff09 最后在GG上找到了一个解决方案 xff0c https f
  • Mac系统装android开发环境无法创建SD卡解决方案

    无法创建SD卡是小事 xff0c 但是引起的问题却是大事 xff0c 模拟器无SD卡则android项目无法正常生成R文件 xff0c 导致HelloWorld都无法跑起来 xff0c 头大 xff0c 折腾了几天 xff0c 终于找到原因
  • Matlab App Designer编译打包exe后读取文件路径问题

    首先 xff0c 标题略长 其次 xff0c 当你看到这个长长的标题并点进来的时候 xff1a bro xff0c 恭喜你终于找到了一个行之有效的解决方案 xff01 好了 xff0c 下面我们言归正传 关于MATLAB App Desig
  • Arduino程序结构,数据类型,变量

    Arduino程序结构 Arduino程序可以分为三个主要部分 xff1a 结构 xff0c 值 xff08 变量和常量 xff09 和函数 span class token keyword void span span class tok
  • 前端基础之《ECMAScript 6(6)—数组》

    一 扩展运算符 1 扩展运算符能将 数组 转换为逗号分隔的 参数序列 声明一个数组 const school 61 39 张三 39 39 李四 39 39 王五 39 用 转换成逗号分隔的序列 xff1a 39 张三 39 39 李四 3
  • linux 安装npm

    1 下载源码安装 cd wget https nodejs org dist v14 15 4 node v14 15 4 linux x64 tar xz 2 解压并放入指定目录 tar xf node v14 15 4 linux x6
  • 【安博.牛耳】嵌入式培训介绍

    培训简介 安博教育集团联手中南地区最大的IT人才输出机构 牛耳软件教育 xff0c 在湖南地区首开专业嵌入式开发工程师培训 嵌入式开发工程师专业培训课程 xff0c 由安博联合各知名企业合作伙伴的精英专家 一线项目总监 经理 优秀技术人员共
  • 最受推荐的10本C/C ++书籍

    链接 xff1a https hackr io blog 10 best c cpp books C和C 43 43 是世界上最流行的编程语言之二 C 43 43 是C语言的扩展 xff0c 这两门语言的潜力都是不可估量的 xff0c 这就
  • Leetcode: Decode ways

    A message containing letters from A Z is being encoded to numbers using the following mapping 39 A 39 gt 1 39 B 39 gt 2
  • 调剂【非全日制】之前必看!关于非全就业情况的一点感想

    原文作者 秦时明月123fly 17年考入帝都的一所985级别的学校非全研究生 xff0c 学制是两年 xff0c 专业是土木口的工程管理 因为是辞职读的非全 xff0c 所以目前也在参加秋招 学土木的都知道 xff0c 要么去施工单位 x
  • 360分!这是某985计算机非全分数线!

    前几天 xff0c 武汉大学公布了计算机相关专业的分数线 xff1a 计算机学院 计算机科学与技术 xff08 学硕 xff09 xff1a 总分 xff1a 380 政治 xff1a 50 外语 xff1a 50 专业课1 xff1a 8
  • 计算机非全日制,究竟值得读吗?

    非全值得读吗 xff1f 作者 xff1a 四川大学 图像所 非全日制 研究生 文章为原创 非全值得读吗 xff1f 我想有这个疑问的大都是应届生 xff0c 而不是往届生或者已经工作的人 xff0c 特别是工作后工资相对较高 xff0c

随机推荐

  • 【非全研究生】到底哪些公司接受?

    很多同学都知道 xff0c 虽然非全在2017年改革了 xff0c 考试难度和毕业难度都加大了 xff0c 但是社会对于非全日制研究生的认可程度依然是个未知数 前几天小编在微博看到一位同学发的 统招非全日制研究生企业认可情况汇总表 xff0
  • 非全凉凉!武汉大学不允许18级19级非全日制硕士研究生参加校招?

    转载于知乎 链接 https www zhihu com question 343870391 作者 xff1a 张铁匠 链接 xff1a https www zhihu com question 343870391 answer 8118
  • 关于博士招生“申请-考核制”,教育部这样说!

    转载于 青塔 近日 xff0c 教育部在官网上就十三届全国人大二次会议 关于改进博士生招生 申请 考核制 的建议 进行答复 答复中称 xff1a 教育部在着力探索建立博士生招生质量第三方评价机制 xff0c 推动招生单位建立健全以自我评价为
  • Keil5.26、Keil5.27、Keil5.30下载地址

    亲测有效 xff0c 速速下载 mdk5 26下载地址 http www keil com fid vquv2wwtdy9j1w9xagw1om5eu9xbkks1e66vd1 files eval mdk526 exe mdk5 27下载
  • EEPROM和flash的区别

    之前对各种存储器一直不太清楚 xff0c 今天总结一下 存储器分为两大类 xff1a ram和rom ram就不讲了 xff0c 今天主要讨论rom rom最初不能编程 xff0c 出厂什么内容就永远什么内容 xff0c 不灵活 后来出现了
  • git merge最简洁用法

    一 开发分支 xff08 dev xff09 上的代码达到上线的标准后 xff0c 要合并到 master 分支 git checkout dev git pull git checkout master git merge dev git
  • 汇编cmp比较指令详解

    刚刚看到了cmp指令 xff0c 一开始有点晕 后来上网找了些资料 xff0c 终于看明白了 xff0c 为了方便初学者 xff0c 我就简单写下我的思路吧 高手绕过 xff0c 谢谢 xff01 cmp compare 指令进行比较两个操
  • vim中复制粘贴

    在vim中要进行复制粘贴 需要使用yy和p指令 但是会发现当我们想讲从vim外面复制的内容粘贴进文本中时 光使用p达不到效果 原因是 在vim中维护者许多的clipboard 而不是只有一个 我们从vim外部 如浏览器 复制的文本所在的cl
  • NP问题真的很难理解

    希望通过这篇文章可以不仅让计算机相关专业的人可以看懂和区分什么是P类问题什么是NP类问题 xff0c 更希望达到的效果是非专业人士比如学文科的朋友也可以有一定程度的理解 有一则程序员界的笑话 xff0c 就是有一哥们去google面试的时候
  • USB转TTL、USB转串口、USB转232的区别

    PO主作为一个没有专业背景的小白 xff0c 在初玩单片机时曾被上面的几个名词所混淆 xff0c 不过后来终于大彻大悟 xff0c 现在把自己的理解写在这里 xff0c 同样准备入门单片机的小白可以看看 xff0c 或许对你有所帮助 首先
  • STM32的时钟系统RCC详细整理

    一 综述 xff1a 1 时钟源 在 STM32 中 xff0c 一共有 5 个时钟源 xff0c 分别是 HSI HSE LSI LSE PLL HSI 是高速内部时钟 xff0c RC 振荡器 xff0c 频率为 8MHz xff1b
  • 第一章 PX4程序编译过程解析

    版权声明 xff1a 本文为博主原创文章 xff0c 未经博主允许不得转载 第一章 PX4程序编译过程解析 PX4是一款软硬件开源的项目 xff0c 目的在于学习和研究 其中也有比较好的编程习惯 xff0c 大家不妨可以学习一下国外牛人的编
  • 第二章 PX4-RCS启动文件解析

    版权声明 xff1a 本文为博主原创文章 xff0c 未经博主允许不得转载 第二章 PX4 RCS启动文件解析 RCS的启动类似于linux的shell文件 xff0c 如果不知道shell文件是什么东西可以理解成是为程序的流程框 xff0
  • pixhawk position_estimator_inav.cpp思路整理及数据流

    写在前面 xff1a 这篇blog主要参考pixhawk的高度解算算法解读 xff0c 并且加以扩展 xff0c 扩展到其他传感器 xff0c 其实里面处理好多只是记录了流程 xff0c 至于里面实际物理意义并不是很清楚 xff0c 也希望
  • git创建新分支

    1 创建本地分支 git branch 分支名 xff0c 例如 xff1a git branch 2 0 1 20120806 注 xff1a 2 0 1 20120806是分支名称 xff0c 可以随便定义 2 切换本地分支 git c
  • 第一章 PX4-Pixhawk-程序编译过程解析

    第一章 PX4程序编译过程解析 PX4是一款软硬件开源的项目 xff0c 目的在于学习和研究 其中也有比较好的编程习惯 xff0c 大家不妨可以学习一下国外牛人的编程习惯 这个项目是苏黎世联邦理工大学的一个实验室搞出来的 该方案是基于NUT
  • 详解几种飞控的姿态解算算法

    姿态解算是飞控的一个基础 重要部分 xff0c 估计出来的姿态会发布给姿态控制器 xff0c 控制飞行平稳 xff0c 是飞行稳定 的最重要保障 有关姿态解算的基础知识 xff0c 这里笔者不会细细描述 xff0c 有关这方面的资料 xff
  • 陀螺仪的数据处理

    1 陀螺仪数据校准 1 1 原理 一款飞控上的传感器是需要进行校准的 xff0c 比如这里讲的陀螺仪 目前大多数的陀螺校准其实就是去掉零点偏移量 xff0c 采集一定的数据 xff0c 求平均 xff0c 这个平均值就是零点偏移 xff0c
  • LevelDB源码分析之从Put说起

    之前分享的文章leveldb实现原理分析详细描述了LevelDB的实现原理 xff0c 本文从Put接口来看下leveldb数据写流程的源码实现 LevelDB的读写接口在类DB中定义 xff08 leveldb db h xff09 xf
  • 大神浅谈无人机飞控软件设计 系统性总结

    写在前面 深感自己对飞控软件 算法的知识点过于杂乱 xff0c 很久没有进行系统的总结了 xff0c 因此决定写几篇文章记录一些飞控开发过程的知识点 主要是针对一些软件 算法部分进行讨论 xff0c 如内容有错误 xff0c 欢迎指出 1