目录

ROS入门:搭建环境与测试

本文记录了在Ubuntu18.04.5 LTS操作系统下安装ROS Melodic的过程,并编写了一个简单的demo用于测试。

安装及环境配置

ROS中的基础知识,在此处不再赘述。若有需要可以学习中国大学mooc上的课程机器人操作系统入门

配置软件源并安装ROS

首先在系统的软件和更新中,将软件源更换成阿里云、清华源等国内源以加速下载,并勾选上main universe multiuniverse restricted的选项,以允许下载所有软件。

添加ros的软件源。为了加快速度这里选择了清华大学提供的镜像源。

$ sudo sh -c '. /etc/lsb-release && echo "deb http://mirrors.tuna.tsinghua.edu.cn/ros/ubuntu/ $DISTRIB_CODENAME main" > /etc/apt/sources.list.d/ros-latest.list'

添加秘钥。如果速度慢或者连接不上可以换用教育网或者魔法上网。

$ sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654

刷新软件源列表:

$ sudo apt update

接下来,就可以安装ros了。ros分为三个版本,分别为desktop-full desktop base。其中,desktop-full为桌面版本,除了ros rqt rviz等基础组件之外,还包含了 gazebo 等附加应用;desktop也为桌面版本,但只包含了基础组件;而base则只包含了最基本的命令行工具,并没有GUI支持。本文以完整版为例,你也可以根据自己的需要,选择下面3条指令中的一条指令进行安装。

# 以下指令根据需要三选一即可
$ sudo apt install ros-melodic-desktop-full
$ sudo apt install ros-melodic-desktop
$ sudo apt install ros-melodic-ros-base

下载及安装过程比较漫长,可以泡杯咖啡休息一下。若下载过程中出现连接失败,不要慌张,首先检查你是否在使用国内的软件源,确认所使用的软件源正确后,重新运行一遍安装指令即可补齐下载失败的包,并成功安装。

ros并未将自身安装到类似/usr/bin这类系统path路径下,而是安装到了/opt/ros下。因此,直接运行是无法找到可执行文件的。好在,ros自身提供了环境配置文件,我们只需要使用这个配置文件激活ros运行环境就可以了。不过,每次打开终端都要激活环境显得有些繁琐。因此,我们将激活ros运行环境的指令添加到bash的启动脚本中,这样就不需要每次都手动激活了。执行完上述部分之后,可以重启终端使其生效,或运行source指令手动激活。

$ echo "source /opt/ros/melodic/setup.bash" >> ~/.bashrc
$ source ~/.bashrc

环境配置

首先,我们需要安装ros-dep,这是ros用于管理包依赖的工具,但是没有跟随主程序一同安装。安装方法非常简单,直接使用Linux的包管理器进行安装即可。

$ sudo apt-get install python-rosdep

接下来初始化ros-dep。若执行的时候出现错误,多半原因是因为网络问题,请自行魔法上网解决。

$ sudo rosdep init
$ rosdep update

运行测试

最后,我们运行ros自带的小乌龟模拟器turtlesim来测试ros是否能够正常运行。分别打开3个终端窗口,分别在其中运行ros核心、turtlesim的界面以及控制器程序。

$ roscore
$ rosrun turtlesim turtlesim_node
$ rosrun turtlesim turtle_teleop_key

然后,在执行最后一条命令的控制终端窗口中,使用方向键,即可控制小乌龟的移动。

对于turtlesim所使用的topicmsg,可以在turtlesim_node运行的时候使用如下指令进行查询。

$ rostopic list | grep turtle
/turtle1/cmd_vel
/turtle1/color_sensor
/turtle1/pose

turtlesim官方文档中可以看到,turtlesim_node订阅了turtleX/cmd_vel这个topic,其中的msg名称为geometry_msgs/Twist,定义为

# This expresses velocity in free space broken into its linear and angular parts.
Vector3  linear
Vector3  angular

geometry_msgs/Twist包含两个数据,分别为线速度以及角速度的3维向量数据。我们可以使用rqt工具对上述msg进行测试。

在命令行中运行rqt指令,打开rqt窗口,点击上方菜单栏的Plugins->Topics->Message Publisher打开消息发送工具。选择好对应的Topic以及Type并点击右侧绿色的加号将其添加进下方列表中;接着在其中的liner->x中输入数值1,并打钩Topic前方的复选框,即可看到小乌龟向前方以设定的速度1向前移动。liner->y则可以控制小乌龟的水平移动,angular->z可以控制小乌龟的旋转。

https://img.yuanze.wang/posts/ros-melodic-intro/rqt_demo.jpg
rqt图形化测试工具

除此之外,还可以使用/reset这个Service来使小乌龟复位。值得一提的是,每次复位之后小乌龟的样子都会改变。

使用rqt_graph指令,还可以绘制ros当前节点的图形。

Demo编写

本文将基于ros以及turtlesim,编写一个demo程序,使用键盘来控制小乌龟的移动,实现与上一节中官方示例相同的效果。值得注意的是,对于文件的编辑操作,可以使用Visual Studio Code来完成,只需要使用VSC打开package所在的目录,即可对工程内的所有文件进行方便地编辑。若安装了ROS插件,则更可以直接在VSC内对工程进行编译,可以大大提高开发效率。

每个catkin工程都是一个workspace,一个workspace之中可以含有多个package,同时一个package可以包含多个node,每个node均是一个可执行文件,是ros软件的最基本单位,在node中可以对message进行订阅与发布,同时提供service或调用service

工程搭建

我们将此次创建的demo所在的工作空间命名为turtlesim_democatkin要求一个合格的工作空间目录下必须要包含src目录,因此我们一并创建该目录。

$ mkdir ~/code/turtlesim_demo/src -p

接下来,我们使用catkin来初始化该工作空间。

$ cd ~/code/turtlesim_demo
$ catkin_make

然后,我们需要创建一个package。创建package的命令如下。

catkin_create_pkg <pkg_name> [deps]

在此,我们创建一个package,用于存放控制turtlesim的代码。这里我们先不并添加依赖,而是在后面手动进行添加。

$ cd ~/code/turtlesim_demo/src
$ catkin_create_pkg turtlesim_demo

这样,我们就创建好了一个package。接下来,我们根据1.3小节中对turtlesim所订阅的topic的分析,创建一个可以被turtlesim所识别的消息。

$ cd ~/code/turtle_demo/src/turtlesim_demo
$ mkdir msg
$ cd msg
$ nano turtle.msg

因为本demo没有使用自定义的message格式,只使用了ros自带的基本message,因此message的编写在此处可以暂时略过。

然后,创建demo程序的源文件。

$ cd ~/code/turtle_demo/src/turtlesim_demo/src
$ touch demo.cpp

创建好源文件之后,我们暂时不编辑其中的内容,而是先编辑turtlesim_demo节点的CMakeLists.txt文件,用以描述我们的packagenode

$ nano ~/code/turtle_demo/src/turtlesim_demo/CMakeLists.txt

如下是去除注释后的CMakeLists.txt文件。其中,find_package宏与catkin_package宏的区别在于,前者是针对本项目自身需要而声明依赖,而后者则是针对依赖本项目的其他项目声明其所需要的额外依赖。对文件的修改,重点在于增加对项目依赖项的添加以及对可执行文件的声明。在find_package宏中,roscpp用来添加对ROS Client Library的支持,std_msgs用来支持标准Message。除此之外,还增加了geometry_msgs包,用来增加turtlesim所使用的geometry_msgs/Twist消息类型。

由于本demo只使用了turtlesim中的数据类型,并未自己编写消息或调用系统基本的消息类型,因此并未使用到message_generationstd_msgs包,用来根据 .msg文件生成头文件或添加系统基本的消息类型。实际上,这二者是非常常见的依赖包,只要是略复杂的项目应该都会使用到它们,因此本工程也包含了它们。

cmake_minimum_required(VERSION 3.0.2) # 所依赖的最低cmake版本 由系统自动生成
project(turtlesim_demo) # 工程名
find_package(catkin REQUIRED COMPONENTS # 加载catkin宏和指定对其他ROS功能包的依赖关系
  roscpp # 使用cpp进行ros编程所必须的Client Library
  std_msgs # 基础消息库 包含了string int等类型
  std_srvs # 基础服务库 包含了/reset等服务
  message_generation # 由.msg文件编译生成.h文件所必须的库
  geometry_msgs # 其中包含了turtlesim所使用的vector消息类型
)
## add_message_files(FILES mymsg.msg) # 如果需要添加自己编写的msg 请在此处添加位于msg目录中的文件
## generate_messages(DEPENDENCIES geometry_msgs) # 根据geometry_msgs生成对应的.h文件 这里由于是系统自带的message因此不用手动生成
catkin_package( # 声明要传递给依赖本项目的其他功能包的内容
  CATKIN_DEPENDS roscpp std_msgs std_srvs geometry_msgs # 告知其他功能包依赖本项目所需要的依赖
)
include_directories( # 项目include目录
  include ${catkin_INCLUDE_DIRS}
)
add_executable(${PROJECT_NAME} src/turtlesim_demo.cpp) # 根据源文件生成node可执行文件 第一个参数为可执行文件名 第二个参数为源文件路径
add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) # 向可执行文件添加依赖库 本质是将前面的find_package与catkin_package宏所添加的依赖添加到可执行文件中
target_link_libraries(${PROJECT_NAME} # 向可执行文件添加链接库
   ${catkin_LIBRARIES}
)

然后,我们编辑package.xml文件中的内容。package.xml文件中主要描述了包的基本信息以及其编译依赖、运行依赖和其他包依赖本包时所需的依赖。

首先,我们需要去除其中<build_depend>message_generation</build_depend>行和<exec_depend>message_runtime</exec_depend>行的注释,然后在最后添加对geometry_msgs的依赖,使其与CMakeLists.txt相对应。完整的package.xml文件如下。

<?xml version="1.0"?>
<package format="2">
  <!-- 包名 版本 作者 协议等基本信息 -->
  <name>turtlesim_demo</name>
  <version>0.1.0</version>
  <description>The turtlesim_demo package</description>
  <maintainer email="wangyz1997@126.com">wangyz</maintainer>
  <license>BSD</license>
  <!-- catkin是编译所必须的 -->
  <buildtool_depend>catkin</buildtool_depend>
  <!-- 此处应该与find_package中的包相同 -->
  <build_depend>roscpp</build_depend>
  <build_depend>std_msgs</build_depend>
  <build_depend>std_srvs</build_depend>
  <build_depend>geometry_msgs</build_depend>
  <build_depend>message_generation</build_depend>
  <!-- 此处应该与catkin_package中的包相同 -->
  <build_export_depend>roscpp</build_export_depend>
  <build_export_depend>std_msgs</build_export_depend>
  <build_export_depend>std_srvs</build_export_depend>
  <build_export_depend>message_runtime</build_export_depend>
  <!-- 此处应该为以上两段依赖的并集 -->
  <exec_depend>roscpp</exec_depend>
  <exec_depend>std_msgs</exec_depend>
  <exec_depend>std_srvs</exec_depend>
  <exec_depend>geometry_msgs</exec_depend>
  <exec_depend>message_runtime</exec_depend>
  <export>  </export>
</package>

源码编写

编写src/turtlesim_demo.cpp文件,对程序的具体描述均在注释中。

#include <ros/ros.h> // 所有ros app都依赖此头文件
#include <geometry_msgs/Twist.h> //包含了Twist消息的定义
#include <std_srvs/Empty.h> //包含了没有参数的服务基本类

int main(int argc, char** argv) {
    ros::init(argc, argv, "turtle_demo"); //初始化Client Library 并给出当前node的名字
    ros::NodeHandle node_h; //实例化node
    geometry_msgs::Twist msg; //创建一个Twist类message对象
    std_srvs::Empty reset_srv; //创建一个Empty类service对象
    ros::Publisher pub = node_h.advertise<geometry_msgs::Twist>("turtle1/cmd_vel", 1); //创建发布message的发布者
    ros::ServiceClient client = node_h.serviceClient<std_srvs::Empty>("/reset"); //创建调用service的client
    ros::Rate loop_rate(1.0); //ros自带的tick功能
    client.call(reset_srv); //调用/reset 复位乌龟位置
    while(ros::ok()) { //主循环 当roscore被关闭或Ctrl+C中断等发生时 会跳出主循环
        msg.linear.x = 1.0; //向前的速度
        msg.linear.y = 0.0;
        msg.angular.z = 1.0; //让小乌龟逆时针做半径为1的圆周运动
        pub.publish(msg); //发布消息

        loop_rate.sleep(); //tick 延时
    }
    return 0;
}

此时,我们可以查看整个工程的目录结构。

wangyz@ubuntu-vm:~/code/turtle_demo$ tree
.
├── build
├── devel
└── src
    └── turtlesim_demo
        ├── build
        ├── include
        │   └── turtlesim_demo
        ├── src
        │   └── turtlesim_demo.cpp
        ├── CMakeLists.txt
        └── package.xml

编写好源代码之后,我们可以试着对工程进行编译。

$ cd ~/code/turtle_demo
$ catkin_make
...
[100%] Built target turtlesim_demo

此时,工程应该已经可以被正常编译了。别忘了在终端中激活catkinworkspace

$ roscore
$ rosrun turtlesim turtlesim_node
$ source ~/code/turtle_demo/devel/setup.bash # 激活workspace
$ rosrun turtlesim_demo turtlesim_demo

一切顺利的话,你应该能看到小乌龟在逆时针转圈了!

https://img.yuanze.wang/posts/ros-melodic-intro/turtle_demo.jpg
运行效果

OpenPose工程编写

$ pwd
/home/wangyz/code/robotics_project
$ catkin_create_pkg openpose_gesture_controller roscpp std_msgs std_srvs geometry_msgs message_generation message_runtime