Jack Huang's Blog


  • 首页

  • 标签

  • 归档

  • 搜索

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.

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 许翔翔.
上一页1…414243…53下一页

Jack Huang

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