ROS入门基础教程 -(快速版)
前言
笔者写的是ros的简单教程,根据官方文档改编,不讲解原理和扩展的话题,只是为了直接上手使用ros,不愿浪费时间逐一了解,直接让小白使用。快人一万步!ros本质就是一个个的工具组成的,一起联合使用,工具之间的配合需要通过话题&服务去通信合作,ros主要是配合linux系统而去维护的,我们最好使用linux系统,所以我们最好使用拥有图形化的乌班图ubuntu,只有20.04及以下版本最后配对ROS1了,22.04已经不支持ROS1了。小白的话最好用虚拟机,不怕搞坏电脑。学习要慢慢学,以下是ROS的核心基础,搞定话的半天可能行了,但是学懂可能要三天以上。
- 昨天之深渊,今日之浅谈,路虽远行之将至,事虽难做其可成。
1.安装并配置ROS环境
配置完成后
看一下啊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_msgs
、roscpp
和rospy
:
$ catkin_create_pkg beginner_tutorials std_msgs rospy roscpp
3.4配置文件
$ cd ~/catkin_ws
$ catkin_make #编译&生成配置文件
分别生成package.xml和CMakeLists.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客户端库可以让用不同编程语言编写的节点进行相互通信:
- rospy = Python客户端库
- 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.4
rosrun
可以让你用包名直接运行软件包内的节点(而不需要知道包的路径)
用法:
$ rosrun [package_name] [node_name]
注:[package_name]是软件包名称 丨 [node_name]是节点程序
所以现在我们试着运行turtlesim
包中的turtlesim_node
(小海龟)。
在一个新终端中:
$ rosrun turtlesim turtlesim_node
- 4.5使用[重映射参数](http://wiki.ros.org/Remapping Arguments)来改变节点名称:
$ 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文件
结束了
结语
- 如果你可以耐心看完,到这里的话,我相信你,你虽白袷藍衫,但也犹如那水佩风棠般洒脱,落日熔金时,便是功成名就的白马少年,我将为你拔雪寻春,烧灯续昼,站在那天山外!