guojh's Blog.

ROS学习笔记

字数统计: 4.1k阅读时长: 16 min
2018/12/16

之前已经接触过一些ROS的使用,但是还没有系统地学习过,因此在此记录一下学习的笔记。学习ROS首先必须参考ROS wiki及ROS Answers,另外国内“古月居”的博客和“东方赤龙”的博客都可以参考学习,本文使用古月居的书《ROS机器人开发实践》来系统学习ROS。不过,需知道ROS本身只是一个方便大家开发的工具罢了。

书中相关学习代码在github上: https://github.com/gjgjh/ros_exploring

1. 初识ROS

分布式网络,TCP/IP,模块间松耦合连接

三种通信机制: 1.基于发布/订阅topic通信(异步)

  • talker注册
  • listener注册
  • ROS master进行信息匹配
  • listener发送连接请求
  • talker确认连接请求
  • listener尝试与talker建立网络连接
  • talker向listener发布数据

注意,节点建立连接后,可以关掉ROS master,节点间数据传输不受影响,但其他节点也无法加入这两个节点间的网络。

2.基于客户端/服务器service通信(同步)

带有应答,减少了listener与talker间的RPC通信。底层协议和topic通信一样,用的都是ROSTCP/ROSUDP。 只允许一个节点提供指定命名的服务(一对多),实时性比topic强。

3.基于远程过程调用(RPC)的参数服务器

不涉及TCP/UDP通信。 参数类似ROS中的全局变量,包含key和value,由ROS master进行管理。 需注意有时需要动态参数配置来通知listener参数已被更新。

topic通信适用于不断更新、含较少逻辑处理的数据通信;service通信适用于数据量较少但有逻辑处理的数据交换。

2. ROS架构

分为三层: - OS层。基于linux - 中间层。提供通信机制及一些库 - 应用层。各功能包内模块以节点为单位

3. ROS基础

3.1 创建工作空间和功能包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
mkdir -p ~/catkin_ws/src 

# 在工作空间根目录编译,编译后自动出现build和devel文件夹及几个脚本文件,用于设置环境变量等
cd ~/catkin_ws/
catkin_make

# 运行脚本文件使其生效
source devel/setup.bash

# 查看环境变量是否生效
echo $ROS_PACKAGE_PATH

# 如果没添加上使用sudo gedit ~/.bashrc打开文件手动添加。或者在终端使用下面命令直接添加。
# 这种方式对所有终端都有效,而source只对当前终端有效!
echo "source ~/catkin_ws/devel/setup.bash">> ~/.bashrc
source ~/.bashrc

# 进入代码空间,创建自己的功能包。一般都会依赖roscpp,rospy,std_msgs这几个功能包
# 不过也可以不用现在添加,后续用到具体的依赖时,再在CMakeLists中直接加上即可。
# 你也可以直接去github下载别人写好的功能包,就不用自己创建啦。
# 创建完成后,代码空间src中会生产一个叫my_package的功能包,其中已经包含package.xml和CMakeLists.txt文件。
# 在后续写代码时,就可以把源码放进功能包src文件夹中,然后写相应的CMakeLists.txt就可以了。具体见下面CLion教程。
cd ~/catkin_ws/src
catkin_create_pkg my_package roscpp rospy std_msgs

3.2 工作空间的覆盖

ROS中为解决同名功能包问题,存在覆盖机制。即$ROS_PACKAGE_PATH中记录的环境变量,最前面覆盖最后面的。 创建多个同名功能包时,需要注意这点!

1
2
3
4
5
# rospack 查找功能包所放置的工作空间
rospack find roscpp

# 直接进入功能包所在路径
roscd roscpp

为了解决冲突问题,可以把功能包放到两个不同的工作空间中,然后重命名其中一个包。 重命名需要改动这个包的package.xml文件中name节点的值,以及launch文件中,原包名全部需要替换为新的包名称。

3.3 使用IDE运行及调试ROS程序

这个是非常重要且实用的一点!否则后面不管是自己写ros程序还是用别人开源的程序,调试起来会很麻烦。 ROS支持许多IDE开发,具体可以看wiki上的介绍。CLion是一个个人觉得非常好用的跨平台c++IDE。搭建CLion开发环境后可以利用CLion运行和调试ros程序,十分方便,具体见CLion官方教程 其中需要注意的是,每次必须从终端利用bash打开CLion;或者要改一个桌面快捷方式文件,使其每次通过bash启动,网上可以搜到解决方案。

另外,还可以配置下编译路径。CLion默认在cmake-build-debug或cmake-build-release文件夹保存编译文件。可以通过File|Settings(Ctrl+Alt+S)|Build, Execution, Deployment|CMake改一下: 1.Generation path改为/home/name/catkin_ws/build 2.CMake options加上 -DCATKIN_DEVEL_PREFIX:PATH=/home/name/catkin_ws/devel

3.4 创建Publisher和Subscriber

这也是一个非常重要的一点!因为做slam会经常用到订阅传感器发布的话题,然后获取各种传感器数据并在程序中处理后,生成位姿与地图,最终把结果按相应规定的数据格式发布出去。 基于C++写一个ROS程序,深入理解发布和订阅机制: http://wiki.ros.org/ROS/Tutorials/WritingPublisherSubscriber%28c%2B%2B%29

3.5 自定义话题消息

ROS的元功能包common_msgs提供了许多不同消息类型的功能包,如std_msgs、geometry_msgs、sensor_msgs等。当不能满足自己程序的需求时,可以在项目下新建msg文件夹,并将自定义的消息类型文件.msg放于其中。然后更改package.xml和CMakeLists.txt文件即可。

话题消息编译与编程语言无关。

3.6 创建Server和Client

类似可以自定义消息,你也可以将自定义服务数据.srv放置于新建的srv文件夹。 创建Server过程类似创建Subscriber,而创建Client类似创建Publisher。

3.7 多机ROS通信

ROS是一种分布式软件框架,节点间以松耦合方式组合,多机通信非常常用,如第5节中就用到了。

  • 配置IP地址
1
2
3
4
5
6
7
#通过ifconfig命令可以查看本机局域网IP地址。然后分别在两台计算机系统的/etc/hosts文件加入对方的IP地址和对应计算机名

# @gjgjh, /etc/hosts
192.168.2.100 raspi3

# @raspi3, /etc/hosts
192.168.2.129 gjgjh

设置完后,分别在两台计算机上互相使用ping命令测试网络是否连通。

  • 设置ROS_MASTER_URI环境变量:
1
2
3
# 从机(非Master机)
echo "export ROS_MASTER_URI=http://gjgjh:11311/" >> ~/.bashrc
source ~/.bashrc

4. ROS中常用组件

4.1 launch启动文件

利用xml文件同时启动和配置多节点,避免了每次打开多个终端运行多个节点。 重要的节点属性包括name/pkg/type/args/output等,其中:

  • <name> 定义节点运行的名称,将覆盖节点中init()赋予节点的名称
  • <pkg> 定义节点所在功能包名称
  • <type> 定义节点可执行文件名
  • <args> 定义节点运行参数,可以有多个
  • <output> 若值为screen表示节点标准输出到终端屏幕,默认输出为日志文档

参数设置: - <param> 类似变量声明 - <rosparam> 直接加载整个yaml文件 - <arg> 类似launch文件内部的局部变量,仅限内部使用,与节点无关

这里需要注意一个小问题。比如我的程序需要1个输入参数(即argc=2),在使用launch文件后,程序参数个数变多了(即argc>2)。比如这是我的launch文件,可以看到我的程序需要1个输入参数:

1
2
3
4
5
6
<launch>
<node
name="rgbdslam" pkg="rgbdslam" type="run_vo" args="$(find rgbdslam)/config/default.yaml"
output="screen"
/>
</launch>
但是,运行后程序的实际argv打印到屏幕如下,多了两个参数。不过这个小问题影响不大,了解即可:
1
2
3
4
/home/gjh/catkin_ws/src/rgbdslam/bin/run_vo
/home/gjh/catkin_ws/src/rgbdslam/config/default.yaml
__name:=rgbdslam
__log:=/home/gjh/.ros/log/e840c676-1bca-11e9-b271-000c290958e7/rgbdslam-2.log

重映射:类似c++别名机制,如:

1
<remap from="/turtlebot/cmd_vel" to="/cmd_vel" />
另外,也可以使用终端完成重映射,如之前运行lsd-slam时就使用过这种方法:
1
rosrun lsd_slam_core live_slam image:=/image_raw camera_info:=/camera_info

嵌套复用。其中使用find命令查找当前包的路径,如:

1
<include file="$(find mypackage)/launch/other.launch">
在launch中直接启动master,参数还可以为restart或no:
1
<master auto="start"/>
## 4.2 TF坐标变换
1
2
3
4
5
6
7
8
9
10
# 一些TF工具
# 1.查看指定坐标系之间变换关系,即平移和旋转
rosrun tf tf_echo <source_frame> <target_frame>

# 2.显示TF树信息,并保存为pdf
rosrun tf view_frames

# 3.其他
tf_monitor
static_transform_publisher

通过创建TF广播器和TF监听器,实现乌龟跟随运动

4.3 Qt工具箱

日志输出工具 rqt_console 计算图可视化工具 rqt_graph 数据绘图工具 rqt_plot 参数动态配置工具 rqt_reconfigure

4.4 rviz可视化平台

配置好rviz后,可以在file|save config as保存.rviz文件。然后使用-d参数加载配置文件,从而可以避免每次重新配置:

1
2
3
4
rosrun rviz rviz -d <path>/rvizfile.rviz

# for example
rosrun rviz rviz -d `rospack find turtle_tf`/rviz/rvizfile.rviz

或者还可以把这一步写进launch文件中,更加方便!

4.5 rosbag数据记录与回放

1
2
3
4
5
# 查看bag文件信息,时长duration,是否压缩等
rosbag info <your bagfile>

# 解压缩
rosbag decompress <your bagfile>

5.机器人平台搭建

机器人组成,4大部分: - 执行机构。类似“手脚”。电机带动的轮子等 - 驱动机构。类似“肌肉和筋络”。主控板:电源子系统、电机驱动子系统、传感器接口 - 传感系统。类似“感官”。内部传感器(里程计、陀螺仪);外部传感器(摄像头、激光) - 控制系统。类似“大脑”。处理器(使用树莓派/PC等)、算法,与ROS相关较大

控制系统两种方案:

  • 使用单处理器。直接使用“一台PC+ROS”,通过usb串口与主控通信,但无法远程监控。
  • 使用多处理器(推荐)。“两台PC”或“PC+嵌入式系统”,通过无线网络通信。

“PC+嵌入式系统”例子:树莓派中搭载Ubuntu系统并运行ROS,订阅速度控制指令,然后通过串口下发速度控制指令,实现MRobot运动。并通过串口读取编码器等内部传感器、摄像头等外部传感器的信息,发布里程计、图像等消息;PC端运行SLAM、导航等功能包,并发布键盘控制话题“cmd_vel”,另外,Master运行在PC端。为保证通信顺畅,还需要设置IP地址和环境变量,见3.7节。

总之,搭载于机器人的嵌入式系统完成本地运动控制及传感器数据采集,远端PC完成远程监控、可视化及复杂功能计算。

6.机器人建模与仿真

如果没有真实机器人,则需仿真。仿真需要先建立机器人模型,然后搭建仿真环境。

6.1 URDF统一机器人描述格式

<link> 机器人刚体部分外观和物理属性(质量、惯性矩阵等) <joint> 连接两个刚体link,6种类型 <robot> 最顶层标签,包含一系列link和joint <gazebo> 不是必需,只在gazebo仿真时加入

6.2 创建机器人URDF模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 0.在工作空间中,创建机器人描述功能包
catkin_create_pkg mrobot_description urdf xacro

# 1.编写urdf,见
https://github.com/gjgjh/ros_exploring/blob/master/robot_mrobot/mrobot_description/urdf/mrobot_chassis.urdf
# 除了link外观属性,还可以设置物理属性和碰撞属性

# 2.检查xml格式是否合法
check_urdf mrobot_chasssis.urdf

# 3.生成模型的整体结构图
urdf_to_graphiz mrobot_chasssis.urdf

# 4.rviz中可视化模型
# 编写相应launch文件,见:
https://github.com/gjgjh/ros_exploring/blob/master/robot_mrobot/mrobot_description/launch/display_mrobot_chassis_urdf.launch
# 如果你安装的是ros完整版本的,会自带一个urdf_tutorial功能包,你还可以使用下面命令可视化模型:
roslaunch urdf_tutorial display.launch model:='$(find mrobot_description)/urdf/mrobot.urdf'

6.3 xacro优化urdf

原始urdf冗长重复,xacro进行改进 可以使用下面方法以达到精简目的:

  • 常量定义

    1
    <xacro:property name="wheel_radius" value="0.033"/>

  • 调用数学公式

    1
    ${(motor_length+wheel_length)/2}

  • 使用宏定义(类似函数)

    1
    2
    3
    <xacro:macro name="usb_camera" params="camera">
    <!-- blah blah blah -->
    </xacro:macro>

  • xacro文件引用,类似C语言中的include

    1
    <xacro:include filename="xxx.xacro"/>

然后通过两种方式显示模型: 1.将xacro文件转换为URDF文件,再用之前方法显示

1
rosrun xacro xacro.py mrobot.urdf.xacro > mrobot.urdf # 例子

2.直接在launch文件中调用xacro文件解析器(推荐)

1
2
<arg name="model" default="$(find xacro)/xacro --inorder '$(find mrobot_description)/urdf/mrobot_with_camera.urdf.xacro'" />
<param name="robot_description" command="$(arg model)" />

6.4 添加传感器模型

https://github.com/gjgjh/ros_exploring/tree/master/robot_mrobot/mrobot_description/urdf

可以加载三维模型文件dae;

还可以使用Solidworks等软件创建更好的模型,然后转换为URDF格式导入。

6.5 基于ArbotiX和rviz的仿真器

构建一个简单运动仿真器

  • 安装ArbotiX
1
sudo apt-get install ros-kinetic-arbotix-*
  • 配置ArbotiX控制器

只需创建一个启动ArbotiX节点的launch文件,再创建一个yaml配置文件。

  • 运行仿真环境
1
2
roslaunch mrobot_description arbotix_mrobot_with_kinect.launch
roslaunch mrobot_teleop mrobot_teleop.launch

6.6 Gazebo仿真

更强大的物理仿真平台——Gazebo,实现机器人高度仿真,包括物理属性、传感器属性、环境模型等。

1
2
roscore
rosrun gazebo_ros gazebo

如果你像我一样使用的是虚拟机,可能遇到黑屏问题,参考此链接可以解决。

仿真前,需构建仿真环境。两种方式:

  • 直接insert模型。需连外网,或把模型提前下载到~/.gazebo/models下。模型百度网盘链接 ,密码cmxc (资源来自:rosclub.cn)
  • Building Editor。在Edit菜单中,可手动绘制地图

另外,模型中现在还必须加入Gazebo属性,如<gazebo><transmission><plugin>等标签。然后就可以对摄像头、Kinect、激光雷达等传感器进行模拟环境仿真了,具体可以参考github的相关源码。

7.Gazebo中仿真SLAM

以gmapping为例,其他类似

1
2
3
4
5
sudo apt-get install ros-kinetic-gmapping # 安装gmapping
roslaunch mrobot_gazebo mrobot_laser_nav_gazebo.launch # 启动Gazebo仿真环境
roslaunch mrobot_navigation gmapping_demo.launch # 启动gmapping节点
roslaunch mrobot_teleop mrobot_teleop.launch # 键盘控制
rosrun map_server map_saver # 保存地图

最优路径规划功能包:move_base

  • 全局路径规划

根据给定目标位置和地图进行总体路径规划,使用Dijkstra或A*算法。

  • 本地实时路径规划

使用Dynamic Window Approaches算法实时避障,使之尽量符合全局最优路径。

配置代价地图后即可导航。手动导航:点击2D Nav Goal设置目标位置;自动导航:随机产生当前目标点,到达目标点后短暂停留后前往下一个目标点。

SLAM+自主导航实现自主探索SLAM

8.ROS进阶

action通信机制:一种带有连续反馈层的上层通信机制

rviz plugin:利用Qt打造自己的人机交互软件

参数动态配置:ROS参数服务器在线动态更新,采用C/S架构

ROS-Matlab

ROS2:支持多机器人系统、产品化、实时性、跨平台

ROS2分为三层:

  • OS层。基于linux/windows/Mac OS/RTOS
  • 中间层。通信基于DDS(数据分发服务),是一种分布式实时系统中数据发布/订阅方案
  • 应用层。不要Master,改为Discovery发现机制彼此建立连接

关键概念:

  • 参与者。每一个发布者或订阅者都是参与者(Participant)
  • 发布者。可与多个数据写入器相连
  • 订阅者。可与多个数据读取器相连
  • 数据写入器。每个对应一个特定话题(topic)
  • 数据读取器。每个对应一个特定话题(topic)
  • QoS。a)实时性。数据必须在ddl前完成更新;b)持续性。提供历史数据服务;c)可靠性。用户根据需要选择BEST_EFFORT还是RELIABLE模式。

个人理解错误的地方还请不吝赐教,转载请标明出处

CATALOG
  1. 1. 1. 初识ROS
  2. 2. 2. ROS架构
  3. 3. 3. ROS基础
    1. 3.1. 3.1 创建工作空间和功能包
    2. 3.2. 3.2 工作空间的覆盖
    3. 3.3. 3.3 使用IDE运行及调试ROS程序
    4. 3.4. 3.4 创建Publisher和Subscriber
    5. 3.5. 3.5 自定义话题消息
    6. 3.6. 3.6 创建Server和Client
    7. 3.7. 3.7 多机ROS通信
  4. 4. 4. ROS中常用组件
    1. 4.1. 4.1 launch启动文件
    2. 4.2. 4.3 Qt工具箱
    3. 4.3. 4.4 rviz可视化平台
    4. 4.4. 4.5 rosbag数据记录与回放
  5. 5. 5.机器人平台搭建
  6. 6. 6.机器人建模与仿真
    1. 6.1. 6.1 URDF统一机器人描述格式
    2. 6.2. 6.2 创建机器人URDF模型
    3. 6.3. 6.3 xacro优化urdf
    4. 6.4. 6.4 添加传感器模型
    5. 6.5. 6.5 基于ArbotiX和rviz的仿真器
    6. 6.6. 6.6 Gazebo仿真
  7. 7. 7.Gazebo中仿真SLAM
  8. 8. 8.ROS进阶