Jack Huang's Blog


  • 首页

  • 标签

  • 归档

  • 搜索

计算机科学术语辨析

发表于 2019-05-05

计算机科学中的一些术语是同行之间进行交流的工具,但是这些术语约定俗成,缺乏权威定义,在不同的语境下有不同的涵义,不同的人有不同的理解,由此造成很多分歧。本文记录常用计算机科学术语,通过规范和校正其内涵和外延,避免分歧,提高效率。

常用术语

架构

软件架构是有关软件整体结构与组件的抽象描述,用于指导大型软件系统各个方面的设计。

软件架构是一个系统的草图,抽象层次高。软件架构描述的对象是直接构成系统的抽象组件。各个组件之间的连接则明确和相对细致地描述组件之间的通讯。在实现阶段,这些抽象组件被细化为实际的组件,比如具体某个类或者对象。在面向对象领域中,组件之间的连接通常用接口来实现。

模式

在软件工程中,设计模式(design pattern)是对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案。这个术语是由埃里希·伽玛(Erich Gamma)等人在1990年代从建筑设计领域引入到计算机科学的。

设计模式并不直接用来完成代码的编写,而是描述在各种不同情况下,要怎么解决问题的一种方案。面向对象设计模式通常以类别或对象来描述其中的关系和相互作用,但不涉及用来完成应用程序的特定类别或对象。设计模式能使不稳定依赖于相对稳定、具体依赖于相对抽象,避免会引起麻烦的紧耦合,以增强软件设计面对并适应变化的能力。

《设计模式》一书原先把设计模式分为创建型模式、结构型模式、行为型模式,把它们通过授权、聚合、诊断的概念来描述。

模块

模块,module,模块是一个通用概念,可能从功能或其他目的来区分。模块可以是子系统子领域,主要取决于上下文环境的用法。

通常我们会说程序模块,功能模块,这实际上是在按照不同的标准对模块的内容和范围的不同定义。

通常我们说的程序模块,是指的一段能够实现某个有价值目标的的成员代码段,这样的东西,我们还有另一个称呼:例程,而例程有两种,即函数和过程,它们都能实现一个有价值的目标供其它的模块使用。

而功能模块的说法一般在分析和设计阶段出现得比较频繁,通常我们用一个功能模块来说明一个功能所包含的系统行为,当我们觉得分析的颗粒度可能更大一些的时候我们可以用一个功能模块来表示一组功能的集合,这似乎让我们觉得,模块这个词的概念和“子系统”这个词的概念有些模糊,是的,事实上,有些大的模块会慢慢的让我们觉得称呼他们子系统更合适,或者一个子系统,我们会慢慢发现你还包含着一些模块。

但是无论怎样,定义模块的原则应该是:高内聚和低耦合。

组件

软件组件,定义为自包含的、可编程的、可重用的、与语言无关的软件单元。

插件

根据对组件和模块的分析,插件属于组件,而且还是一个程序模块,也是一个功能模块。插件是一种电脑程序,通过和应用程序的互动,来替应用程式增加一些特定的功能。 插件必须依赖于应用程序才能发挥自身功能,仅靠插件是无法正常运行的。

使用方法:满足一定接口规范的具有一定功能的程序模块。开发者可以在自己软件系统中设计相应的接口以匹配某个插件,也可以设计一定的接口规范,来让别人开发插件。插件和程序之间通过接口进行交互。

控件

可视化的组件。

中间件

中间件是提供系统软件和应用软件之间连接的软件,以便于软件各部件之间的沟通。

术语辨析

面向对象编程 VS 面向过程编程 VS 面向切面编程

面向过程(Procedure Oriented)是一种以过程为中心的编程思想。这些都是以什么正在发生为主要目标进行编程,不同于面向对象的是谁在受影响。与面向对象明显的不同就是封装、继承、类。

面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)是一种计算机编程架构。OOP 的一条基本原则是计算机程序是由单个能够起到子程序作用的单元或对象组合而成。OOP 达到了软件工程的三个主要目标:重用性、灵活性和扩展性。为了实现整体运算,每个对象都能够接收信息、处理数据和向其它对象发送信息。

面向切面编程(Aspect Oriented Programming(AOP)),是一个比较热门的话题。AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。

面向过程编程围绕行为组织事物,面向对象编程围绕事物组织行为,有没有类、有没有继承并不是两种编程方法差异的关键;

面向切面编程是横跨流程的,实现某个特定位置的功能,面向功能进行抽象。具体流程只需做引用即可,而不至于不同流程中冗余很多类似代码。

组件化开发 VS 模块化开发

组件化和模块化的中心思想都是分而治之。目的都是将一个庞大的系统拆分成多个组件或者说是模块。

模块化就是将一个程序按照其功能做拆分,分成相互独立的模块,以便于每个模块只包含与其功能相关的内容。模块我们相对熟悉,比如登录功能可以是一个模块,搜索功能可以是一个模块,汽车的发送机也可是一个模块.

组件化就是基于可重用的目的,将一个大的软件系统按照分离关注点的形式,拆分成多个独立的组件,主要目的就是减少耦合.

一个独立的组件可以是一个软件包、web服务、web资源或者是封装了一些函数的模块。比如汽车的发动机是一个模块,也是一个组件,再或者前端中的一个日历控件是一个模块,也一个组件.这样,独立出来的组件可以单独维护和升级而不会影响到其他的组件.

组件和模块是一对容易混淆的名词,也常常被用来相互替换,两者是否有差异往往取决于专业背景、所在领域、以及视角。从设计上来看,组件强调复用,模块强调职责(内聚、分离),或者说组件是达到可复用要求的模块

模块化强调的是拆分,无论是从业务角度还是从架构、技术角度,模块化首先意味着将代码、数据等内容按照其职责不同分离,使其变得更加容易维护、迭代,使开发人员可以分而治之。

组件化则着重于可重用性,不管是界面上反复使用的用户头像按钮,还是处理数据的流程中的某个部件,只要可以被反复使用,并且进行了高度封装,只能通过接口访问,就可以称其为“组件”。

参考链接

  1. 面向对象 vs 类与继承 vs 面向组件, by 龙腾道默默地.
  2. 软件架构,by wikipedia.
  3. 软件架构入门,by 阮一峰.
  4. 设计模式,by wikipedia.
  5. 软件架构、框架、模式、模块、组件、插件概念汇总,by 时间的朋友.
  6. 模块化与组件化,by 滴答.
  7. 面向过程编程,面向对象编程和面向切面编程理解, by 枫叶千言.

PX4应用开发简要教程

发表于 2019-04-29

本文说明如何创建和运行第一个板载应用程序。 它涵盖了PX4上应用程序开发所需的所有基本概念和API。

开发环境

在开发第一个PX4应用程序之前,需要构建如下开发环境:

  • PX4 SITL模拟器或兼容PX4的飞行控制器。
  • PX4开发工具链用于所需目标。
  • 从Github下载PX4源代码

简单应用

代码编写

本节创建一个最小的应用,仅用于打印Hello Sky!。整个应用由一个简单C文件和一个cmake定义文件构成。具体步骤如下:

  1. 创建目录Firmware/src/examples/px4_simple_app
  2. 在上述目录中创建C文件px4_simple_app.c
  3. 在上述目录中创建cmake定义文件CMakeLists.txt

px4_simple_app.c代码内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* @file px4_simple_app.c
* Minimal application example for PX4 autopilot
*
* @author Example User <mail@example.com>
*/

#include <px4_log.h>

__EXPORT int px4_simple_app_main(int argc, char *argv[]);

int px4_simple_app_main(int argc, char *argv[])
{
PX4_INFO("Hello Sky!");
return OK;
}

CMakeLists.txt文件内容如下:

1
2
3
4
5
6
7
8
9
px4_add_module(
MODULE examples__px4_simple_app
MAIN px4_simple_app
STACK_MAIN 2000
SRCS
px4_simple_app.c
DEPENDS
platforms__common
)

px4_add_module()方法从模块描述构建静态库。 MAIN块列出了模块的名称 。这会将该模块与NuttX一起注册,以便可以从PX4 shell或SITL控制台调用它。

编译链接

针对不同的目标平台,使用不同的make命令构建:

  • jMAVSim Simulator: make posix_sitl_default jmavsim
  • Pixhawk v1/2: make px4fmu-v2_default
  • Pixhawk v3: make px4fmu-v4_default

测试应用(硬件)

上传固件到开发板

在开发板上测试,使用如下命令上传PX4固件:

  • Pixhawk v1/2: make px4fmu-v2_default upload
  • Pixhawk v3: make px4fmu-v4_default upload

连接控制台

现在通过串口或USB连接到系统控制台。 点击ENTER将弹出shell提示符:

1
2
3
4
nsh>
nsh>help
nsh> px4_simple_app
Hello Sky!

测试应用(SITL)

如果您正在使用SITL,PX4控制台将自动启动。 与nsh控制台一样,您可以键入help以查看内置应用程序列表。

输入px4_simple_app以运行最小应用程序。

1
2
pxh> px4_simple_app
INFO [px4_simple_app] Hello Sky!

参考链接

  1. PX4编译开发环境配置,by jackhuang.
  2. PX4开发基本概念解读,by jackhuang.
  3. First Application Tutorial (Hello Sky),by dronecode.

OpenCV4.0相机标定教程

发表于 2019-04-28 | 更新于 2019-05-20

相机已经存在了很长时间。 然而,随着20世纪后期廉价针孔相机的推出,它们成为我们日常生活中的常见现象。 不幸的是,这种便宜与其价格有关:严重失真。 幸运的是,这些是常数,并且通过校准和一些重新映射,我们可以纠正这一点。 此外,通过校准,您还可以确定相机的自然单位(像素)与真实世界单位(例如毫米)之间的关系。这个校准过程就是相机标定。

理论

对于失真,OpenCV考虑了径向和切向因子。 对于径向因子,使用以下公式:

$$x_{distorted} = x( 1 + k_1 r^2 + k_2 r^4 + k_3 r^6) \ y_{distorted} = y( 1 + k_1 r^2 + k_2 r^4 + k_3 r^6)$$

因此,对于$(x,y)$坐标处的未失真像素点,其在失真图像上的位置将是$(x_{distorted},y_{distorted})$。 径向变形的存在表现为“桶状”或“鱼眼”效应。

由于摄像镜头与成像平面不完全平行,因此会发生偏心畸变。 它可以通过公式表示:

$$x_{distorted} = x + [ 2p_1xy + p_2(r^2+2x^2)] \ y_{distorted} = y + [ p_1(r^2+ 2y^2)+ 2p_2xy]$$

所以我们有五个失真参数,在OpenCV中呈现为一行矩阵,有5列:

$$distortion_coefficients=(k_1 \hspace{10pt} k_2 \hspace{10pt} p_1 \hspace{10pt} p_2 \hspace{10pt} k_3)$$

现在我们使用以下公式进行单位转换:

$$\left [ \begin{matrix} x \ y \ w \end{matrix} \right ] = \left [ \begin{matrix} f_x & 0 & c_x \ 0 & f_y & c_y \ 0 & 0 & 1 \end{matrix} \right ] \left [ \begin{matrix} X \ Y \ Z \end{matrix} \right ]$$

这里通过使用单应性坐标系(和$w = Z$)来解释$w$的存在。 未知参数是$f_x$和$f_y$(相机焦距)和($c_x,c_y$),它们是以像素坐标表示的光学中心。 如果对于两个轴,使用具有给定纵横比(通常为1)的共同焦距,则$f_y = f_x * a$,并且在上部公式中,我们将具有单个焦距$f$。 包含这四个参数的矩阵称为相机矩阵。 虽然无论使用何种相机分辨率,失真系数都是相同的,但应根据校准分辨率的当前分辨率进行缩放。

确定这两个矩阵的过程是校准。 通过基本几何方程计算这些参数。 使用的等式取决于所选择的校准对象。 目前,OpenCV支持三种类型的校准对象:

  • 古典黑白棋枰
  • 对称的圆圈图案
  • 不对称的圆圈图案

基本上,您需要使用相机拍摄这些图案的快照,然后让OpenCV找到它们。 每个找到的模式都会产生一个新的等式。 要求解方程,您需要至少预定数量的模式快照,以形成一个良好的方程系统。 棋盘图案的数量较高,圆圈图案的数量较少。 例如,理论上棋盘图案需要至少两个快照。 但是,实际上我们的输入图像中存在大量噪声,因此为了获得良好的结果,您可能需要至少10个不同位置的输入模式的快照。

目标

OpenCV4.0中相机标定样例程序的目标:

  • 确定失真矩阵
  • 确定相机矩阵
  • 从摄像机,视频和图像文件列表中获取输入
  • 从XML / YAML文件中读取配置
  • 将结果保存到XML / YAML文件中
  • 计算重新投影误差

源代码

您也可以在OpenCV源库的samples / cpp / tutorial_code / calib3d / camera_calibration /文件夹中找到源代码,或从此处下载。要使用该程序,请使用-h参数运行它。该程序有一个重要的参数:配置文件的名称。如果没有给出,那么它将尝试打开名为“default.xml”的那个。这是XML格式的示例配置文件。在配置文件中,您可以选择将相机用作输入,视频文件或图像列表。如果选择最后一个,则需要创建一个配置文件,用于枚举要使用的图像。这是一个例子。要记住的重要部分是需要使用绝对路径或应用程序工作目录中的相对路径来指定图像。您可以在上面提到的samples目录中找到所有这些。

应用程序启动时从配置文件中读取设置。虽然这是它的一个重要部分,但它与本教程的主题无关:摄像机校准。因此,我选择不在此处发布该部分的代码。有关如何执行此操作的技术背景,您可以在使用XML和YAML文件的文件输入和输出教程中找到。

构建相机标定程序

切换到camera_calibration示例教程源代码所在目录,创建build临时目录并创建CMakeLists.txt文件。

1
2
3
cd ~/opencv/samples/cpp/tutorial_code/calib3d/camera_calibration/
mkdir build
touch CMakeLists.txt

CMakeLists.txt文件内容如下:

1
2
3
4
5
6
7
cmake_minimum_required(VERSION 2.8)
set (CMAKE_CXX_STANDARD 11)
project( camera_calibration )
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
add_executable( camera_calibration camera_calibration.cpp )
target_link_libraries( camera_calibration ${OpenCV_LIBS} )

构建相机标定程序:

1
2
3
cd build
cmake ..
make

运行相机标定程序

运行相机标定程序的目的在于获得相机的失真参数和内外参,其中相机的失真参数和内参只需标定一次便不再变化。下面以标定笔记本自带摄像头说明运行相机标定程序的步骤。

修改标定配置参数

找到camera_calibration/in_VID5.xml文件,这是标定程序使用的配置文件,需要设置里面的几个参数。

  • 修改棋盘格交叉点参数
1
2
3
<!-- Number of inner corners per a item row and column. (square, circle) -->
<BoardSize_Width>9</BoardSize_Width>
<BoardSize_Height>6</BoardSize_Height>

需要特别注意的是,这里的宽度和高度是指内部交叉点的个数,而不是方形格的个数。如图1所示的棋盘格,内部交叉点的宽度是9,高度是6。请务必填写正确,否则无法标定。

用于相机标定的棋盘格

图1 用于相机标定的棋盘格
  • 修改每格的宽度

每格的宽度应设置为实际的毫米数,该参数的实际用途尚待考证。目前看来,即使设置的不准确也无大碍。根据我使用的棋盘格,设置棋盘格参数42。

1
2
<!-- The size of a square in some user defined metric system (pixel, millimeter)-->
<Square_Size>42</Square_Size>
  • 设置图像输入方式

例程提供了三种输入方式。不过,如果待标定的摄像头已经接入电脑,建议使用input camera方式。该方式只需要设置视频输入设备号,对于笔记本电脑来说,通常0表示笔记本自带摄像头,1表示外接摄像头。

1
2
3
4
5
6
  <!-- The input to use for calibration. 
To use an input camera -> give the ID of the camera, like "1"
To use an input video -> give the path of the input video, like "/tmp/x.avi"
To use an image list -> give the path to the XML or YAML file containing the list of the images, like "/tmp/circles_list.xml"
-->
<Input>"0"</Input>

执行相机标定程序

运行如下命令开始标定笔记本自带摄像头,标定完成后将得到保存相关参数的文件。

1
./camera_calibration ../in_VID5.xml

参考链接

  1. Using OpenCV with gcc and CMake,by opencv.
  2. Camera calibration With OpenCV,by opencv.
  3. C++11 activation with or <set (CMAKE_CXX_STANDARD)>,by stackoverflow.
  4. 计算机视觉之相机成像原理与坐标系转换,by jack huang.
  5. OpenCV 相机参数标定(Camera Calibration),by Wafei.
  6. 图像二维坐标转世界三维坐标, by 橙子.
  7. solvepnp三维位姿估算,by cocoaqin.
  8. 单目SLAM理论基础,by zhaoxuhui.
  9. SLAM相机位姿估计(1),by zhaoxuhui.
  10. 张氏法相机标定,by Lstyle.
  11. 机器视觉的相机标定到底是什么?, by zhihu.
  12. 相机标定究竟在标定什么?,by 许翔翔.

Ubuntu_16.04安装OpenCV的方法

发表于 2019-04-28 | 更新于 2019-05-17

本文记录在Ubuntu16.04 LTS操作系统中从源代码编译安装OpenCV的过程。

安装必需的软件包

1
2
3
[compiler] sudo apt-get install build-essential
[required] sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
[optional] sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev

下载OpenCV源代码

1
2
3
cd ~/<my_working_directory>
git clone https://github.com/opencv/opencv.git
git clone https://github.com/opencv/opencv_contrib.git

使用CMake构建OpenCV

创建临时的build目录

1
2
3
4
5
6
7
cd ~/opencv
# 查看并检出OpenCV最新发布版
git tag
git checkout 4.1.0

mkdir build
cd build

创建配置文件

1
2
3
4
5
$ cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local ..
# 可选,如使用opencv_contrib, 采用如下命令生成编译配置文件
$ cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local -D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib/modules ..
# 可选,构建示例程序和文档
cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local -D BUILD_EXAMPLES=1 -D BUILD_DOCS=1 ..

构建OpenCV

1
make -j3 # runs 3 jobs in parallel

安装OpenCV

1
sudo make install

参考链接

  1. Installation in Linux, by opencv.
  2. 4.0.0 does not produce pkgconfig file, by opencv.
  3. Pkg-config,by wikipedia.

PX4开发基本概念解读

发表于 2019-04-27 | 更新于 2019-06-19

进行PX4开发,必先了解PX4体系结构及相关概念。下面及简要介绍PX4开发的相关知识。

PX4体系结构

PX4由两个层次组成:一是飞行控制栈(flight stack),即自驾仪的软件解决方案,二是中间件,一种可以支持任意类型自主机器人的通用机器人中间件。

所有的无人机机型,事实上所有的包括船舶在内的机器人系统,都具有同一代码库。整个系统设计是反应式(reactive)的,这意味着:

  • 所有的功能被划分为可替换部件
  • 通过异步消息传递进行通信
  • 该系统可以应对不同的工作负载

除了这些运行时考虑之外,其模块化最大限度地提高了系统的可重用性。

PX4体系结构

图1 PX4体系结构

飞行控制栈

飞行控制栈是自主无人机的引导、导航和控制算法的集合。它包括用于固定翼,多旋翼和垂直起降机身的控制器以及用于姿态和位置的估计器。

图2显示了飞行控制栈的构建块的预览。 它包含从传感器,RC输入和自主飞行控制(导航器)到电机或伺服控制(执行器)的完整管道。

PX4飞行控制栈结构图

图2 PX4飞行控制栈结构图

估计器采用一个或多个传感器输入,组合它们,并计算无人机状态(例如来自IMU传感器数据的姿态)。

控制器是将设定值和测量或估计状态(过程变量)作为输入的组件。 其目标是调整过程变量的值,使其与设定值匹配。 输出是最终达到该设定点的校正。 例如,位置控制器将位置设定点作为输入,过程变量是当前估计的位置,输出是将车辆移向期望位置的姿态和推力设定点。

混合器接受强制命令(例如向右转)并将它们转换为单独的电机命令,同时确保不超过某些限制。 该平移特定于无人机类型并且取决于各种因素,例如关于重心的马达布置或无人机的转动惯量。

中间件

中间件主要包括嵌入式传感器的设备驱动程序,与外部世界的通信(协同计算机,地面控制站等)和uORB发布 - 订阅消息总线。

此外,中间件包括一个模拟层,允许PX4飞行代码在桌面操作系统上运行,并在模拟的“世界”中控制计算机建模的无人机。

更新速率

由于模块等待消息更新,因此驱动程序通常会定义模块更新的速度。 大多数IMU驱动器以1kHz采样数据,将其集成并以250Hz发布。 系统的其他部分,例如导航器,不需要如此高的更新速率,因此运行速度相当慢。

可以通过运行uorb top在系统上实时检查消息更新率。

运行时环境

PX4可在各种提供POSIX-API的操作系统上运行(例如Linux,macOS,NuttX或QuRT)。 它还应该具有某种形式的实时调度(例如FIFO)。

模块间通信(使用uORB)基于共享内存。 整个PX4中间件在单个地址空间中运行,即在所有模块之间共享存储器。

有两种不同的方式可以执行模块:

  • 任务:模块在自己的任务中运行,具有自己的堆栈和进程优先级(这是更常见的方式)。

  • 工作队列:模块在共享任务上运行,这意味着它不拥有堆栈。 多个任务在同一堆栈上运行,每个工作队列具有一个优先级。

    通过指定将来的固定时间来安排任务。 优点是它使用较少的RAM,但不允许任务在消息上休眠或轮询。

    工作队列用于周期性任务,例如传感器驱动器或陆地探测器。

操作系统相关信息

NuttX

NuttX是在飞行控制板上运行PX4的主要RTOS。 它是开源(BSD许可证),重量轻,高效且非常稳定。

模块作为任务执行:它们有自己的文件描述符列表,但它们共享一个地址空间。 任务仍然可以启动共享文件描述符列表的一个或多个线程。

每个任务/线程都有一个固定大小的堆栈,并且有一个周期性任务,它检查所有堆栈是否有足够的可用空间(基于堆栈着色)。

Linux / MacOS

在Linux或macOS上,PX4在单个进程中运行,并且模块在它们自己的线程中运行(NuttX上的任务和线程之间没有区别)。

PX4飞行模式

飞行模式定义了系统在任何给定时间的状态。用户可以使用远程遥控器或者QGroundControl地面站来进行飞行模式切换。

PX4飞行模式控制流程图

图3 PX4飞行模式控制流程图

Dronecode平台软硬件架构

Dronecode是开源的无人机平台,其软硬件体系结构如图4所示。图4左侧显示了一种可能的硬件配置,其中飞行控制器(浅蓝色)通过RTPS连接到感知计算机(深蓝色)。 感知计算机使用相机传感器阵列提供视觉控制和物体避免,并且具有单独的有效载荷相机。

图的右侧显示了端到端软件堆栈。 堆栈“近似”水平对齐图表的硬件部分,并进行颜色编码,以显示飞行控制器上运行的软件以及配套计算机上的软件。

Dronecode平台软硬件架构

图4 Dronecode平台软硬件架构

PX4位姿控制

多旋翼位置控制

PX4多旋翼位置控制

图5 PX4多旋翼位置控制

混合和执行器

PX4架构保证了核心控制器中不需要针对机身布局做特别处理。

混控指的是把输入指令(例如:遥控器打右转)分配到电机以及舵机的执行器(如电调或舵机PWM)指令。对于固定翼的副翼控制而言,每个副翼由一个舵机控制,那么混控的意义就是控制其中一个副翼抬起而另一个副翼落下。同样的,对多旋翼而言,俯仰操作需要改变所有电机的转速。

将混控逻辑从实际姿态控制器中分离出来可以大大提高复用性。

控制管线

一个特定的控制器(如姿态控制器)发送特定的归一化(-1..+1)的命令到给混合(mixing),然后混合后输出独立的PWM到执行器(电调,舵机等).在经过输出驱动如(串口,UAVCAN,PWM)等将归一化的值再转回特性的值(如输出1300的PWM等)。

PX4控制管线

图6 PX4控制管线

控制组

PX4 有输入组和输出组的概念,顾名思义:控制输入组(如: attitude),就是用于核心的飞行姿态控制,(如: gimbal )就是用于挂载控制. 一个输出组就是一个物理总线,如前8个PWM组成的总线用于舵机控制,组内带8个归一化(-1..+1)值,一个混合就是用于输入和输出连接方式(如:对于四轴来说,输入组有俯仰,翻滚,偏航等,对于于向前打俯仰操作,就需要改变输出组中的4个电调的PWM输出值,前俩个降低转速,后两个增加转速,飞机就向前)。

对于简单的固定翼来说,输入0(roll),就直接连接到输出的0(副翼)。对于多旋翼来说就不同了,输入0(roll)需要连接到所有的4个电机。

参考链接

  1. PX4 Development Guide (STABLE - v1.8.2),by Dronecode.
  2. PX4开发指南, by Dronecode.

PX4编译开发环境配置

发表于 2019-04-26 | 更新于 2019-06-19

拟在基于NuttX的硬件平台如Pixhawk系列开源硬件平台上运行自定义的Px4自驾仪软件,因此需要建立Px4的编译开发环境。以官方文档推荐,在Ubuntu 16.04 LTS操作系统上建立Px4编译开发环境为例,记录整个配置过程。

安装Ubuntu 16.04 LTS

官方推荐在Mac OS和Linux上进行开发,因此选择安装Ubuntu 16.04 LTS作为Px4开发的操作系统。主要步骤如下:

  1. 安装VirtualBox系统虚拟机
  2. 在VirtualBox创建虚拟机
  3. 在虚拟机中安装Ubuntu 16.04 LTS操作系统

Ubuntu中安装工具链

权限设置

为了使当前用户能够访问串口,将当前用户添加到dialout组。

1
2
sudo usermod -a -G dialout $USER
reboot

安装工具链

Pixhawk/NuttX (and jMAVSim)

针对基于NuttX的硬件平台如Pixhawk构建开发工具链,步骤如下:

  1. 下载ubuntu_sim_nuttx.sh
  2. 运行脚本ubuntu_sim_nuttx.sh
  3. 完成后重启
1
2
3
wget https://raw.githubusercontent.com/PX4/Devguide/master/build_scripts/ubuntu_sim_nuttx.sh
source ubuntu_sim_nuttx.sh
reboot

编译Px4软件

下载Px4源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
mkdir -p ~/src
cd ~/src
git clone https://github.com/PX4/Firmware.git

cd Firmware

# list the releases (tags)
git tag -l

# Checkout code for particular tag (e.g. for tag v1.8.2 stable version)
git checkout v1.8.2

git submodule update --init --recursive

现在可以通过编译源代码来构建二进制文件。在直接使用硬件前,推荐先进行仿真。

jMAVSim仿真器

在直接使用硬件之前,以jMAVSim仿真器为目标平台构建PX4,验证PX4的正确性。注意在virtualbox中启动3D图形加速,防止jMAVSim运行出错!

1
2
3
4
make posix jmavsim

# 起飞四旋翼无人机
pxh> commander takeoff

基于NuttX / Pixhawk的硬件板

以Pixhawk为目标平台,构建PX4。

1
2
cd Firmware
make px4fmu-v2_default

注意到“make”是一个字符命令编译工具,“px4fmu-v2”是硬件/ardupilot版本,“default”是默认配置,所有的PX4编译目标遵循这个规则。

成功编译的最后输出是这样的:

1
2
3
4
5
[100%] Linking CXX executable firmware_nuttx
[100%] Built target firmware_nuttx
Scanning dependencies of target build/firmware_px4fmu-v2
[100%] Generating nuttx-px4fmu-v2-default.px4
[100%] Built target build/firmware_px4fmu-v2

通过在命令后面添加‘upload’,编译的二进制程序就会通过USB上传到飞控硬件:

1
make px4fmu-v2_default upload

上传成功时输出情况如下:

1
2
3
4
5
6
Erase  : [====================] 100.0%
Program: [====================] 100.0%
Verify : [====================] 100.0%
Rebooting.

[100%] Built target upload

参考链接

  1. PX4 Development Guide (STABLE - v1.8.2),by Dronecode.
  2. PX4开发指南, by Dronecode.
  3. running JMAVSim in vmware fails, by jMAVSim issues.

硬件在环与软件在环概念辨析

发表于 2019-04-25

在PX4自驾仪软件的二次开发过程中,涉及硬件在环与软件在环两个概念,不易理解。下面对这两个概念进行辨析。

基本概念

硬件在环

硬件在环(Hardware in the Loop,简称HIL)即硬件在控制环路,是一种半实物仿真。根据控制器和控制对象是否为真实硬件,分为以下两种硬件在环方式:

  • 虚拟控制器+实际对象=快速控制原型(RCP)仿真系统,是系统的一种半实物仿真;
  • 实际控制器+虚拟对象=硬件在回路(HIL)仿真系统,是系统的另一种半实物仿真。

硬件在环主要用于测试控制器系统。

软件在环

软件在环主要测试控制器模型与控制器模型代码实现之间的一致性。

处理器在环

软件在环主要测试控制器模型与控制器模型代码实现在目标处理器上运行之间的一致性。

模型在环

模型在环(Model in the Loop,简称MIL)是用模型驱动进行嵌入式系统的开发时,在开发阶段初期及建模阶段中进行的仿真方式。嵌入式系统需和其运作的环境互动,一般会预期有合理的传感器信号为其输入,也会依输入及系统设计来驱动实体系统。为了使系统正常工作,需要将嵌入式系统的环境纳入仿真考量范围内。若嵌入式系统模型和环境模型连接,一起进行仿真,则即称为模型在环模拟。

模型在环主要用于测试控制算法,其控制器模型和控制器对象都是虚拟的。

参考链接

  1. 请明白人通俗的解释一下什么叫硬件在环?, by zhihu.
  2. 简单说说MIL、SIL、PIL和HIL, by Wangxn665.
  3. 模型在环, by wikipedia.
  4. 硬件在环, by 百度百科.

机器人路径规划、轨迹规划和运动规划概念辨析

发表于 2019-04-17

在机器人自动控制研究中,路径规划、轨迹规划和运动规划三个概念总是混淆不清,难以捉摸。下面结合各种资料,给出我个人的一些理解,对这三个概念进行辨析。

基本概念

路径规划(path planning)

路径是机器人位姿的一定序列,不考虑机器人位姿参数随时间变化的因素。路径规划(一般指位置规划)是找到一系列要经过的路径点,路径点是空间中的位置或关节角度。

轨迹规划(trajectory planning)

路径是机器人位姿的一定序列,不考虑机器人位姿参数随时间变化的因素。路径规划(一般指位置规划)是找到一系列要经过的路径点,路径点是空间中的位置或关节角度,而轨迹规划是赋予路径时间信息。

运动规划(motion planning)

运动规划就是在给定的位置A与位置B之间为机器人找到一条符合约束条件的路径。运动规划包含路径规划和轨迹规划。

运动规划,又称运动插补,是在给定的路径端点之间插入用于控制的中间点序列从而实现沿给定的平稳运动。

运动控制则是主要解决如何控制目标系统准确跟踪指令轨迹的问题,即对于给定的指令轨迹,选择适合的控制算法和参数,产生输出,控制目标实时,准确地跟踪给定的指令轨迹。

参考链接

  1. 运动(motion)规划、路径(path)规划和轨迹(trajectory)规划之区别,by Roger_Ceng.
  2. 运动规划/路径规划/轨迹规划,by 小白鼠2号.
  3. 运动规划 | 简介篇,by qqfly.
  4. 无人车运动规划,路径规划,轨迹规划的区别和联系?, by zhihu.

FlightGear简易飞行教程

发表于 2019-03-29 | 更新于 2021-01-09

FlightGear是一个始于1997年多平台飞行模拟器、自由软件项目。下面简要介绍如何在FlightGear中驾驶飞行。

常用快捷键

飞机操纵

  • 9/3

推力:9增加推力(油门),3减小推力(油门)

  • 4/6

副翼:4向左滚转,6向右滚转

  • 8/2

升降舵:8推杆低头,2拉杆抬头

  • 0/Enter

方向舵:0向右偏航,Enter向右偏航

  • 5

居中副翼/升降舵/方向舵

  • ]/[

放/收襟翼

  • g/G

收/放起落架

  • b/B

刹车(全部轮胎)/或释放刹车

视角变换

  • x/X

放大/缩小

  • v/V

切换飞行员的观测模式

  • Tab

循环切换鼠标模式:正常模式(默认)、控制模式和查看模式。

自动驾驶

  • Ctrl + A

高度保持开关

  • Ctrl + G

下滑角跟随开关

  • Ctrl + H

航向保持开关

  • Ctrl + N

NAV 开关

  • Ctrl + T

地形跟随开关

  • Ctrl + U

高度增加 1000 英尺(紧急情况)

起飞教程

起飞步骤如下:

1.启动引擎

在驾驶舱内通过按键启动飞机引擎的过程很麻烦,且各种类型飞机引擎启动过程不一样。幸运的是,FlightGear的飞机菜单中会有自动启动或快速启动的子菜单,点击它们自动启动飞机引擎和各种航电设备。

2.释放刹车

使用快捷键B释放刹车。

3.滑跑起飞

飞机尽量在跑道中央进行滑跑起飞,使用快捷键“0/Enter”控制飞机方向舵,使飞机在跑道中央滑跑; 当飞机达到起飞速度(一般200~300km/h)时,先使用快捷键“5”居中副翼/升降舵/方向舵,以降低飞机在空中操纵的难度,再使用快捷键“8/2”操纵飞机升降舵,注意应避免仰角过大。

注意,FlightGear 2020.3 版本中F16不支持数字小键盘!

武器使用教程

各种战斗机可通过飞机菜单选择不同武器加载方案。但各种战斗机的武器使用方法不一样,对应武器发射的快捷键也不一样,可通过菜单“Help->Aircraft Help”查看具体飞机的自定义快捷键。下面以官方飞机库中的F15和F16为例说明武器使用方法。

F15

F15武器使用步骤如下:

1.打开Master ARM开关

该军械总开关防止武器误发射,使用快捷键Ctrl+w控制。

2.选择武器

可选择航炮和导弹等武器,使用快捷键m控制

3.发射航炮或释放导弹

使用快捷键e控制,注意航炮按e就发射,而导弹按e得持续3秒钟才能释放导弹。

4.使用诱饵弹

使用快捷键Ctrl+q释放诱饵弹。

F16

F16武器使用步骤如下:

1.打开Master ARM开关

该开关防止武器误发射,使用快捷键m控制。

2.选择武器

可选择航炮和导弹等武器,使用快捷键w控制

3.发射航炮或释放导弹

使用快捷键e控制,注意航炮按e就发射,而导弹按e得持续3秒钟才能释放导弹。

4.使用诱饵弹

使用快捷键q释放诱饵弹。

参考链接

  1. FlightGear,by wikipedia.
  2. FlightGear基本飞行操作快捷键,by zxc.
  3. “illegal argument” on some specific aircrafts,by flightgear forum.

JSBSim编程实践之入门

发表于 2019-03-27 | 更新于 2020-01-07

JSBSim是一个开源跨平台的飞行动力学模型(FDM)软件库,用于模拟航空航天飞行器的飞行动力学。 该库已被纳入飞行模拟软件包FlightGear和OpenEaagles。JSBSim可以独立运行,通过命令行参数指定飞行器和初始状态,进行简单情境下的飞行动力学仿真,也可以将JSBSim作为代码库,编程实现飞行器模型加载,设置输入,获得输出。下面即介绍在Linux平台编程调用JSBSim库的方法和步骤。

基础知识

gcc与g++

GNU编译器套装(英语:GNU Compiler Collection,缩写为GCC),指一套编程语言编译器,以GPL及LGPL许可证所发行的自由软件,也是GNU项目的关键部分,也是GNU工具链的主要组成部分之一。GCC(特别是其中的C语言编译器)也常被认为是跨平台编译器的事实标准。

通常gcc用于编译链接c代码文件,而g++用于编译链接c++代码文件,但它们的使用方法很类似。下面介绍gcc和g++的常用选项。

  • 添加头文件搜索路径
1
gcc foo.c -I /home/xiaowp/include -o foo
  • 添加动态库搜索路径
1
gcc foo.c -L /home/xiaowp/lib -lfoo -o foo
  • 添加静态库搜索路径
1
gcc foo.c -L /home/xiaowp/lib -static -lfoo -o foo

编程实践

最简仿真

下面是JSBSim参考手册中的最简单实例,因JSBSim的不断开发,JSBSim参考手册中该编程实例有点过时,因此进行了少量修改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <FGFDMExec.h>
#include <sg_path.hxx>

using namespace std;

int main(int argc, char **argv)
{
JSBSim::FGFDMExec FDMExec;
bool result = true;

FDMExec.LoadScript(SGPath::fromUtf8(argv[1]));

while (result) result = FDMExec.Run();
}

从上述代码可知,调用JSBSim的主要方法是利用FGFDMExec类,通过实例化一个FGFDMExec类,就相当于获得了一个运行JSBSim仿真的工具箱,通过这个工具箱就可以调用JSBSim的大部分功能,实现我们要的仿真目标。

接下来对该实例进行编译链接,使用如下命令:

1
2
# jsbsim_script.cpp是上述实例的代码文件
g++ jsbsim_script.cpp -I ../jsbsim/src/ -I../jsbsim/src/simgear/misc -L ../jsbsim/build/src/ -static -l JSBSim -o jsbsim_script

测试该实例,使用如下命令:

1
2
3
4
# jsbsim是JSBSim项目文件夹
# JSBSimTest是JSBSim测试实例所在文件夹
cd jsbsim
../JSBSimTest/jsbsim_script ./scripts/c1723.xml

参考链接

  1. JSBSim编程实践,by 32768.
  2. 战斗机与引擎速查,by 么的聊.
  3. JSBSim学习笔记(3)—— 基本概念,by 么的聊.
  4. JSBSim学习笔记(6)——飞行控制系统,by 么的聊.
  5. Linux平台编译安装测试JSBSim,by jack huang.
  6. JSBSim Reference Manual ,by jsbsim.
  7. gcc和g++头文件和库路径的寻找和添加,by 周学伟.
  8. GCC,by wikipedia.
  9. WHAT IS THE DIFFERENCE BETWEEN GCC AND G++,by KITTY GUPTA.
上一页1…414243…53下一页

Jack Huang

521 日志
67 标签
© 2025 Jack Huang
由 Hexo 强力驱动
|
主题 — NexT.Muse