Week 1 - ROS通信初步

ROS是什么

ROS是一个集成了许多工具和库的机器人操作框架,以节点之间的通信实现对数据的处理和硬件的操控。

配置ROS的工作环境

Windows上有用choco分发的ROS2,不过目前功能不算完善,所以关于ROS的开发工作一般在Linux系列系统上进行,这里我们选用20.04的Ubuntu来配置工作环境。

参考AutoLabor上的教程,配置主要有以下步骤。

  • 设置安装源
    1
    sudo sh -c '. /etc/lsb-release && echo "deb http://mirrors.tuna.tsinghua.edu.cn/ros/ubuntu/ `lsb_release -cs` main" > /etc/apt/sources.list.d/ros-latest.list'
  • 设置key
    1
    sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654
  • 安装
    1
    2
    sudo apt update
    sudo apt install ros-noetic-desktop-full
  • 配置环境变量
    1
    2
    echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc
    source ~/.bashrc
    其中.bashrc是Ubuntu系统根目录下的记录环境变量的文件,以后我们自己编译了什么项目也可以把路径放在这里。
  • 安装构建依赖
    1
    sudo apt install python3-rosdep python3-rosinstall python3-rosinstall-generator python3-wstool build-essential
  • 初始化rosdep
    1
    2
    sudo rosdep init
    rosdep update

HelloWorld

在ROS里实现HelloWorld,首先需要我们构造一个节点,然后让该节点在日志中将HelloWorld作为信息输出。

搭建工作环境

要搭建工作环境,首先需要在工作区执行

1
catkin_make

这个命令的执行需要文件夹下存在src目录,该目录存放我们的工程文件。
之后要编译其中的工作文件我们也需要执行同样的命令。

完成命令后,会额外生成./bin./devel文件夹,与./src/CMakeLists.txt
./bin中会存放生成的构建文件
./devel中会存放生成的执行脚本与一些头文件

创建工具包

要开始编写节点,我们需要先创建工具包,进入./src目录,并执行

1
catkin_create_pkg 包名 roscpp rospy std_msgs

包名的命名不要携带任何大写字母、下划线与连接线,用纯小写字母,这是一种命名规范
roscpp或者rospy是C++语言或Python语言的基础工具包,std_msgs是标准消息库,之后的通信会用到。

配置CMakeLists.txt

add_executable()target_link_libraries()取消注释,表明本次构建生成可执行文件。

编写项目

编写项目的流程就我目前总结如下:

  1. 修改工具包下packages.xml,添加所需依赖
  2. 依据需求修改CMakeLists.txt,设置编译过程
  3. 如果要生成例如msgsrv这种依赖,那么先编译一遍
  4. 配置工具包和依赖完成后,写代码。
  5. 完成节点代码后编译
  6. 启动节点测试

为了实现HelloWorld,我们需要编写如下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
#include "ros/ros.h"

int main(int argc, char *argv[])
{
// 初始化
ros::init(argc,argv,"hello");
// 创建节点
ros::NodeHandle n;
// 打印日志
ROS_INFO("hello world!");

return 0;
}

尤其值得注意的是,#include "ros/ros.h"这一行,为了让VSCode找到ros的头文件,我们要编辑includePath设置,一般来说在ros的默认安装路径下头文件在/opt/ros/noetic/include/**(最后那个**指包含所有子目录)

进行ros编程,最重要的就是节点,我们首先初始化并声明自己这个节点,然后再下一步输出日志。

int argc, char *argv[]是运行该节点时的一些基本参数,argc代表参数数量,argv是参数列表

没有额外参数传入时,argv[0]为文件路径,argv[1]为节点名称,argv[2]为日志路径,argc3

有额外参数时,argv[1]是第一个额外参数,argv[2]等等以此类推,argc为参数数量加上3

启动节点测试

首先启动ROS内核

1
roscore

然后在工作区内启动节点

1
2
source ./devel/setup.bash
rosrun 包名 C++节点名(详见CMake脚本生成的可执行文件名)

节点通信的三类模型

参数服务器模型

ROSMaster负责储存一系列参数,发布者修改其中的参数,订阅者可以获取其中的参数。

工程文件详见param文件夹,以下提出几个要点:

  • 服务器使用setParam()设置并准备发布参数,hasParam()检测参数存在性,getParam()以获取参数值。
  • 该方法并不高效,不要把这个玩意当寄存器用。

服务通信模型

ROSMaster负责让发布者与订阅者建立连接,发布者接受来自订阅者的数据请求,并相应回给订阅者处理后的信息。

工程文件详见srv文件夹,以下提出几个要点:

  • 为了明确发布者和订阅者发送的数据类型与数目,需要提前建立srv文件夹并准备.srv描述文件
  • .srv文件中---上方的是订阅者请求信息,下方是发布者回应信息
  • CMakeLists.txt中,应当将add_service_files()generate_messages()方法打开,并添加message_generation作为第三方库到find_package()中。
  • package.xml中,应当添加如下引用
    1
    2
    <build_depend>message_generation</build_depend>
    <exec_depend>message_runtime</exec_depend>
  • 调用订阅者节点时,在这个实例中,应当在rosrun指令后添加参数,参数会被argv储存
  • waitForService()方法可以在节点没启动时阻塞进程

话题通信模型

ROSMaster负责让发布者与订阅者建立连接,发布者发布消息,订阅者接收信息。

工程文件详见msg文件夹,其使用了.msg文件自定义传输数据,以下提出几个要点:

  • 如果要自定义传输数据的结构,需要提前建立msg文件夹并准备.msg描述文件
  • .msg文件中一行一个变量定义
  • CMakeLists.txt中,应当将add_message_files()generate_messages()方法打开,并添加message_generation作为第三方库到find_package()中。
  • package.xml中,应当添加如下引用
    1
    2
    <build_depend>message_generation</build_depend>
    <exec_depend>message_runtime</exec_depend>

其它事项

1
rqt_graph

这个命令可以查看所有的节点状态与它们之间的关系。

创建工具包时使用catkin_create_pkg命令需在./src资源文件夹内进行。

编写msg文件或者srv文件时,int类型定义为int32long longint64doublefloat64,记得查表。