Jack Huang's Blog


  • 首页

  • 标签

  • 归档

  • 搜索

光线追踪基本概念入门

发表于 2019-05-26 | 更新于 2022-05-11

光线追踪(Ray tracing)是三维计算机图形学中的特殊渲染算法,跟踪从眼睛发出的光线而不是光源发出的光线,通过这样一项技术生成编排好的场景的数学模型显现出来。光线追踪的优点可以提供更为真实的光影效果,缺点是计算量巨大。

基本概念

光线追踪与光栅化渲染作为相对的两个概念,理解光栅化渲染更能解释光线追踪的概念。

光栅化渲染是将向量图形格式表示的图像转换成位图以用于显示器或者打印机输出的过程,如图1所示。

光线追踪示意图

图1 光栅化渲染示意图

光线追踪的示意图如图2所示。[Whitted 1980]提出了使用光线跟踪来在计算机上生成图像的方法,这一方法后来也被称为经典光线跟踪方法或Whitted-style 光线跟踪方法。其主要思想是从视点向成像平面上的像素发射光线,找到与该光线相交的最近物体的交点,如果该点处的表面是散射面,则计算光源直接照射该点产生的颜色;如果该点处表面是镜面或折射面,则继续向反射或折射方向跟踪另一条光线,如此递归下去,直到光线逃逸出场景或达到设定的最大递归深度。这种经典的方法可以产生镜面反射、折射、阴影等效果,不过不能实现其他的全局光照的效果。

光线追踪示意图

图2 光线追踪示意图

辐射度学基本量

图形学模拟可见光与各种材质的交互,这个过程涉及到能量的传输。辐射度学(Radiometry)是度量电磁辐射能量传输的学科,也是基于物理着色模型的基础。

  • 能量

能量(Energy),用符号Q表示,单位焦耳(J),每个光子都具有一定量的能量,和频率相关,频率越高,能量也越高。

  • 功率

功率(Power),单位瓦特(Watts),或者焦耳/秒(J/s)。辐射度学中,辐射功率也被称为辐射通量(Radiant Flux)或者通量(Flux),指单位时间内通过表面或者空间区域的能量的总量,用符号\Phi 表示,定义 $\Phi = \frac{ dQ}{dt}$。

  • 辐照度和辐出度

辐照度(Irradiance),指单位时间内到达单位面积的辐射能量,或到达单位面积的辐射通量,也就是通量对于面积的密度。用符号E表示,单位 $W / m^{2}$ 。定义为 $E = \frac{d\Phi }{dA}$。

辐出度(Radiant Existance),也称为辐射出射度、辐射度(Radiosity),用符号M表示。辐出度与辐照度类似,唯一的区别在辐出度衡量的是离开表面的通量密度,辐照度衡量的是到达表面的通量密度。辐照度和辐出度都可以称为辐射通量密度(Radiant Flux Density)。

  • 辐射强度

立体角则是度量三维角度的量,用符号 $\omega$ 表示,单位为立体弧度(也叫球面度,Steradian,简写为sr),等于立体角在单位球上对应的区域的面积(实际上也就是在任意半径的球上的面积除以半径的平方 $\omega = \frac {s}{r^{2} }$ ),单位球的表面积是 $4\pi$ ,所以整个球面的立体角也是$4\pi$ 。

辐射强度(Radiant Intensity),指通过单位立体角的辐射通量。用符号I表示,单位 $W / sr$,定义为 $I = \frac{d \Phi }{d \omega }$ 。之所以引入辐射强度,是因为有时候要度量通过一个点的通量的密度,但因为点的面积是0,无法使用辐照度,所以引入辐射强度。辐射强度不会随距离变化而变化,不像点光源的辐照度会随距离增大而衰减,这是因为立体角不会随距离变化而变化。

  • 辐射率

辐射率(Radiance),指每单位面积每单位立体角的辐射通量密度。用符号 $L$ 表示,单位 $W/m^{2} sr$ ,定义为 $L = \frac{d \Phi }{d\omega d A^{\bot } }$ 。其中 $dA^{\bot}$是微分面积dA在垂直于光线方向的投影。

渲染方程(The Rendering Equation)

[Kajiya 1986]第一次将渲染方程引入图形学,使用它来解释光能传输的产生的各种现象。这一方程描述了场景中光能传输达到稳定状态以后,物体表面某个点在某个方向上的辐射亮度(Radiance)与入射辐射亮度等的关系。

$$L_o(x,w_o)=L_e(x,w_0)+\int_\Omega{f_r(x,w_i,w_0)L_i(x,w_i)cos\theta_idw_i}$$

其中,$L_o(x,w_o)$ 表示物体表面点 $x$ 处在方向 $𝜔_𝑜$ 上出射的辐射亮度,$𝐿𝑒(𝑥, 𝜔_0)$ 表示在该点该方向上自辐射的亮度。$𝐿𝑖(𝑥,𝜔_𝑖)$ 表示该点处 $𝜔_𝑖$ 方向入射的辐射亮度,$𝑓𝑟(𝑥, 𝜔_𝑖, 𝜔_𝑜)$ 是双向反射分布函数(BRDF),描述的是入射方向的辐射亮度对出射方向的贡献,$cos 𝜃𝑖$ 是$𝜔_𝑖$与表面法向的点积。在这一方程的基础上,辐射度方法和蒙特卡罗光线跟踪的方法就可以看成是对方程中积分的不同的数值求解方法。

BRDF描述的是表面本身的性质,比如它的光滑程度,导电程度等等。由于四面八方的光线都会作用在这个表面,所以我们需要对所有方向进行积分,也就是一个球面上的积分,考虑到积分项中的 $(w_i\cdot n)$ ,那么只有位于正半空间的方向才会对最终积分有贡献,所以最后这个球面的积分就变成了一个半球的积分,如图3所示。

光线追踪示意图

图3 BRDF示意图

双向反射分布函数(bidirectional reflectance distribution function, BRDF)

在计算机图形学领域,着色(Shading)是指根据表面或者多边形相对光源和相机的角度和距离来计算它的颜色的过程。不同的用途可以使用不同的着色算法,CAD等追求响应速度的交互式图形领域可以使用简单快速的着色算法,卡通油画等艺术效果可以使用非真实感(Nonphotorealistic)着色算法,而追求真实感的CG电影或游戏则可以使用基于物理建模的着色算法。而BRDF是基于物理建模的着色算法的理论基础。

我们看到一个表面,实际上是周围环境的光照射到表面上,然后表面将一部分光反射到我们眼睛里。双向反射分布函数BRDF(Bidirectional Reflectance Distribution Function)就是描述表面入射光和反射光关系的。

对于一个方向的入射光,表面会将光反射到表面上半球的各个方向,不同方向反射的比例是不同的,我们用BRDF来表示指定方向的反射光和入射光的比例关系,BRDF定义为:

$$f(l,v)=\frac{dL_o(v)}{dE(l)}$$

其中,$f$就是BRDF,$l$是入射光方向,$v$是观察方向,也就是我们关心的反射光方向。$d L_o(v)$ 是表面反射到$v$方向的反射光的微分辐射率。表面反射到$v$方向的反射光的辐射率为$L_o(v)$,来自于表面上半球所有方向的入射光线的贡献,而微分辐射率 $d L_o(v)$ 特指来自方向 $l$ 的入射光贡献的反射辐射率。$dE(l)$是表面上来自入射光方向 $l$ 的微分辐照度。表面接收到的辐照度为 $E$ ,来自上半球所有方向的入射光线的贡献,而微分辐照度 $dE(l)$ 特指来自于方向 $l$ 的入射光。

光照模型(illumination model)

当光照射到物体表面时,物体对光会发生反射、透射、吸收、衍射、折射、和干涉,其中被物体吸收的部分转化为热,反射、透射的光进入人的视觉系统,使我们能看见物体。为模拟这一现象,我们建立一些数学模型来替代复杂的物理模型,这些模型就称为明暗效应模型或者光照明模型。

局部光照模型

在真实感图形学中,仅处理光源直接照射物体表面的光照明模型被称为局部光照明模型。局部光照明模型的分类如图4所示。

局部光照模型分类

图4 局部光照模型分类

局部光照模型是一种比较简单的光照模型,它是与光栅化渲染算法相适应的,光栅化算法一次只考虑一个像素的光照强度,因此局部光照模型不能计算某像素受其他像素影响的光照强度部分。也就是说,局部光照模型只对物体进行直接光照的计算,而不考虑其他的间接影响。

全局光照模型

全局光照模型是基于光学物理原理的,光照强度的计算依赖于光能在现实世界中的传播情况,考虑光线与整个场景中各物体表面及物体表面间的相互影响,包括多次反射 、透射 、散射等。因此,与局部光照模型相比,全局光照模型需要相当大的计算量 ,但同时也能取得非常逼真的真实效果 。全局光照模型分类如图5所示。

全局光照模型分类

图5 全局光照模型分类

求交检测

在光线追踪过程中,从眼睛发出的光线与3D模型的三角面求交是一个复杂问题。通常精致的3D模型可能由几十万至上百万三角面构成,如果采用穷举法求交点,其时间复杂度将是O(n), 过于复杂。为了减少不必要的求交检测,应采用空间划分技术,最常用的是平衡kdtree算法,提高求交检测的效率。

k-d tree

在计算机科学里,k-d树( k-维树的缩写)是在k维欧几里德空间组织点的数据结构。k-d树可以使用在多种应用场合,如多维键值搜索(例:范围搜寻及最邻近搜索)。k-d树是空间二分树(Binary space partitioning )的一种特殊情况。

k-d树是每个节点都为k维点的二叉树。所有非叶子节点可以视作用一个超平面把空间分割成两个半空间。节点左边的子树代表在超平面左边的点,节点右边的子树代表在超平面右边的点。选择超平面的方法如下:每个节点都与k维中垂直于超平面的那一维有关。因此,如果选择按照x轴划分,所有x值小于指定值的节点都会出现在左子树,所有x值大于指定值的节点都会出现在右子树。这样,超平面可以用该x值来确定,其法线为x轴的单位向量。

参考链接

  1. 光线追踪,by wikipedia.
  2. 栅格化,by wikipedia.
  3. 渲染,by wikipedia.
  4. 光线追踪基本概念与代码实现,by 鹅城惊喜师爷.
  5. 一篇光线追踪的入门,by 洛城.
  6. 基于蒙特卡罗的光线跟踪绘制方法,by 严俊.
  7. 基于物理着色:BRDF,by Maple.
  8. Monte-Carlo Ray Tracing System (一)原理以及设计,by 已退逼乎.
  9. 冯氏光照模型–镜面光的计算,by MooAiFighting.
  10. 什么是光照模型,by 黄琦.
  11. 蒙特卡洛光线追踪,by sunacmer.
  12. k-d树,by wikipedia.
  13. 辐射强度、辐亮度、辐照度——一文搞定,by 三眼二郎.
  14. 从光栅化到光线追踪,by CrazyEngineCo.
  15. windows下没有srand48和drand48的解决方法,by 查志强.
  16. 辐射照度、辐射强度、光照度、发光强度(差异以及如何相互转换)(易懂讲解),by 三眼二郎.

SLAM中位姿估计的数学基础

发表于 2019-05-20 | 更新于 2021-05-10

同步定位与地图构建(SLAM或Simultaneous localization and mapping)是一种概念:希望机器人从未知环境的未知地点出发,在运动过程中通过重复观测到的地图特征(比如,墙角,柱子等)定位自身位置和姿态,再根据自身位置增量式的构建地图,从而达到同时定位和地图构建的目的。

SLAM的核心工作有两个:

  • 地图构建

研究如何把从一系列传感器收集到的信息,集成到一个一致性的模型上的问题。它可以被描述为第一核心问题:这个世界长什么样?地图构建的核心部分是环境的表达方式以及传感器数据的解释。

  • 定位

研究在地图上估测机器人的坐标和姿势形态的问题;换而言之,机器人需要回答这里的第二核心问题,我在哪?典型的解包含以下两个方面:追踪——通常机器人的初始位置已知;全局定位——通常只给出很少,甚至不给出有关于起始位置环境特征的先验信息。

下面主要介绍SLAM定位研究中涉及的数学知识。

向量点积

有如下两个向量:

$$a=\begin{pmatrix}
a_{1}\
a_{2}\
a_{3}
\end{pmatrix},b=\begin{pmatrix}
b_{1}\
b_{2}\
b_{3}
\end{pmatrix}$$

它们的点乘定义如下:

$$a\cdot b=a^{T}\cdot b = \sum_{i=1}^{3}a_{i}b_{i}=\left | a \right |\left | b \right |cos<a,b>$$

即两个向量点乘等于一个向量的转置乘以另一个向量。

向量叉积

两个向量做叉积结果还是一个向量,这个向量垂直于这两个做叉积的向量所组成的平面。

$$
a\times b=\begin{vmatrix}
i & j & k\
a_{1} & a_{2} & a_{3}\
b_{1} & b_{2} & b_{3}
\end{vmatrix}=(a_{2}b_{3}-a_{3}b_{2})i+(a_{3}b_{1}-a_{1}b_{3})j+(a_{1}b_{2}-a_{2}b_{1})k $$

为了计算方便,将两个向量写成行列式的形式,然后按对角线法则计算行列式的值。i、j、k分量分别即代表x、y、z轴方向的分量。写成列向量的形式如下:

$$
\begin{pmatrix}
a_{2}b_{3}-a_{3}b_{2}\
a_{3}b_{1}-a_{1}b_{3}\
a_{1}b_{2}-a_{2}b_{1}
\end{pmatrix}=\begin{pmatrix}
0\cdot b_{1}-a_{3}b_{2}+a_{2}b_{3}\
a_{3}b_{1}-0\cdot b_{2}-a_{1}b_{3}\
-a{2}b_{1}+a_{1}b_{2}+0\cdot b_{3}
\end{pmatrix}=\begin{pmatrix}
0 & -a_{3} & a_{2}\
a_{3} & 0 & -a_{1}\
-a_{2} & a_{1} & 0
\end{pmatrix}\begin{pmatrix}
b_{1}\
b_{2}\
b_{3}
\end{pmatrix} $$

再将其写成与b相乘的矩阵形式,提取系数矩阵。这个系数矩阵就称作向量a的反对称矩阵,用a^记。所谓反对称矩阵,是指满足下面这个条件的矩阵。

$$A^{-1}=-A$$

因为向量叉积的结果是一个向量,因此可以用来表示旋转,结果向量的方向为旋转轴,大小为旋转角。结果可以看作一个旋转向量。

对极几何

两个相机在不同位置拍摄同一物体,两张照片中的景物有重叠部分,那么理论上这两张照片会存在一定的对应关系,而对极几何就是探索描述它们之间对应关系的工具。相机在不同位置拍摄同一物体示意图如图1所示。

相机在不同位置拍摄同一物体示意图

图1 相机在不同位置拍摄同一物体示意图

图中的概念有:

  • 极点e:分别是左边相机中心在右图像平面上的像,右相机中心在左像平面上的像。

  • 极平面:两个相机中心和空间中某店p形成的平面。

  • 极线l:极平面分别和两个像平面的交线。

对极几何则是描述这几个量之间的对应关系。直观讲,从左图的角度看,如果不知道p点的深度信息,射线op是这个点可能出现的空间位置,因为该射线上的点都会投影到同一个像素点,同时,如果不知道p点的具体位置,那么当在右图的位置看时,极线 l’ 就是点p可能出现的位置,即在这条线上的某个地方。如图2所示:

物体位置示意图

图2 物体位置示意图

在计算机视觉中,基础矩阵(Fundamental matrix) F 是一个3×3的矩阵,表达了立体像对的像点之间的对应关系。在对极几何中,对于立体像对中的一对同名点,它们的齐次化图像坐标分别为 $p$ 与 $p’$, ${\displaystyle \mathrm {F} p}$ 表示一条必定经过 $p’$的直线(极线)。这意味着立体像对的所有同名点对都满足:

$${\displaystyle p’^{\top }\mathrm {F} p=0.}$$

F矩阵中蕴含了立体像对的两幅图像在拍摄时相互之间的空间几何关系(外参数)以及相机检校参数(内参数),包括旋转、位移、像主点坐标和焦距。因为 F 矩阵的秩为2,并且可以自由缩放(尺度化),所以只需7对同名点即可估算出F的值。

基础矩阵这一概念由Q. T. Luong在他那篇很有影响力的博士毕业论文中提出。Faugeras则是在1992年发表的著作中以上面的关系式给出了 F 矩阵的定义。尽管Longuet-Higgins提出的本质矩阵也满足类似的关系式,但本质矩阵中并不蕴含相机检校参数。本质矩阵与基础矩阵之间的关系可由下式表达:

$$ {\displaystyle \mathrm {E} =\mathrm {K’^{\top }} \mathrm {FK} .}$$

其中 $K$和 $K’$分别为两个相机的内参数矩阵。

参考链接

  1. SLAM数学基础,by zhaoxuhui.
  2. 即时定位与地图构建,by wikipedia.
  3. 大牛讲堂|SLAM第一篇:基础知识, by 地平线HorizonRobotics.
  4. 学习SLAM需要哪些预备知识?,by wikipedia.
  5. 计算机视觉中的数学方法,by 吴福朝.
  6. 对极几何及单应矩阵, by Rap_God.
    ​

PX4无人机MAVROS外部控制教程

发表于 2019-05-15

PX4中的offboard模式能够接受来自外部的控制指令,搭配机载或支持MAVROS的协同计算机,可在PX4飞控平台上加入视觉处理或人工智能,以实现无人机自动控制功能。下面即介绍如何在基于MAVROS的协同计算机上运行程序控制PX4无人机。具体过程如下:

PX4固件参数设置

在开始无人机外部控制开发之前,您需要在PX4固件中设置两件事:

  • 将RC开关映射到场外模式激活

要执行此操作,请在QGroundControl中加载参数并查找RC_MAP_OFFB_SW参数,您可以为其分配要用于激活offboard模式的RC通道。 以这样一种方式映射事物是非常有用的。当你脱离offboard模式时,你会进入位置控制。

虽然此步骤不是强制性的,因为您可以使用MAVLink消息激活offboard模式。 我们认为这种方法更安全。

  • 启用配套计算机接口

查找SYS_COMPANION参数并将其设置为921600(推荐)或57600. 此参数将激活Telem2端口上的MAVLink流,其中包含特定于板载模式的数据流以及相应的波特率(921600 8N1或57600 8N1)。

本人实验测试时SYS_COMPANION参数设置成Companion Link(57600) 。此外要注意通过Telem2端口的无线收发装置与地面支持MAVROS的具有无线收发装置的协同计算机连接。并长按安全锁手动解锁无人机。

安装MAVROS

在地面协同计算机上安装MAVROS请参考Ubuntu16.04安装MAVROS,完成后使用如下命令启动MAVROS:

1
2
3
$ roscore
# 启动MAVROS,链接到本地ROS
$ roslaunch mavros px4.launch fcu_url:=serial:///dev/ttyUSB0:57600

构建Offboard示例程序

ROS节点Offboard示例程序的构建请参考ROS构建Package和Node的教程,完成后使用如下命令启动Offboard示例程序:

1
2
3
$ cd catkin_ws/
$ source devel/setup.bash
$ rosrun offboard offboard_node

参考链接

  1. PX4软件在环仿真之MAVROS外部控制,by jackhuang.
  2. Offboard Control, by dronecode.

PX4软件在环仿真之MAVROS外部控制

发表于 2019-05-15

PX4软件在环仿真之MAVROS外部控制将使用基于MAVROS的PX4外部控制ROS节点,控制在Gazebo仿真环境中的四悬翼无人机,如图1所示。

px4软件在环仿真

图1 px4软件在环仿真

具体步骤如下:

构建PX4自驾仪

请参考PX4编译开发环境配置和Development Environment on Linux配置PX4编译开发环境。需要指出的是,为使用Gazebo仿真环境,PX4开发工具链使用脚本ubuntu_sim_ros_gazebo.sh构建。

PX4编译开发环境配置完成后,使用如下命令启动:

1
2
$ cd ~/src/Firmware
$ make posix_sitl_default gazebo

安装MAVROS

安装MAVROS请参考Ubuntu16.04安装MAVROS,完成后使用如下命令启动MAVROS:

1
2
3
$ roscore
# 启动MAVROS,链接到本地ROS
$ roslaunch mavros px4.launch fcu_url:="udp://:14540@127.0.0.1:14557"

构建Offboard示例程序

ROS节点Offboard示例程序的构建请参考ROS构建Package和Node的教程,完成后使用如下命令启动Offboard示例程序:

1
2
3
$ cd catkin_ws/
$ source devel/setup.bash
$ rosrun offboard offboard_node

最终能够在Gazebo仿真环境中观察到四悬翼无人机垂直起飞到2米的高度。

参考链接

  1. Ubuntu16.04安装MAVROS,by jackhuang.
  2. ROS构建Package和Node的教程,by jackhuang.
  3. PX4编译开发环境配置,by jackhuang.
  4. Development Environment on Linux, by dronecode.

ROS构建Package和Node的教程

发表于 2019-05-15

ROS(机器人操作系统,Robot Operating System),是专为机器人软件开发所设计出来的一套电脑操作系统架构。它是一个开源的元级操作系统(后操作系统),提供类似于操作系统的服务,包括硬件抽象描述、底层驱动程序管理、共用功能的执行、程序间消息传递、程序发行包管理,它也提供一些工具和库用于获取、建立、编写和执行多机融合的程序。

ROS的运行架构是一种使用ROS通信模块实现模块间P2P的松耦合的网络连接的处理架构,它执行若干种类型的通讯,包括:

  • 基于服务的同步RPC(远程过程调用)通讯;
  • 基于Topic的异步数据流通讯,还有参数服务器上的数据存储。

ROS可与PX4一起用于飞行器的外部控制, 它使用MAVROS节点与在硬件上运行的PX4或使用Gazebo Simulator进行通信。MAVROS节点的安装请参考Ubuntu16.04安装MAVROS,下面以编写基于MAVROS的外部控制节点为例,介绍ROS包和节点的构建过程。

ROS包构建方法

catkin和rosbuild是构建ROS包的两种方法。目前多用catkin构建ros包。

catkin包可以构建为独立项目,与构建普通cmake项目的方式相同,但catkin还提供了工作空间的概念,您可以在其中同时构建多个相互依赖的包。

ROS包构成

ROS包是其代码组织的一种高级结构好哦,最简单的catkin包的构成如下:

1
2
3
my_package/
CMakeLists.txt
package.xml

其中:

  • 包必须包含一个符合catkin的package.xml文件。
    • 该package.xml文件提供有关包的元信息。
  • 包必须包含一个使用catkin的CMakeLists.txt。
    • 如果它是catkin元数据包,它必须具有相关的样板CMakeLists.txt文件。
  • 包都必须有自己的文件夹。
    • 这意味着没有嵌套包,也没有多个包共享同一目录。

catkin工作空间的构成

使用catkin软件包的推荐方法是使用catkin工作区,但您也可以独立构建catkin软件包。 一个简单的工作空间可能如下所示:

1
2
3
4
5
6
7
8
9
10
workspace_folder/        -- WORKSPACE
src/ -- SOURCE SPACE
CMakeLists.txt -- 'Toplevel' CMake file, provided by catkin
package_1/
CMakeLists.txt -- CMakeLists.txt file for package_1
package.xml -- Package manifest for package_1
...
package_n/
CMakeLists.txt -- CMakeLists.txt file for package_n
package.xml -- Package manifest for package_n

创建catkin包

通常使用catkin_create_pkg命令创建新的catkin包,具体步骤如下:

1
2
3
4
5
6
7
8
$ mkdir -p ~/catkin_ws/src
$ cd ~/catkin_ws/src
# 创建名为offboard的ros包,它依赖roscpp、mavros和geometry_msgs
$ catkin_create_pkg offboard roscpp mavros geometry_msgs
$ cd offboard/src/
# 创建offboard_node.cpp,将官方PX4外部控制例程代码写入该文件
# 该文件也是offboard包的第一个node
$ touch offboard_node.cpp

offboard_node.cpp文件的具体内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/**
* @file offb_node.cpp
* @brief Offboard control example node, written with MAVROS version 0.19.x, PX4 Pro Flight
* Stack and tested in Gazebo SITL
*/

#include <ros/ros.h>
#include <geometry_msgs/PoseStamped.h>
#include <mavros_msgs/CommandBool.h>
#include <mavros_msgs/SetMode.h>
#include <mavros_msgs/State.h>

mavros_msgs::State current_state;
void state_cb(const mavros_msgs::State::ConstPtr& msg){
current_state = *msg;
}

int main(int argc, char **argv)
{
ros::init(argc, argv, "offb_node");
ros::NodeHandle nh;

ros::Subscriber state_sub = nh.subscribe<mavros_msgs::State>
("mavros/state", 10, state_cb);
ros::Publisher local_pos_pub = nh.advertise<geometry_msgs::PoseStamped>
("mavros/setpoint_position/local", 10);
ros::ServiceClient arming_client = nh.serviceClient<mavros_msgs::CommandBool>
("mavros/cmd/arming");
ros::ServiceClient set_mode_client = nh.serviceClient<mavros_msgs::SetMode>
("mavros/set_mode");

//the setpoint publishing rate MUST be faster than 2Hz
ros::Rate rate(20.0);

// wait for FCU connection
while(ros::ok() && !current_state.connected){
ros::spinOnce();
rate.sleep();
}

geometry_msgs::PoseStamped pose;
pose.pose.position.x = 0;
pose.pose.position.y = 0;
pose.pose.position.z = 2;

//send a few setpoints before starting
for(int i = 100; ros::ok() && i > 0; --i){
local_pos_pub.publish(pose);
ros::spinOnce();
rate.sleep();
}

mavros_msgs::SetMode offb_set_mode;
offb_set_mode.request.custom_mode = "OFFBOARD";

mavros_msgs::CommandBool arm_cmd;
arm_cmd.request.value = true;

ros::Time last_request = ros::Time::now();

while(ros::ok()){
if( current_state.mode != "OFFBOARD" &&
(ros::Time::now() - last_request > ros::Duration(5.0))){
if( set_mode_client.call(offb_set_mode) &&
offb_set_mode.response.mode_sent){
ROS_INFO("Offboard enabled");
}
last_request = ros::Time::now();
} else {
if( !current_state.armed &&
(ros::Time::now() - last_request > ros::Duration(5.0))){
if( arming_client.call(arm_cmd) &&
arm_cmd.response.success){
ROS_INFO("Vehicle armed");
}
last_request = ros::Time::now();
}
}

local_pos_pub.publish(pose);

ros::spinOnce();
rate.sleep();
}

return 0;
}

之后需要修改~/catkin_ws/src/offboard目录下的CMakeLists.txt文件。取消掉一些注释,生成相应节点(否则会出现找不到节点的错误)。

修改CMakeLists.txt文件

构建catkin包

在catkin工作空间(catkin_ws)中,使用catkin_make工具从源文件构建和安装一个包:

1
2
3
4
5
6
7
$ cd ~/catkin_ws
$ catkin_make
$ catkin_make install
# 配置catkin工作空间,使ros能找到刚生成的offboard包
$ source devel/setup.bash
# 查看ros包路径环境变量是否配置好
$ echo $ROS_PACKAGE_PATH

参考链接

  1. Ubuntu16.04安装MAVROS,by jackhuang.
  2. Creating a ROS Package, by ros homepage.
  3. Building a ROS Package, by ros homepage.
  4. Understanding ROS Nodes, by ros homepage.
  5. catkin 与 rosbuild解析及两者区别和联系,by Xuefeng_BUPT.
  6. Pixhawk原生固件PX4之SITL软件在环仿真,by FantasyJXF.
  7. Pixhawk原生固件PX4之offboard,by FantasyJXF.
  8. MAVROS Offboard control example, by dronecode.

使用nvm进行nodejs版本管理

发表于 2019-05-11 | 更新于 2022-05-21

nvm是一个简单bash脚本,用于管理多个活动的nodejs版本。在linux操作系统中使用nvm安装和管理nodejs十分方便。在windows操作系统下则使用nvm-windows对nodejs版本进行管理。下面简单介绍ubuntu 16.04操作系统下nvm的安装使用。

安装脚本

在Ubuntu 16.04的终端中,直接运行如下命令:

1
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash

管理Nodejs

  • 安装最新nodejs长期支持版
    1
    2
    3
    4
    5
    6
    7
    8
    # in linux
    nvm ls-remote
    # in windows
    nvm ls available
    # install node and use
    nvm install --lts
    nvm install 12.22.12
    nvm use 12.22.12
  • 卸载最新nodejs长期支持版
    1
    nvm uninstall --lts

nvm设置代理

在 nvm 的安装路径下,找到 settings.txt,在后面加上这两行:

1
2
node_mirror: https://npm.taobao.org/mirrors/node/
npm_mirror: https://npm.taobao.org/mirrors/npm/

nvm离线安装

无法连接互联网的Windows环境下,使用nvm的前提是,需要在有互联网环境下将自己所需要的 Node版本,使用 nvm install 版本号 下载到本地,然后将 C:\Users\Administrator\AppData\Roaming\nvm 目录下的对应版本文件拷贝到离线安装后的文件夹中即可。

参考链接

  1. Node Version Manager, by nvm-sh.
  2. nvm-windows,by nvm-windows.
  3. nvm 在 Windows 中的使用及离线安装,by tyronchen.
  4. Windows上安装nodejs版本管理器nvm,by weiqinl.
  5. nvm 设置下载 node 的镜像地址,by xhlwill.
  6. 使用 nvm 管理不同版本的 node 与 npm,by runoob.

Dell笔记本安装Ubuntu16.04出现的问题及解决方案

发表于 2019-05-11

PX4开发推荐在Ubuntu16.04上进行,然在一些带独立显卡的笔记本上安装时,进入安装界面就卡住了。问题产生原因显然与显卡驱动有关。

解决方案

解决方案可参考链接Ubuntu16.04–64位安装及使用中出现的问题。主要有两种方法:

  • 重新开机,光标选中“Install Ubuntu” ,按“e”,进入grub界面,将倒数第二行中的“quiet splash —”改为“nomodeset”。F10保存,就可以进入安装界面,进行安装。
  • 如果加入nomodeset参数不行,则试试加入nouveau.modeset=0,步骤一样。

后续维护

如果能顺利安装,则安装好后,添加选项到/etc/default/grub文件。步骤如下:

1
sudo gedit /etc/default/grub

然后将nomodeset选项添加到 GRUB_CMDLINE_LINUX_DEFAULT:

1
2
3
4
5
6
7
GRUB_DEFAULT=0
GRUB_HIDDEN_TIMEOUT=0
GRUB_HIDDEN_TIMEOUT_QUIET=true
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash nomodeset"
GRUB_CMDLINE_LINUX=""

最后更显grub启动文件:

1
sudo update-grub

参数含义

附内核显示参数的含义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
nomodeset 
不载入所有关于显示卡的驱动

nouveau.modeset=0
关闭nvidia显卡的驱动,反之=1为开启

i915.modeset=0
关闭Intel显卡的驱动,挺好奇对于Intel内显会有什么影响

xforcevesa或radeon.modeset=0 xforcevesa
跟AMD显卡(ATI)有关的设定,我猜也是关闭

acpi=off
回归旧时代,电源相关设定,OS无法控管,交给bios处理
acpi功能失效,有不少硬体上奇怪的问题,可以用这参数解决

参考链接

  1. Ubuntu16.04–64位安装及使用中出现的问题,by 一部电影.
  2. acpi_osi=linux、 nomodeset是什么意思? 功能?, by 峰Caesar.
  3. How do I set ‘nomodeset’ after I’ve already installed Ubuntu?,by askubuntu.

Ubuntu16.04安装MAVROS

发表于 2019-05-10 | 更新于 2019-06-24

MAVROS包支持运行ROS的计算机、支持Mavlink的自驾仪、支持Mavlink的地面控制站之间使用Mavlink协议进行通信,如图1所示。

px4软件在环仿真

图1 px4软件在环仿真

为构建px4软件在环仿真环境,下面介绍在协同计算机上安装Ubuntu16.04、ROS和MAVROS的步骤。

安装ubuntu 16.04

安装ubuntu 16.04 LTS桌面板的教程请参考链接Ubuntu 16.04 安装基础入门教程(图文)。

安装ROS

ROS简介

ROS(机器人操作系统,Robot Operating System),是专为机器人软件开发所设计出来的一套电脑操作系统架构。它是一个开源的元级操作系统(后操作系统),提供类似于操作系统的服务,包括硬件抽象描述、底层驱动程序管理、共用功能的执行、程序间消息传递、程序发行包管理,它也提供一些工具和库用于获取、建立、编写和执行多机融合的程序。

ROS的首要设计目标是在机器人研发领域提高代码复用率。ROS是一种分布式处理框架(又名Nodes)。这使可执行文件能被单独设计,并且在运行时松散耦合。这些过程可以封装到数据包(Packages)和堆栈(Stacks)中,以便于共享和分发。ROS还支持代码库的联合系统。使得协作亦能被分发。这种从文件系统级别到社区一级的设计让独立地决定发展和实施工作成为可能。上述所有功能都能由ROS的基础工具实现。

ROS有三个层次的概念:分别为Filesystem level,Computation graph level, 以及Communication level。 以下内容具体的总结了这些层次及概念。除了这三个层次的概念, ROS也定义了两种名称– Package资源名称和Graph资源名称。

安装ROS

不建议在虚拟机中安装Ubuntu,再安装ROS。具体ROS安装步骤请参考ROS 不能再详细的安装教程和Ubuntu install of ROS Kinetic。在此只简单记录Ubuntu 16.04 中安装ROS步骤:

  • 设置source.list
1
sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
  • 设置公钥

如何在连接服务器的过程中出现问题,可设置可选的hkp://pgp.mit.edu:80 或 hkp://keyserver.ubuntu.com:80

1
sudo apt-key adv --keyserver hkp://ha.pool.sks-keyservers.net:80 --recv-key 421C365BD9FF1F717815A3895523BAEEB01FA116
  • 安装
1
2
sudo apt-get update
sudo apt-get install ros-kinetic-desktop-full
  • 初始化rosdep
1
2
sudo rosdep init
rosdep update
  • 环境配置
1
2
echo "source /opt/ros/kinetic/setup.bash" >> ~/.bashrc
source ~/.bashrc
  • 安装ros组件构建环境
1
sudo apt install python-catkin-tools python-rosinstall python-rosinstall-generator python-wstool build-essential -y

运行ROS

在Ubuntu 16.04终端中运行如下命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# roscore will start up a ROS Master, a ROS Parameter Server and a rosout logging node
$ roscore

# rosnode is a command-line tool for printing information about ROS Nodes.
$ rosnode list

# rospack allows you to get information about packages.

$ rospack list

# rosrun will locate PACKAGE and try to find an executable named EXECUTABLE in the PACKAGE tree. If it finds it, it will run it with ARGS.
# Usage: rosrun [--prefix cmd] [--debug] PACKAGE EXECUTABLE [ARGS]
$ rosrun turtlesim turtlesim_node
$ rosrun turtlesim turtle_teleop_key

# record the message which published in the topic
$ rosbag record /turtle1/cmd_vel

# check what's happen in ros system
$ rosrun rqt_graph rqt_graph

# rqt_plot displays a scrolling time plot of the data published on topics
$ rosrun rqt_plot rqt_plot

# rostopic is a command-line tool for printing information about ROS Topics.
$ rostopic list

# rostopic echo shows the data published on a topic.
$ rostopic echo /turtle1/cmd_vel

# rostopic type returns the message type of any topic being published.
$ rostopic type /turtle1/cmd_vel

# rostopic pub publishes data on to a topic currently advertised.
$ rostopic pub -1 /turtle1/cmd_vel geometry_msgs/Twist -- '[2.0, 0.0, 0.0]' '[0.0, 0.0, 1.8]'

# rostopic hz reports the rate at which data is published.
$ rostopic hz /turtle1/pose

# check info of /turtlesim node
$ rosnode info /turtlesim

安装MAVROS

具体安装MAVROS的步骤请参考链接MAVROS。下面简单介绍Ubuntu 16.04下从源代码安装MAVROS的过程。

  • 创建catkin工作空间
1
2
3
4
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws
catkin init
wstool init src
  • 安装MAVLink
1
rosinstall_generator --rosdistro kinetic mavlink | tee /tmp/mavros.rosinstall
  • 安装MAVROS
1
rosinstall_generator --upstream mavros | tee -a /tmp/mavros.rosinstall
  • 创建工作空间和依赖
1
2
3
wstool merge -t src /tmp/mavros.rosinstall
wstool update -t src -j4
rosdep install --from-paths src --ignore-src -y
  • 安装GeographicLib数据集
1
sudo ./src/mavros/mavros/scripts/install_geographiclib_datasets.sh
  • 构建源
1
catkin build
  • 添加工作空间到ros环境
1
2
3
4
# Needed or rosrun can't find nodes from this workspace.
$ source devel/setup.bash
# Or write in .bashrc
$ echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc

参考链接

  1. Ubuntu 16.04 安装基础入门教程(图文), by ubuntu中文论坛.
  2. 机器人操作系统,by wikipedia.
  3. ROS 不能再详细的安装教程,by 小萌是个球.
  4. Ubuntu install of ROS Kinetic, by ROS.org.
  5. ROS Tutorials, by ROS.org.
  6. MAVROS, by DroneCode.
  7. catkin 与 rosbuild解析及两者区别和联系,by Xuefeng_BUPT.
  8. Installing and Configuring Your ROS Environment, by ros.org.
  9. Installing and Configuring Your ROS Environment,by ros.org.

计算机科学术语辨析

发表于 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.
上一页1…414243…53下一页

Jack Huang

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