ROS入门基础教程 -(快速版)

前言

笔者写的是ros的简单教程,根据官方文档改编,不讲解原理和扩展的话题,只是为了直接上手使用ros,不愿浪费时间逐一了解,直接让小白使用。快人一万步!ros本质就是一个个的工具组成的,一起联合使用,工具之间的配合需要通过话题&服务去通信合作,ros主要是配合linux系统而去维护的,我们最好使用linux系统,所以我们最好使用拥有图形化的乌班图ubuntu,只有20.04及以下版本最后配对ROS1了,22.04已经不支持ROS1了。小白的话最好用虚拟机,不怕搞坏电脑。学习要慢慢学,以下是ROS的核心基础,搞定话的半天可能行了,但是学懂可能要三天以上。

  • 昨天之深渊,今日之浅谈,路虽远行之将至,事虽难做其可成。

官方文档 - 中文/ROS/教程 - ROS百科

1.安装并配置ROS环境

ubuntu系统安装ROS(简单版)

虚拟机安装ubuntu系统20.04 (详细版)

配置完成后

看一下啊b站up的快速视频

超精简8分钟ros入门教程,实战前够用的基础_bilibili

2.ROS文件系统导览

ROS的文件系统与linux的文件系统最大的区别就是可以通过的软件包名与node的程序名来直接查找文件

命令行 用法
rospack 获取软件包的有关信息,加上find可以查看路径
roscd 通过包名进去到所在目录
rosls 通过包名显示所在目录的文件
rosed 通过包名找到程序并打开编辑器,默认是vim

用法:**(下面所有 $ 前缀表示为命令行不要复制 # 后面是注释,也不要复制)**
打开终端输入

$ rospack list  #查看所在环境的全部软件包

格式:

$ find [package_name]  #使用find可以查找路径

注:[package_name] 是包名

正确命令 如:

$ rospack find roscpp

roscd、rosld 的格式

roscpp/cmake

注:roscpp是包名 /后面是路径的子目录(子目录可以不填)

Tab键:可以输完命令行&包名后自动补全 包名或&路径

3.工作空间&软件包

3.1创建工作空间

  • 工作空间(workspace)是一个存放工程开发相关文件的文件夹。
  • src:代码空间(Source Space)
  • build:编译空间(Build Space)
  • devel:开发空间(Development Space)
  • install:安装空间(Install Space)
$ cd ~
$ mkdir catkin_ws         #创建文件夹

注:每次只复制一句在终端输入,#后面是注释,不要复制

3.2创建存放代码的文件夹

$ cd ~/catkin_ws
$ mkdir src               #src:代码空间(Source Space)

3.3创建软件包,先进去src文件夹

$ cd ~/catkin_ws/src

再使用catkin_create_pkg命令创建一个名为beginner_tutorials的新软件包

这个软件包依赖于std_msgsroscpprospy

$ catkin_create_pkg beginner_tutorials std_msgs rospy roscpp

3.4配置文件

$ cd ~/catkin_ws
$ catkin_make     #编译&生成配置文件

分别生成package.xmlCMakeLists.txt两个配置文件

文件详解:

3.5完成后更新一下环境 (要在工作空间的根目录运行)

$ source ~/catkin_ws/devel/setup.bash

注意:在以后使用ros命令行报错显示找不到包,都要使用上面命令行更新环境,这是临时性的,只对当前终端有效。下面有永久的环境设置,就不用每次都要输入一次了!

3.6更新完,重新构建一下工作空间,编译&生成配置文件

$ cd ~/catkin_ws
$ catkin_make

永久ROS环境设置:

在桌面终端输入命令行,打开bashrc文件:

$ gedit .bashrc

在最下面输入setup.bash的路径,让ROS找到:

source ~/catkin_ws/devel/setup.bash

setup.bash的路径是在你的工作空间里面的,不是固定的,先去工作空间找这个文件,再把你的文件路径写上去!

4.节点nodes

  • 节点Nodes:节点是一个可执行文件,它可以通过ROS来与其他节点进行通信。

ROS客户端库可以让用不同编程语言编写的节点进行相互通信:

  1. rospy = Python客户端库
  2. roscpp = C++客户端库

node节点是在 工作空间ws/src/软件包/src 写入程序cpp&py,更改CMakeLists.txt文件后,用catkin_make编译生成可执行的node程序

  • 4.1运行node,需要新的终端打开并运行roscore
  • 4.2通过包名使用roscore可以运行指定的节点程序
  • 4.3查看在运行的node节点
$ rosnode list
  • 4.4rosrun可以让你用包名直接运行软件包内的节点(而不需要知道包的路径)

用法:

$ rosrun [package_name] [node_name]

注:[package_name]是软件包名称 丨 [node_name]是节点程序

所以现在我们试着运行turtlesim包中的turtlesim_node(小海龟)。

在一个终端中:

$ rosrun turtlesim turtlesim_node
$ rosrun turtlesim turtlesim_node __name:=my_turtle

注:__name:=my_turtle #名字更改为my_turtle

5.话题

节点1与节点2之间需要通过话题去通信,节点1在话题上发布消息,节点2就要订阅话题才能收到节点1的消息

命令行 工具作用
rqt_graph 查看节点和话题的关系
rostopic echo 显示在某个话题上发布的数据
rostopic list 列出当前已被订阅和发布的所有话题
rostopic type 查看所发布话题的消息类型
rostopic pub 将数据发布到当前某个正在广播的话题
rostopic hz 报告话题数据发布的速率。
rqt_plot 在滚动时间图上显示发布到某个话题上的数据

注意:命令行工具的使用都需要开启roscore 。

开始 使用下面的工具需要打开三个终端执行

$ roscore                            #打开第一个新终端,运行ros
$ rosrun turtlesim turtlesim_node    #打开第二个终端,出现小海龟
$ rosrun turtlesim turtle_teleop_key #第三个终端,通过键盘遥控小海龟
5.1 rqt_graph

#查看节点和话题的关系

$ rosrun rqt_graph rqt_graph         #可以简写为 rpt_graph 直接输入

鼠标放在/turtle1/command_velocity上方,两个圆的就是节点,红色就是话题

5.2rostopic

#获取ROS话题的信息

你可以使用帮助选项查看可用的rostopic的子命令,例如:

$ rostopic -h
5.3rostopic echo

#显示在某个话题上发布的数据

用法:

$ rostopic echo [topic]   #[topic]是话题
$ rostopic echo /turtle1/cmd_vel   #例子
5.4rostopic list

#列出当前已被订阅和发布的所有话题

$ rostopic list -v  #可以分别看到订阅和发布的话题
5.5rostopic type

#查看所发布话题的消息类型

$ rostopic type [topic]     #[topic]是话题
5.6rostopic pub

#把数据发布到当前某个正在广播的话题上

rostopic pub [topic] [msg_type] [args]

注:[topic]是话题 丨 [msg_type]是消息类型 丨 [args]是消息&数据

例子:

$ rostopic pub -1 /turtle1/cmd_vel geometry_msgs/Twist -- '[2.0, 0.0, 0.0]' '[0.0, 0.0, 1.8]'

这个 -1是 次数 丨 表明之后的参数都不是选项 丨以上命令会发送一条消息给小海龟,告诉它以2.0大小的线速度和1.8大小的角速度移动

5.7rostopic pub -r命令

#可以来发布源源不断的命令,稳定的频率为1Hz的指令流如下:

rostopic pub /turtle1/cmd_vel geometry_msgs/Twist -r 1 -- '[2.0, 0.0, 0.0]' '[0.0, 0.0, -1.8]'

6.ros服务

服务(Services)是节点之间通讯的第二种方式。服务允许节点发送一个请求(request)并获得一个响应(response)

rosservice

#可以很容易地通过服务附加到ROS客户端/服务器框架上。rosservice有许多可用于服务的命令,如下所示:

用法:

$ rosservice -h       #看到可以用到的命令行
命令行 作用
rosservice list 输出活跃服务的信息
rosservic call 用给定的参数调用服务
rosservice type 输出的服务的类型
rosservice find 按照服务类型查找服务
rosservice uri 输出服务的ROSRPC uri
6.1rosservice list

例子:

$ rosservice list        #查看当前节点提供的所有服务
6.2rosservice call

#给参数调用服务

用法:

$ rosservice call [service] [args]    #[service]是话题 丨 [args]是数据&消息 

例子:(这个命令会重新生成第二只小海龟)这个就是给数据去掉调用&启动服务

$ rosservice call /spawn 2 2 0.2 ""
rosparam

#能让我们在ROS[参数服务器(Parameter Server)](http://wiki.ros.org/Parameter Server)上存储和操作数据

用法:

$ rosparam -h       #看到可以用到的命令行
命令行 作用
rosparam set 设置参数
rosparam get 获取参数
rosparam load 从文件中加载参数
rosparam dump 向文件中转储参数
rosparam delete 删除参数
rosparam list 列出参数名
6.3rosparam list
$ rosparam list              #可以看到turtlesim节点在参数服务器上的所有参数
6.4rosparam set

#修改参数值

$ rosparam set /turtlesim/background_r 150   #修改参数值为150

注:/turtlesim/background_r 这个参数用于设定背景颜色的 r是红色 改为150的色值

修改后需要rosservice call的命令去调用服务使之生效

$ rosservice call /clear

小海龟的背景就会变色了

6.5rosparam get

#获取参数值

$ rosparam get /turtlesim/background_g

注:/turtlesim/background_g 获取参数用于设定背景颜色的值 g是绿色

也可以用rosparam get /来显示参数服务器上的所有内容:

$ rosparam get /
6.6rosparam dump和rosparam load

用法:

$ rosparam dump [file_name] [namespace]
$ rosparam load [file_name] [namespace]

在这里,我们将所有的参数写入params.yaml文件:

$ rosparam dump params.yaml

你甚至可以将yaml文件重载入新的命名空间,例如copy_turtle

rosparam load params.yaml copy_turtle

7.输出信息工具和多节点启动

  • rqt_console连接到了ROS的日志框架,以显示节点的输出信息。
  • rqt_logger_level允许我们在节点运行时改变输出信息的详细级别,包括Debug调试Info信息、Warn警告Fatal 致命Error错误
$ rosrun rqt_console rqt_console             #简写启动rqt_console 
$ rosrun rqt_logger_level rqt_logger_level   #简写启动rqt_logger_level
roslaunch 多节点启动

#roslaunch可以用来启动定义在launch(启动)文件中的节点。

用法:

$ roslaunch [package] [filename.launch]

注:[package]是软件包 丨 [filename.launch] 是在软件包下的luanch文件

$ roscd beginner_tutorials       #回到工作空间的软件包,

注:这里报错的话,source一下环境,上面有命令

$ mkdir launch                   #创建一个launch目录
$ cd launch                      #进去目录
$ touch turtlemimic.launch       #创建一个turtlemimic.launch文件
$ gedit turtlemimic.launch       #通过编辑器打开turtlemimic.launch文件

之后,将下面的文件粘贴在turtlemimic.launch文件里,保存并退出

<launch>

  <group ns="turtlesim1">
    <node pkg="turtlesim" name="sim" type="turtlesim_node"/>
  </group>

  <group ns="turtlesim2">
    <node pkg="turtlesim" name="sim" type="turtlesim_node"/>
  </group>

  <node pkg="turtlesim" name="mimic" type="mimic">
    <remap from="input" to="turtlesim1/turtle1"/>
    <remap from="output" to="turtlesim2/turtle1"/>
  </node>

</launch>

启动launch,多节点运行

& roslaunch beginner_tutorials turtlemimic.launch

通过launch,我们启动了两只小海龟

用rostopic pub向话题发送消息&数据,会同时控制两只小海龟

rostopic pub /turtlesim1/turtle1/cmd_vel geometry_msgs/Twist -r 1 -- '[2.0, 0.0, 0.0]' '[0.0, 0.0, -1.8]'

8.msg和srv

  • msg(消息):msg文件就是文本文件,用于描述ROS消息的字段。它们用于为不同编程语言编写的消息生成源代码。
  • srv(服务):一个srv文件描述一个服务。它由两部分组成:请求(request)和响应(response)。

注:msg文件存放在软件包的msg目录下,srv文件则存放在srv目录下

8.1 msg
$ roscd beginner_tutorials            #回到软件包
$ mkdir msg                           #创建msg文件夹
$ echo "int64 num" > msg/Num.msg      #定义消息类型并创建文件

要更改配置文件package.xml

$ roscd beginner_tutorials              #进去软件包目录
$ gedit package.xml                     #打开package.xml

保它包含以下两行且没有被注释,如果没有,添加进去

<build_depend>message_generation</build_depend>
 <exec_depend>message_runtime</exec_depend>

再更改配置文件CMakeLists.txt

$ roscd beginner_tutorials              #进去软件包目录
$ gedit CMakeLists.txt                  #打开CMakeLists.txt

找到这一句,把message_generation添加上去

find_package(catkin REQUIRED COMPONENTS
   roscpp
   rospy
   std_msgs
   message_generation           #只复制只一句,添加上去
)

再找到add_message_files 修改为下面一样,把前面注释#号删掉

add_message_files(
  FILES
  Num.msg
)

检验

$ rosmsg show beginner_tutorials/Num

&

$ rosmsg show Num
8.2 srv
$ roscd beginner_tutorials                        #回到软件包
$ mkdir srv                                       #创建srv文件夹

现在我们可以从rospy_tutorials包中复制一个服务:

$ roscp rospy_tutorials AddTwoInts.srv srv/AddTwoInts.srv

更改配置文件CMakeLists.txt

$ roscd beginner_tutorials              #进去软件包目录
$ gedit CMakeLists.txt                  #打开CMakeLists.txt

找到add_service_files,修改为下面一样

add_service_files(
  FILES
  AddTwoInts.srv
)

检验

$ rossrv show beginner_tutorials/AddTwoInts

额外 都可以打开子命令查看功能

$ rosmsg -h

&

$ rosmsg show -h

9.发布者和订阅者

以下是python的教程,c++看这个(c++) - 发布者&订阅者i

9.1编写发布者节点

节点”是连接到ROS网络的可执行文件。在这里,我们将创建talker(发布者)节点,该节点将不断广播消息。

1.先回到软件包里

$ roscd beginner_tutorials

2.1首先让我们创建一个脚本目录来存放我们的(Python脚本):

$ mkdir scripts
$ cd scripts

3.下载示例脚本 talker.py 放到scripts目录中并给执行权限

$ wget https://raw.github.com/ros/ros_tutorials/noetic-devel/rospy_tutorials/001_talker_listener/talker.py # 若遇到网络问题,请打开上面文件的链接并复制文本内容到talker.py文件中
$ chmod +x talker.py
9.2编写订阅者节点

下载示例脚本 listener.py 放到scripts目录中并给执行权限

$ roscd beginner_tutorials/scripts/
$ wget https://raw.github.com/ros/ros_tutorials/noetic-devel/rospy_tutorials/001_talker_listener/listener.py # 若遇到网络问题,请打开上面文件的链接并复制文本内容到listener.py文件中
$ chmod +x listener.py

两个节点都完成后,回到catkin工作空间,然后运行catkin_make

$ cd ~/catkin_ws
$ catkin_make
9.3运行发布者

确保roscore已经开启,回到catkin_ws工作空间,source一下环境

我们制作了一个叫做talker的发布者,发布者节点启动:

$ rosrun beginner_tutorials talker      # (C++)
$ rosrun beginner_tutorials talker.py   # (Python)
9.4运行订阅者

上面,我们也制作了一个叫做listener的订阅者,让我们运行它:

$ rosrun beginner_tutorials listener     # (C++)
$ rosrun beginner_tutorials listener.py  # (Python) 

10.客户端和服务端

下面是pychon的,也可以看这个python - 客户端&服务端,c++看这个c++ - 客户端&服务端i

客户端和服务端是通过ros服务通信的,上面的发布者和订阅者是通过话题通信的。

10.1编写服务端

1.先回到软件包

roscd beginner_tutorials

2.在beginner_tutorials包中创建scripts/add_two_ints_server.py文件并粘贴以下内容进去

#!/usr/bin/env python

from __future__ import print_function

from beginner_tutorials.srv import AddTwoInts,AddTwoIntsResponse
import rospy

def handle_add_two_ints(req):
    print("Returning [%s + %s = %s]"%(req.a, req.b, (req.a + req.b)))
    return AddTwoIntsResponse(req.a + req.b)

def add_two_ints_server():
    rospy.init_node('add_two_ints_server')
    s = rospy.Service('add_two_ints', AddTwoInts, handle_add_two_ints)
    print("Ready to add two ints.")
    rospy.spin()

if __name__ == "__main__":
    add_two_ints_server()

3.给节点文件执行权限

$ chmod +x scripts/add_two_ints_server.py

4,找到软件包内的CMakeLists.txt文件,把下面的内容粘贴上去

catkin_install_python(PROGRAMS scripts/add_two_ints_server.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
10.2编写客户端节点

1.在beginner_tutorials包中创建scripts/add_two_ints_client.py文件并粘贴以下内容进去

#!/usr/bin/env python

from __future__ import print_function

import sys
import rospy
from beginner_tutorials.srv import *

def add_two_ints_client(x, y):
    rospy.wait_for_service('add_two_ints')
    try:
        add_two_ints = rospy.ServiceProxy('add_two_ints', AddTwoInts)
        resp1 = add_two_ints(x, y)
        return resp1.sum
    except rospy.ServiceException as e:
        print("Service call failed: %s"%e)

def usage():
    return "%s [x y]"%sys.argv[0]

if __name__ == "__main__":
    if len(sys.argv) == 3:
        x = int(sys.argv[1])
        y = int(sys.argv[2])
    else:
        print(usage())
        sys.exit(1)
    print("Requesting %s+%s"%(x, y))
    print("%s + %s = %s"%(x, y, add_two_ints_client(x, y)))

2.给节点文件执行权限

$ chmod +x scripts/add_two_ints_client.py

3.在你的软件包内的CMakeLists.txt中编辑catkin_install_python()调用

catkin_install_python(PROGRAMS scripts/add_two_ints_server.py scripts/add_two_ints_client.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

4.所有完成后,回到catkin工作空间,然后运行catkin_make

$ cd ~/catkin_ws
$ catkin_make
10.3运行服务端

让我们先开始运行服务:

$ rosrun beginner_tutorials add_two_ints_server     # (C++)
$ rosrun beginner_tutorials add_two_ints_server.py  # (Python)
10.4运行客户端

运行客户端并附带必要的参数:

$ rosrun beginner_tutorials add_two_ints_client 1 3     # (C++)
$ rosrun beginner_tutorials add_two_ints_client.py 1 3  # (Python)

你会看到:

Requesting 1+3
1 + 3 = 4

注:小技巧,报错时,日志中无明显报错信息,一般都是CMakeLists.txt文件写错,可以去碰碰运气

11.录制和回放数据(bag文件)

正在运行的ROS系统中的数据记录到一个bag文件中,然后通过回放这些数据来来重现相似的运行过程。

11.1录制数据(创建bag文件)

这一部分将指导你如何从正在运行的ROS系统中记录话题数据。话题数据将被积累到一个袋(bag)文件中。

首先,在不同的终端中分别执行:

$ roscore                            #打开第一个新终端,运行ros
$ rosrun turtlesim turtlesim_node    #打开第二个终端,出现小海龟
$ rosrun turtlesim turtle_teleop_key #第三个终端,通过键盘遥控小海龟

检查正在运行的话题:

$ rostopic list -v

在用户的根目录建一个临时文件,我们将记录发布的数据保存进去。打开一个新终端:

$ mkdir ~/bagfiles    #创建文件夹
$ cd ~/bagfiles       #进去文件夹
$ rosbag record -a    #运行rosbag record带选项-a,表明所有发布的话题都应该积累在一个bag文件中
  • 然后回到遥控小乌龟节点所在的终端窗口并控制乌龟随意移动10秒钟左右
  • 完成后,在运行rosbag record的窗口中按Ctrl+C以退出。
  • 现在查看~/bagfiles目录中的内容,你应该会看到一个以年份、日期和时间开头且扩展名是.bag的文件
11.2检查bag文件

现在我们已经使用rosbag record命令录制了一个bag文件,接下来我们可以使用rosbag info查看它的内容。我们可以执行info命令检查bag文件的内容而不回放它。在bag文件所在的目录下执行以下命令:

$ rosbag info <your bagfile>

注: 是你刚才录制数据保存下的文件名称

11.3回放bag文件

回放bag文件以再现系统运行过程。首先用Ctrl+C杀死之前运行的遥控小乌龟终端窗口,但让小海龟继续运行。在终端中bag文件所在目录下运行以下命令:

$ rosbag play <your bagfile>

默认模式下,rosbag play命令在公告每条消息后会等待一小段时间(0.2秒)才真正开始发布bag文件中的内容

最终/turtle1/cmd_vel话题将会被发布,同时在turtuelsim终端窗口中乌龟应该会像之前用遥控小海龟控制它那样开始移动

你通过设定一个参数来改变消息发布速率。如果执行:

$ rosbag play -r 2 <your bagfile>
11.4录制指定话题

跟上面一样的操作,只是 rosbag record工具命令改变一下

用法:

$ rosbag record -O subset “话题1” “话题2” “话题3”

例子,在bag文件所在目录下执行以下命令:

rosbag record -O subset /turtle1/cmd_vel /turtle1/pose
  • 上述命令中的-O参数告诉rosbag record将数据记录到名为subset.bag的文件中
  • 而后面的topic参数告诉rosbag record只能订阅这两个指定的话题。
  • 然后通过键盘控制乌龟随意移动几秒钟,最后按Ctrl+C退出rosbag record命令
11.5从bag文件中读取消息

注意先看原文[bag - 读取消息](http://wiki.ros.org/cn/ROS/Tutorials/reading msgs from a bag file)

1.在任何终端中用这个命令,来手动检查所有已发布的话题,以及向每个话题发布了多少消息

$ time rosbag info demo.bag

注:这个 demo.bag 是你刚才录制数据保存下的bag文件名称

或者你已经知道话题名称的话:

$ time rosbag info mybag.bag | grep -E "(topic1|topic2|topic3)"

注:topic 是话题名称

2.先保证启动启动roscore工具

2.1使用rostopic echo命令可以订阅/obs1/gps/fix话题并复读该话题上发布的所有内容,同时用tee命令转储到一个yaml格式的文件中以便之后查看:

$ rostopic echo /obs1/gps/fix | tee topic1.yaml

2.2再打开一个新终端,订阅另一个话题/diagnostics_agg,转储到另一个yaml格式的文件

$ rostopic echo /diagnostics_agg | tee topic2.yaml

3.打开另一个新终端来回放bag文件,使用--immediate选项 回放文件,他就只会发布我们感兴趣的话题

用法:

$ time rosbag play --immediate demo.bag --topics /topic1 /topic2 /topic3 /topicN

例子:

time rosbag play --immediate demo.bag --topics /obs1/gps/fix /diagnostics_agg

4.完成!现在看一下你的两个终端,每个终端都订阅了一个话题,每个话题类型的所有消息用YAML格式输出,(这里要回放bag文件,终端才会有信息输出)

到这里,ROS的基础核心,基本已经学完了。

12.安装系统依赖项

1.进入软件包,ROS packages必须在配置文件中声明他们需要哪些系统依赖项

$ roscd turtlesim               #turtlesim为包名

2.rosdep

rosdep 是一个能够下载并安装ROS packages所需要的系统依赖项的小工具

$ rosdep install [package]            #[package]为包名

13.自定义消息类型

cn/ROS/教程/定义自定义消息 - ROS 维基
1.自定义消息

自定义一个消息类型很简单,只要将.msg文件放到一个包的msg文件夹下即可。请参考创建.msg 文件 (不要忘记选择相应的编译构建系统)。

2.引用和输出消息类型

消息类型都被归属到与package相对应的域名空间下,例如:

c++

1 #include <std_msgs/String.h>
2 
3 std_msgs::String msg;

python

from std_msgs.msg import String
 
msg = String()
3.依赖项

如果你要使用在其他package里定义的消息类型,不要忘记添加以下语句:

<build_depend>name_of_package_containing_custom_msg</build_depend>
<run_depend>name_of_package_containing_custom_msg</run_depend>

到 package.xml文件

结束了

结语

  • 如果你可以耐心看完,到这里的话,我相信你,你虽白袷藍衫,但也犹如那水佩风棠般洒脱,落日熔金时,便是功成名就的白马少年,我将为你拔雪寻春,烧灯续昼,站在那天山外!