# ROS1基础课程
## 1. ROS系统介绍
### 1.1 ROS操作系统介绍
在学习ROS系统前,我们需要先了解操作系统的定义。操作系统,顾名思义,即提供部分软件和硬件的接口,以供用户直接使用。因此,针对不同的平台、不同的功能,需要采用不同的操作系统来完成底层操作。
ROS系统是适用于机器人的开源操作系统。它提供类似于操作系统的服务,包括硬件抽象描述、底层驱动程序管理、共用功能的执行、程序间消息传递、程序发行包管理,它也提供一些工具和库,用于获取、编译、编写和执行多机融合的程序。
另外,ROS具备进程之间的通信,这是它与其他操作系统之间最大的区别。传统的操作系统,进程之间的通信需要系统来调用,这会消耗大量的系统资源,不适用于作为机器人的操作系统。
一个机器人的构成可能会包含多种传感器,以通过各模块间的通信协作来完成指定任务。因此进程之间有效快速的通信,是一个机器人必备的要求,而ROS则提供了这样的功能。
### 1.2 ROS的特点
(1) 点对点设计,各个功能独立;
(2) 结构简单,集成度高;
(3) 工具包丰富,多语言支持,各个包可以采用不同的编程语言;
(4) 免费且开源;
(5) 社区丰富。
ROS官网:**https://wiki.ros.org**
## 2. ROS系统安装和环境搭建
本节课适用于Jetson Nano官方镜像下从0开始搭建ROS环境,这里提供两种ROS系统的安装方式,"方法一"为一键安装,只需要一条指令即可自动安装整个ROS系统;"方法二"则需要设置下载源配置、设置环境变量等步骤。
如果你是初次接触ROS的用户,建议选择"方法一"一键即可快速安装,在后续根据个人需求可选择"方法二"进行体验。
### 2.1 方法一:一键安装(推荐)
点击系统桌面的图标
,打开命令行终端。在终端输入指令"**wget http://fishros.com/install -O fishros && . fishros**",按下回车,然后输入密码。
```bash
wget http://fishros.com/install -O fishros && . fishros
```
接下来输入数字1,选择一键安装ROS。
在首次安装时需要换源并清理第三方源,所以输入数字1选择更换系统源再安装。
输入数字2选择更换系统源并清理第三方源。
输入数字1选择安装melodic(ROS1)版本。
输入数字1选择安装melodic(ROS1)桌面版,等待安装成功即可。
### 2.2 方法二:逐步安装(常规安装方式)
- #### 2.2.1 版本选择
不同的Ubuntu安装的ROS版本不同,其中Ubuntu18.04的ROS对应版本为Melodic。
- #### 2.2.2 检查Ubuntu的软件和更新源
(1) 找到系统中的"**软件和更新**"。
(2) 确保勾上互联网下载的选项,下载源更换成国内的,以阿里云为例。
- #### 2.2.3 设置ROS的下载源
(1) 设置国内下载源
打开命令行终端,输入指令:
```bash
sudo sh -c '. /etc/lsb-release && echo "deb http://mirrors.ustc.edu.cn/ros/ubuntu/ \`lsb_release -cs\` main" \> /etc/apt/sources.list.d/ros-latest.list'
```
按下回车,接着输入虚拟机的密码"**ubuntu**"(此密码为用户自行设置的,我们这里的密码为ubuntu)。
(2) 设置公匙
输入指令
```bash
sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654
```
按下回车,如下图所示则设置成功。
(3) 更新软件包
```bash
sudo apt update
```
- #### 2.2.4 安装ROS
打开命令行终端,输入指令"**sudo apt install ros-melodic-desktop-full**",等待下载安装完成,根据网络状况不同,安装过程大概要10分钟。
```bash
sudo apt install ros-melodic-desktop-full
```
- #### 2.2.5 设置环境变量
打开命令行终端,依次输入指令"**echo "source /opt/ros/melodic/setup.bash" \>\> ~/.bashrc**"和"**source ~/.bashrc**",完成环境变量配置。
```bash
echo "source /opt/ros/melodic/setup.bash" >> ~/.bashrc
```
```bash
source ~/.bashrc
```
- #### 2.2.6 安装rosdep
输入指令"**sudo apt-get install python3-rosdep**"按下回车,安装rosdep;出现安装确认提示,输入"**Y**"即可。
```bash
sudo apt-get install python3-rosdep
```
(5) 替换完成后,直接点击保存再关闭文件。
(6) 输入指令"**cd /usr/lib/python2.7/dist-packages/rosdep2/**",进入到"**rosdep2**"目录下。
```bash
cd /usr/lib/python2.7/dist-packages/rosdep2/
```
(7) 输入指令"**sudo gedit gbpdistro_support.py**"按下回车,若提示有输入虚拟机密码的提示,我们输入"**ubuntu**"(此密码为用户自行设置的,我们这里的密码为ubuntu),按下回车,即可打开"**gbpdistro_support.py**"文 件,找到"FUERTE_GBPDISTRO_URL"代码。
```bash
sudo gedit gbpdistro_support.py
```
(8) 将" **https://raw.githubusercontent.com/ros/rosdistro/** "修改为" **https://gitee.com/wybros/rosdistro/raw/** ",(只修改下图红框所示内容,后续内容无需更改)修改完成后点击保存,关闭即可。
(9) 接着输入指令"**sudo gedit rep3.py**",打开"**rep3.py**"文件,找到"REP3_TARGETS_URL"代码。
```bash
sudo gedit rep3.py
```
(10) 将" **https://raw.githubusercontent.com/ros/rosdistro/** "修改为" **https://gitee.com/wybros/rosdistro/raw/** ",(只修改下图红框所示内容,后续内容无需更改)修改完成后点击保存,关闭即可。
(11) 接着输入指令"**sudo gedit sources_list.py**",打开"**sources_list.py**"文件,找到"**DEFAULT_SOURCES_LIST_URL**"代码。
```bash
sudo gedit sources_list.py
```
(12) 将" **https://raw.githubusercontent.com/ros/rosdistro/** "修改为" **https://gitee.com/wybros/rosdistro/raw/** ",(只修改下图红框所示内容,后续内容无需更改)修改完成后点击保存,关闭即可。
(13) 输入指令"**cd /usr/lib/python2.7/dist-packages/rosdistro/**",进入"**rosdistro**"目录下。
```bash
cd /usr/lib/python2.7/dist-packages/rosdistro/
```
(14) 输入指令"**sudo gedit \_\_init\_\_.py**",进入"**\_\_init\_\_.py**"文件,找到"DEFAULT_INDEX_URL"代码。
```bash
sudo gedit __init__.py
```
(15) 将" **https://raw.githubusercontent.com/ros/rosdistro/** "修改为" **https://gitee.com/wybros/rosdistro/raw/** ",(只修改下图红框所示内容,后续内容无需更改)修改完成后点击保存,关闭即可。
- #### 2.2.8 更新
(1) 打开新的命令行终端,输入指令"**rosdep update**"更新。
```bash
rosdep update
```
(2) 出现如下信息,则代表更新成功了。
(3) 若出现下图读取超时的提示,可能是网络原因,用户可多输入几次"**rosdep update**"尝试更新;若还是更新不了,用户可检查"[2.2.7 初始化](#anchor_2_2_7)"的内容,确保修改的内容无误,后再次输入"**rosdep update**"进行更新。
## 3. ROS常用术语及命令说明
### 3.1 ROS文件系统的组成
ROS文件是由Packages和Manifests(package.xml)组成。
Packages:功能包,是ROS软件中的基本单元,包含节点源码、配置文件、数据定义等。
Manifest(package xml):功能包的描述文件,用于定义功能包相关元信息之间的依赖关系,这些信息包括版本、维护者和许可协议等。
### 3.2 了解ROS的基本术语
下表是对ROS的部分基本术语的解释说明:
| 术语名称 | 说明 |
节点管理器 (ROS Master) |
负责节点之间的连接与消息通信。 |
| 节点(Node) | 在ROS中运行的最小处理单元,通常是一个可执行文件。每个节点可使用话题或服务与其它节点进行通信。 |
| 消息(Message) | 是int、float和boolean等数据类型的变量。 |
| 话题(Topic) | 一种单向异步通信机制。通过发布消息到话题或订阅话题的形式,可以在节点之间实现数据的传输。话题的类型由对应消息的类型决定。 |
| 发布(Publish) | 以与话题内容对应的消息类型发送数据。 |
| 发布者(Publisher) | 为执行发布,发布者节点在主节点上注册自己的话题等多种信息,并向希望订阅的订阅者节点发送消息。 |
| 订阅(Subscrib) | 以与话题内容对应的消息类型接收数据。 |
| 订阅者(Subscriber) | 为执行订阅,订阅者节点在主节点上注册自己的话题等多种信息,并从主节点接收所有发布了此节点需订阅话题的发布者节点的信息。 |
| 服务(Service) | 一种双向同步通信机制。服务客户端请求对应于特定目的任务的服务,服务服务端进行服务响应。 |
服务服务器 (Service Server) |
以请求作为输入,响应作为输出的节点。 |
服务客户端 (Service Client) |
以响应作为输入,请求作为输出的节点。 |
### 4.2 ROS功能包的创建
(1) 输入指令"**cd ~/catkin_ws/src**",并按下回车,进入catkin_ws的源文件空间(src)目录。
```bash
cd ~/catkin_ws/src
```
(2) 输入指令"**catkin_create_pkg beginner_hiwonder std_msgs rospy roscpp**",并按下回车,创建一个名为"**beginner_hiwonder**"的功能包,添加依赖关系(msgs、rospy、roscpp)。
```bash
catkin_create_pkg beginner_hiwonder std_msgs rospy roscpp
```
(3) 输入指令"**cd ~/catkin_ws**",并按下回车,返回catkin工作空间。
```bash
cd ~/catkin_ws
```
(4) 输入指令"**catkin_make**",并按下回车,完成catkin工作区中功能包的构建。
```bash
catkin_make
```
(5) 输入指令"**echo "source ~/catkin_ws/devel/setup.bash" \>\> ~/.bashrc**",将catkin_ws工作空间添加到ROS环境中,即完成工作空间的创建。
```bash
echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc
```
(6) 输入指令"**source ~/.bashrc**",并按下回车,即完成路径的添加。
```bash
source ~/.bashrc
```
(7) 输入进入功能包所在目录的指令"**roscd beginner_hiwonder**",并按下回车,验证功能包是否创建成功。
```bash
roscd beginner_hiwonder
```
## 5. 编写简单的发布器Publisher
本节以创建一个**velocity_publisher.py**的(发布者)节点为例进行讲解。
(1) 输入指令"**roscd beginner_hiwonder**",回车。进入beginner_hiwonder软件包。
```bash
roscd beginner_hiwonder
```
(2) 输入指令"**mkdir scripts**",回车。新建一个scripts目录存放Python脚本。
```bash
mkdir scripts
```
(3) 输入指令"**cd scripts/**",回车。
```bash
cd scripts/
```
(4) 输入指令"**vi velocity_publisher.py**"编辑程序,复制下面程序。如需修改,再按下"**i**"即可修改。修改完成,按下"**Esc**",输入"**:wq**"保存并退出。
```bash
vi velocity_publisher.py
```
```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将发布turtle1/cmd_vel话题,消息类型geometry_msgs::Twist
import rospy
from geometry_msgs.msg import Twist
def velocity_publisher():
# ROS节点初始化
rospy.init_node('velocity_publisher', anonymous=True)
# 创建一个Publisher,发布名为/turtle1/cmd_vel的topic,消息类型为geometry_msgs::Twist,队列长度10
turtle_vel_pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=10)
#设置循环的频率
rate = rospy.Rate(10)
while not rospy.is_shutdown():
# 初始化geometry_msgs::Twist类型的消息
vel_msg = Twist()
vel_msg.linear.x = 0.5
vel_msg.angular.z = 0.2
# 发布消息
turtle_vel_pub.publish(vel_msg)
rospy.loginfo("Publsh turtle velocity command\[%0.2f m/s, %0.2f rad/s\]",
vel_msg.linear.x, vel_msg.angular.z)
# 按照循环频率延时
rate.sleep()
if __name__ == '__main__':
try:
velocity_publisher()
except rospy.ROSInterruptException:
pass
```
(5) 输入指令"**chmod +x velocity_publisher.py**"回车,为保存的velocity_publisher.py赋予可执行权限。
```bash
chmod +x velocity_publisher.py
```
到此,发布器编辑完成。
## 6. 编写简单的订阅器Subscriber
订阅器是基于编辑了发布器的基础上创建的,只有发布了消息,才有可能订阅。若未编辑发布器,可前往目录"**[5. 编辑简单的发布器Publisher](#anchor_5)**"查看编辑教程。
### 6.1 编写订阅者节点
这里我们以创建一个的pose_subscriber.py节点为例进行讲解。
(1) 输入指令"**cd catkin_ws/src/beginner_hiwonder/scripts/**",回车。
```bash
cd catkin_ws/src/beginner_hiwonder/scripts/
```
(2) 输入指令"**vi pose_subscriber.py**"编辑程序,复制下面程序。如需修改,再按下"**i**"即可修改。修改完成,按下"**Esc**",输入"**:wq**"保存并退出。
```bash
vi pose_subscriber.py
```
```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import rospy
from turtlesim.msg import Pose
def poseCallback(msg):
rospy.loginfo("Turtle pose: x:%0.6f, y:%0.6f", msg.x, msg.y)
def pose_subscriber():
# ROS节点初始化
rospy.init_node('pose_subscriber', anonymous=True)
# 创建一个Subscriber,订阅名为/turtle1/pose的topic,注册回调函数poseCallback
rospy.Subscriber("/turtle1/pose", Pose, poseCallback)
# 循环等待回调函数
rospy.spin()
if __name__ == '__main__':
pose_subscriber()
```
(3) 输入指令"**chmod +x pose_subscriber.py**"回车,为保存的pose_subscriber.py赋予可执行权限。
```bash
chmod +x pose_subscriber.py
```
### 6.2 测试发布者和订阅者
(1) 输入指令"**roscore**",启动节点管理器。
```bash
roscore
```
若已开启,则会出现以下提示:
(2) 再输入指令"**rosrun turtlesim turtlesim_node**",回车,开启小乌龟。
```bash
rosrun turtlesim turtlesim_node
```
(3) 再打开一个新的终端,输入指令"**rosrun beginner_hiwonder velocity_publisher.py**"运行velocity_publisher.py的发布者。按下"Ctrl+C"即可停止发布者节点的运行。
```bash
rosrun beginner_hiwonder velocity_publisher.py
```
(4) 重新打开一个命令行终端,输入指令 "**rosrun beginner_hiwonder pose_subscriber.py**" 运行pose_subscriber.py的订阅者。按下"**Ctrl+C**"即可停止订阅者节点的运行。
```bash
rosrun beginner_hiwonder pose_subscriber.py
```
:::{Note}
1. 启动发布者节点后,订阅者节点才能订阅消息。
2. 若需要完全接收发布者消息,可以先启动订阅者节点再启动发布者节点。
:::
## 7. 话题消息的自定义与使用
### 7.1 自定义话题消息
:::{Note}
在自定义话题消息之前,需要先创建工作空间和功能包,具体操作过程可前往目录"**[4. 创建工作空间与功能包](#anchor_4)**"查看文档。
:::
自定义话题消息的具体操作步骤如下:
(1) 打开命令行终端。
(2) 输入进入功能包所在目录的指令"**roscd beginner_hiwonder**",并按下回车。
```bash
roscd beginner_hiwonder
```
:::{Note}
若出现提示"**No such package/stack ‘beginner_hiwonder’**",即功能包不存在于环境变量ROS_PACKAGE_PATH中,具体解决方法可前往目录"**[4. 创建工作空间与功能包](#anchor_4)**"查看文档,解决此问题后,请重复一次当前步骤的操作。
:::
(3) 输入指令"**mkdir msg**",并按下回车,新建用于存放文本文件的文件夹"**msg**"。
```bash
mkdir msg
```
(4) 输入指令"**cd msg**",回车。
```bash
cd msg
```
(5) 输入指令"**vi Person.msg**"编辑程序,复制下面程序。如需修改,再按下"**i**"即可修改。修改完成,按下"**Esc**",输入"**:wq**"保存并退出。
```bash
vi Person.msg
```
```
string name
uint8 age
uint8 sex
uint8 unknown = 0
uint8 male = 1
uint8 female = 2
```
(6) 输入"**vi package.xml**",复制下面程序,在下图所示位置添加功能包依赖。如需修改,再按下"**i**"即可修改。修改完成,按下"**Esc**",输入"**:wq**"保存并退出。
```bash
vi package.xml
```
(7) 在下图所示位置添加功能包依赖:
```bash
(8) 输入"**vi CMakeLists.txt**",再按下"**i**",修改"**CMakeLists.txt**"文件。
```bash
vi CMakeLists.txt
```
(9) 在下图所示位置添加所需的编译选项"**message_generation**"。
(10) 找到下图所示代码,将红框部分进行反注释,并添加所需的编译选项"**Person.msg**"。
(11) 找到下图所示代码,将红框部分进行反注释,确保所需的编译选项生效。
(12) 找到下图所示代码,将红框部分进行反注释,并添加所需的编译选项"**message_runtime**"。
(13) 修改完成,按下"**Esc**",输入"**:wq**"保存并退出。
(14) 输入指令"**rosmsg show beginner_hiwonder/Person**",并按下回车,查看写入的消息字段能否被系统识别。当出现下图红框所示字样,即代表识别成功。
```bash
rosmsg show beginner_hiwonder/Person
```
### 7.2 话题消息的使用
- #### 7.2.1 创建发布者和订阅者代码
(1) 打开命令行终端。
(2) 输入进入功能包所在目录的指令"**roscd beginner_hiwonder**",并按下回车。
```bash
roscd beginner_hiwonder
```
(3) 输入指令"**cd scripts**",并按下回车,进入用于存放Python脚本的文件夹"**scripts**"。
```bash
cd scripts
```
(4) 输入指令"**vi person_publisher.py**"编辑程序,复制下面程序。如需修改,再按下"**i**"即可修改。修改完成,按下"**Esc**",输入"**:wq**"保存并退出。
```bash
vi person_publisher.py
```
```python
#!/usr/bin/env python
# -\*- coding: utf-8 -\*-
# 该例程将发布/person_info话题,自定义消息类型beginner_hiwonder::Person
import rospy
from beginner_hiwonder.msg import Person
def velocity_publisher():
# ROS节点初始化
rospy.init_node('person_publisher', anonymous=True)
# 创建一个Publisher,发布名为/person_info的topic,消息类型为beginner_hiwonder::Person,队列长度10
person_info_pub = rospy.Publisher('/person_info', Person, queue_size=10)
#设置循环的频率
rate = rospy.Rate(10)
while not rospy.is_shutdown():
# 初始化beginner_hiwonder::Person类型的消息
person_msg = Person()
person_msg.name = "Tom";
person_msg.age = 18;
person_msg.sex = Person.male;
# 发布消息
person_info_pub.publish(person_msg)
rospy.loginfo("Publsh person message\[%s, %d, %d\]",
person_msg.name, person_msg.age, person_msg.sex)
# 按照循环频率延时
rate.sleep()
if __name__ == '__main__':
try:
velocity_publisher()
except rospy.ROSInterruptException:
pass
```
(5) 输入指令"**vi person_subscriber.py**"编辑程序,复制下面程序。如需修改,再按下"**i**"即可修改。修改完成,按下"**Esc**",输入"**:wq**"保存并退出。
```bash
vi person_subscriber.py
```
```python
#!/usr/bin/env python
# -\*- coding: utf-8 -\*-
# 该例程将订阅/person_info话题,自定义消息类型beginner_hiwonder::Person
import rospy
from beginner_hiwonder.msg import Person
def personInfoCallback(msg):
rospy.loginfo("Subcribe Person Info: name:%s age:%d sex:%d",
msg.name, msg.age, msg.sex)
def person_subscriber():
# ROS节点初始化
rospy.init_node('person_subscriber', anonymous=True)
# 创建一个Subscriber,订阅名为/person_info的topic,注册回调函数personInfoCallback
rospy.Subscriber("/person_info", Person, personInfoCallback)
# 循环等待回调函数
rospy.spin()
if __name__ == '__main__':
person_subscriber()
```
(6) 输入指令"**chmod +x person_publisher.py**"回车,为保存的person_publisher.py赋予可执行权限。
```bash
chmod +x person_publisher.py
```
(7) 输入指令"**chmod +x person_subscriber.py**"回车,为保存的person_publisher.py赋予可执行权限。
```bash
chmod +x person_subscriber.py
```
- #### 7.2.2 运行发布者和订阅者节点
(1) 输入指令"**cd ~/catkin_ws**",并按下回车,进入catkin工作空间。
```bash
cd ~/catkin_ws
```
(2) 输入指令"**catkin_make**",并按下回车,构建目录中所有的功能包。
```bash
catkin_make
```
(3) 输入指令"**source ./devel/setup.bash**",并按下回车,刷新工作空间的环境。
```bash
source ./devel/setup.bash
```
(4) 输入指令"**roscore**",启动节点管理器。
```bash
roscore
```
若已开启,则会出现以下提示:
(5) 输入指令"**rosrun beginner_hiwonder person_publisher.py**",并按下回车,运行发布者节点。如需停止节点的运行,可按下快捷键"**Ctrl+C**"。
```bash
rosrun beginner_hiwonder person_publisher.py
```
(6) 打开一个新的命令行终端,输入指令 "**rosrun beginner_hiwonder person_subscriber.py**",并按下回车,运行订阅者节点。如需停止节点的运行,可按下快捷键"**Ctrl+C**"。
```bash
rosrun beginner_hiwonder person_subscriber.py
```
:::{Note}
1. 需要先启动发布者节点,订阅者节点才可订阅消息;
2. 若需完全接收发布者消息,可以先启动订阅者节点,再启动发布者节点。
:::
## 8. 编写简单的客户端Client
本节以创建简单的服务(Client)节点turtle_spawn.py为例进行讲解。该节点通过程序的形式发布一个让客户端产生一个新的小乌龟的请求。
### 8.1 配置客户端代码编译规则
(1) 输入指令"**cd catkin_ws/src/beginner_hiwonder/scripts/**",回车。
```bash
cd catkin_ws/src/beginner_hiwonder/scripts/
```
(2) 输入指令"**vi turtle_spawn.py**"编辑程序,复制下面程序。如需修改,再按下"**i**"即可修改。修改完成,按下"**Esc**",输入"**:wq**"保存并退出。
```bash
vi turtle_spawn.py
```
```python
#!/usr/bin/env python
# -\*- coding: utf-8 -\*-
# 该例程将请求/spawn服务,服务数据类型turtlesim::Spawn
import sys
import rospy
from turtlesim.srv import Spawn
def turtle_spawn():
# ROS节点初始化
rospy.init_node('turtle_spawn')
# 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的service
rospy.wait_for_service('/spawn')
try:
add_turtle = rospy.ServiceProxy('/spawn', Spawn)
# 请求服务调用,输入请求数据
response = add_turtle(2.0, 2.0, 0.0, "turtle2")
return response.name
except rospy.ServiceException:
pass
if __name__ == "__main__":
#服务调用并显示调用结果
name = turtle_spawn()
print("Spwan turtle successfully \[name:{}\]".format(name))
```
(3) 输入指令"**chmod +x turtle_spawn.py**"回车,为保存的turtle_spawn.py赋予可执行权限。
```bash
chmod +x turtle_spawn.py
```
### 8.2 运行客户端
(1) 输入指令"**roscore**",启动节点管理器。
```bash
roscore
```
若已开启,则会出现以下提示:
(3) 输入指令"**rosrun turtlesim turtlesim_node**",回车,开启小乌龟。
```bash
rosrun turtlesim turtlesim_node
```
此时,界面会弹出小乌龟运行窗口,如下图所示:
(4) 重新打开一个命令行终端,输入指令"**rosrun beginner_hiwonder turtle_spawn.py**"回车,运行客户端。
```bash
rosrun beginner_hiwonder turtle_spawn.py
```
这时,客户端发送请求至服务端,并应答开启另一个小乌龟,如下图所示:
## 9. 编写简单的服务端Server
### 9.1 创建服务器代码
:::{Note}
在创建服务器代码之前,需要先创建工作空间和功能包,具体操作过程可前往目录"**[4. 创建工作空间与功能包](#anchor_4)**"查看文档。
:::
(1) 输入指令"**cd catkin_ws/src/beginner_hiwonder/scripts/**",回车。
```bash
cd catkin_ws/src/beginner_hiwonder/scripts/
```
(2) 输入指令"**vi turtle_command_server.py**"编辑程序,复制下面程序。如需修改,再按下"**i**"即可修改。修改完成,按下"**Esc**",输入"**:wq**"保存并退出。
```bash
vi turtle_command_server.py
```
```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import rospy
import thread,time
from geometry_msgs.msg import Twist
from std_srvs.srv import Trigger, TriggerResponse
pubCommand = False;
turtle_vel_pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=10)
def command_thread():
while True:
if pubCommand:
vel_msg = Twist()
vel_msg.linear.x = 0.5
vel_msg.angular.z = 0.2
turtle_vel_pub.publish(vel_msg)
time.sleep(0.1)
def commandCallback(req):
global pubCommand
pubCommand = bool(1-pubCommand)
rospy.loginfo("Publish turtle velocity command\![%d\]", pubCommand)
return TriggerResponse(1, "Change turtle command state!")
def turtle_command_server():
rospy.init_node('turtle_command_server')
s = rospy.Service('/turtle_command', Trigger, commandCallback)
print "Ready to receive turtle command."
thread.start_new_thread(command_thread, ())
rospy.spin()
if __name__ == "__main__":
turtle_command_server()
```
(3) 输入指令"**chmod +x turtle_command_server.py**",并按下回车,为保存的turtle_command_server.py赋予可执行权限。
```bash
chmod +x turtle_command_server.py
```
### 9.2 运行服务器节点
(1) 输入指令"**roscore**",启动节点管理器。
```bash
roscore
```
若已开启,则会出现以下提示:
(2) 输入指令"**rosrun turtlesim turtlesim_node**",并按下回车,启动小乌龟仿真器。
```bash
rosrun turtlesim turtlesim_node
```
(3) 打开一个新的命令行终端,输入指令"**rosrun beginner_hiwonder turtle_command_server.py**",并按下回车,运行服务器节点。如需停止节点的运行,可按下快捷键"**Ctrl+C**"。
```bash
rosrun beginner_hiwonder turtle_command_server.py
```
(4) 再次打开一个新的命令行终端,输入指令"**rosservice call /turtle_command "{}"**",并按下回车,令小乌龟沿着圆形轨迹移动。
```bash
rosservice call /turtle_command "{}"
```
## 10. 服务数据的自定义与使用
### 10.1 自定义服务数据
:::{Note}
在自定义服务数据之前,需要先创建工作空间和功能包,具体操作过程可前往目录"**[4. 创建工作空间与功能包](#anchor_4)**"查看文档。
:::
自定义服务数据的具体操作步骤如下:
(1) 打开命令行终端。
(2) 输入进入功能包所在目录的指令"**roscd beginner_hiwonder**",并按下回车。
```bash
roscd beginner_hiwonder
```
:::{Note}
若出现提示"**No such package/stack ‘beginner_hiwonder’**",即功能包不存在于环境变量ROS_PACKAGE_PATH中,具体解决方法可前往目录"**[4. 创建工作空间与功能包](#anchor_4)**"查看文档,解决此问题后,请重复一次当前步骤的操作。
:::
(3) 输入指令"**mkdir srv**",并按下回车,新建用于存放文本文件的文件夹"**srv**"。
```bash
mkdir srv
```
(4) 输入指令"**vi Person.srv**"编辑程序,复制下面程序。如需修改,再按下"**i**"即可修改。修改完成,按下"**Esc**",输入"**:wq**"保存并退出。
```bash
vi Person.srv
```
```bash
string name
int8 age
int8 sex
int8 unknown = 0
int8 male = 1
int8 female = 2
---
string result
```
(5) 输入"**cd ~/catkin_ws/src/beginner_hiwonder/**",按下回车。
```bash
cd ~/catkin_ws/src/beginner_hiwonder/
```
(6) 输入"**vi package.xml**",复制下面程序,在下图所示位置添加功能包依赖。如需修改,再按下"**i**"即可修改。修改完成,按下"**Esc**",输入"**:wq**"保存并退出。
```bash
vi package.xml
```
```bash
(7) 输入"**vi CMakeLists.txt**",再按下"**i**",修改"**CMakeLists.txt**"文件。
```bash
vi CMakeLists.txt
```
(8) 在下图所示位置添加所需的编译选项"**message_generation**"。
(9) 找到下图所示代码,将红框部分进行反注释,并添加所需的编译选项"**Person.srv**"。
(10) 找到下图所示代码,将红框部分进行反注释,确保所需的编译选项生效。
(11) 找到下图所示代码,将红框部分进行反注释,并添加所需的编译选项"**message_runtime**"。
(12) 修改完成,按下"**Esc**",输入"**:wq**"保存并退出。
(14) 输入指令"**rossrv show beginner_hiwonder/Person**",并按下回车,查看写入的消息字段能否被系统识别。当出现下图红框所示字样,即代表识别成功。
```bash
rossrv show beginner_hiwonder/Person
```
### 10.2 服务数据的使用
- #### 10.2.1 创建服务器和客户端代码
(1) 打开Linux命令行终端。
(2) 输入指令"**cd catkin_ws/src/beginner_hiwonder/scripts/**",并按下回车,进入用于存放Python脚本的文件夹"**scripts**"。
```bash
cd catkin_ws/src/beginner_hiwonder/scripts/
```
(3) 输入指令"**vi person_server.py**"编辑程序,复制下面程序。如需修改,再按下"**i**"即可修改。修改完成,按下"**Esc**",输入"**:wq**"保存并退出。
```bash
vi person_server.py
```
```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将执行/show_person服务,服务数据类型beginner_hiwonder::Person
import rospy
from beginner_hiwonder.srv import Person, PersonResponse
def personCallback(req):
# 显示请求数据
rospy.loginfo("Person: name:%s age:%d sex:%d", req.name, req.age, req.sex)
# 反馈数据
return PersonResponse("OK")
def person_server():
# ROS节点初始化
rospy.init_node('person_server')
# 创建一个名为/show_person的server,注册回调函数personCallback
s = rospy.Service('/show_person', Person, personCallback)
# 循环等待回调函数
print "Ready to show person informtion."
rospy.spin()
if __name__ == "__main__":
person_server()
```
(5) 输入指令"**vi person_client.py**"编辑程序,复制下面程序。如需修改,再按下"**i**"即可修改。修改完成,按下"**Esc**",输入"**:wq**"保存并退出。
```bash
vi person_client.py
```
```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将请求/show_person服务,服务数据类型beginner_hiwonder::Person
import sys
import rospy
from beginner_hiwonder.srv import Person, PersonRequest
def person_client():
# ROS节点初始化
rospy.init_node('person_client')
# 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的service
rospy.wait_for_service('/show_person')
try:
person_client = rospy.ServiceProxy('/show_person', Person)
# 请求服务调用,输入请求数据
response = person_client("Tom", 20, PersonRequest.male)
return response.result
except rospy.ServiceException, e:
print "Service call failed: %s"%e
if __name__ == "__main__":
#服务调用并显示调用结果
print "Show person result : %s" %(person_client())
```
(5) 输入指令"**chmod +x person_server.py**"和"**chmod +x person_client.py**",并按下回车,赋予文件可执行权限。
```bash
chmod +x person_server.py
```
### 10.3 运行服务器和客户端节点
(1) 输入指令"**cd ~/catkin_ws**",并按下回车,进入catkin工作空间。
```bash
cd ~/catkin_ws
```
(2) 输入指令"**catkin_make**",并按下回车,构建目录中所有的功能包。
```bash
catkin_make
```
(3) 输入指令"**source ./devel/setup.bash**",并按下回车,刷新工作空间的环境。
```bash
source ./devel/setup.bash
```
(4) 输入指令"**roscore**",并按下回车,启动节点管理器。
```bash
roscore
```
若已开启,则会出现以下提示:
(5) 输入指令"**rosrun beginner_hiwonder person_server.py**",并按下回车,运行服务器节点。如需停止节点的运行,可按下快捷键"**Ctrl+C**"。
```bash
rosrun beginner_hiwonder person_server.py
```
(6) 打开一个新的命令行终端,输入指令"**rosrun beginner_hiwonder person_client.py**",并按下回车,运行客户端节点。
```bash
rosrun beginner_hiwonder person_client.py
```
(7) 运行客户端节点后,启动服务器节点的终端窗口会打印下图红框所示内容。
## 11. 参数的使用与编程方法
### 11.1 服务模型
在ROS master当中有一个参数服务器,它是一个全局字典,用来保存各个节点之间的配置参数的。例如里面有Parameter server保存我们的名字、半径和高度,是各个节点都可以全局访问的。
比如说我在Node A点里面来访问robot name,然后就会获取得到一个"my_rot"的值,它只要给我们的ROS master去发送一个查询的请求,然后就会返回"my_rot"的结果。Node B、Node C和Node D也是一样。
Parameter server参数服务器模型如下图所示:
### 11.2 rosparam参数
- #### 11.2.1 rosparam详细参数
这里我们先来了解下rosparam参数,详细参数如下图:
- #### 11.2.2 运行海龟例程
这里以海龟案例为例,先运行海龟例程,步骤如下:
(1) 输入指令"**roscore**",回车。
```bash
roscore
```
若已开启,则会出现以下提示:
(2) 输入指令"**rosrun turtlesim turtlesim_node**",回车,打开小海龟的仿真器。
```bash
rosrun turtlesim turtlesim_node
```
- #### 11.2.3 rosparam的使用
再打开一个终端, rosparam的使用,步骤如下:
(1) 输入指令"**rosparam**",回车。
```bash
rosparam
```
(2) 输入指令"**rosparam list**",回车,查询海龟参数个数。
```bash
rosparam list
```
(3) 输入指令"**rosparam get /turtlesim/background_b**",回车,获取"**background_b**"数值,其他数值获取方法类似。
```bash
rosparam get /turtlesim/background_b
```
(4) 输入指令"**rosparam set /turtlesim/background_b 100**",回车,设置"**background_b**"数值,其他数值设置方法类似。
```bash
rosparam set /turtlesim/background_b 100
```
(5) 输入指令"**rosparam get /turtlesim/background_b**",回车,看到数值改为100了。
```bash
rosparam get /turtlesim/background_b
```
(6) 输入指令"**rosservice call clear "{}"**",回车,发送请求,更改颜色。
```bash
rosservice call clear "{}"
```
(7) 输入指令"**rosparam dump param.yaml**",回车,保存到文件。
```bash
rosparam dump param.yaml
```
(8) 文件打开在默认路径,我们保存在主文件路径,直接打开。
(9) 输入指令"**vi param.yaml**",回车。按下"**i**"修改"**param.yaml**"。
```bash
vi param.yaml
```
(10) 可以将颜色都改为0,也就是黑色,修改完成,按下"**Esc**",输入"**:wq**"保存并退出。
(11) 输入指令"**rosparam load param.yaml**",回车,加载文件。
```bash
rosparam load param.yaml
```
(12) 输入指令"**rosparam get /turtlesim/background_b**",回车,检查加载效果。
```bash
rosparam get /turtlesim/background_b
```
(13) 输入指令"**rosservice call clear "{}"**",回车,发送请求,更改颜色,背景颜色为黑色。
```bash
rosservice call clear "{}"
```
(14) 输入指令"**rosparam delete /turtlesim/background_g**",回车,删除g的颜色。
```bash
rosparam delete /turtlesim/background_g
```
(15) 输入指令"**rosparam list**",回车,查看效果。
```bash
rosparam list
```
(16) 输入指令"**rosservice call clear "{}"**",回车,重新刷新背景颜色,查看效果。
```bash
rosservice call clear "{}"
```
### 11.3 编程方法
创建功能包,步骤如下:
(1) 输入指令"**cd catkin_ws/src/**",回车,进入工作空间。
```bash
cd catkin_ws/src/
```
(2) 输入指令"**catkin_create_pkg parameter_hiwonder rospy std_msgs**",回车,创建功能包。
```bash
catkin_create_pkg parameter_hiwonder rospy std_msgs
```
- #### 11.3.1 编写控制程序
(1) 打开Linux命令行终端。
(2) 输入进入功能包所在目录的指令"**roscd parameter_hiwonder**",并按下回车。
```bash
roscd parameter_hiwonder
```
(3) 输入指令"**mkdir scripts**",并按下回车,新建用于存放Python脚本的文件夹"**scripts**"。
```bash
mkdir scripts
```
(4) 输入指令"**cd scripts/**",并按下回车,进入用于存放Python脚本的文件夹"**scripts**"。
```bash
cd scripts/
```
(5) 输入指令"**vi parameter_config.py**"编辑程序,复制下面程序。如需修改,再按下"**i**"即可修改。修改完成,按下"**Esc**",输入"**:wq**"保存并退出。
```bash
vi parameter_config.py
```
```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程设置/读取海龟例程中的参数
import sys
import rospy
from std_srvs.srv import Empty
def parameter_config():
# ROS节点初始化
rospy.init_node('parameter_config', anonymous=True)
# 读取背景颜色参数
red = rospy.get_param('/turtlesim/background_r')
green = rospy.get_param('/turtlesim/background_g')
blue = rospy.get_param('/turtlesim/background_b')
rospy.loginfo("Get Backgroud Color\[%d, %d, %d\]", red, green, blue)
# 设置背景颜色参数
rospy.set_param("/turtlesim/background_r", 255);
rospy.set_param("/turtlesim/background_g", 255);
rospy.set_param("/turtlesim/background_b", 255);
rospy.loginfo("Set Backgroud Color\[255, 255, 255\]");
# 读取背景颜色参数
red = rospy.get_param('/turtlesim/background_r')
green = rospy.get_param('/turtlesim/background_g')
blue = rospy.get_param('/turtlesim/background_b')
rospy.loginfo("Get Backgroud Color\[%d, %d, %d\]", red, green, blue)
# 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的service
rospy.wait_for_service('/clear')
try:
clear_background = rospy.ServiceProxy('/clear', Empty)
# 请求服务调用,输入请求数据
response = clear_background()
return response
except rospy.ServiceException:
pass
if __name__ == "__main__":
parameter_config()
```
(6) 输入指令"**chmod +x parameter_config.py**"回车,为保存的parameter_config.py赋予可执行权限。
```bash
chmod +x parameter_config.py
```
### 11.4 运行程序
(1) 输入指令"**roscore**",并按下回车,启动节点管理器。
```bash
roscore
```
若已开启,则会出现以下提示:
(2) 输入指令"**rosrun turtlesim turtlesim_node**",回车,打开小海龟的仿真器。
```bash
rosrun turtlesim turtlesim_node
```
(3) 输入指令"**rosrun parameter_hiwonder parameter_config.py**",并按下回车,运行程序,它将海龟的背景颜色改为白色,显示如下图:
```bash
rosrun parameter_hiwonder parameter_config.py
```
(4) 如需停止程序,可按下快捷键"**Ctrl+C**"。
## 12. Launch启动文件的使用方法
### 12.1 本节前言
我们在前面的教程里面通过命令行来尝试运行新的节点。但随着创建越来越复杂的机器人系统中,打开多个终端且重新输入设置就变得越来越麻烦。
因此我们可以通过创建一个Launch文件,可以同时启动并配置多个需执行的ROS节点,启动更多的功能,另外还可自动启动Ros Master。
### 12.2 Lanuch文件基本语法
- #### 12.2.1 标签说明
Lanuch文件:通过XML文件实现多节点的配置和启动。
```xml
(5) 复制下方内容至的文件内。
```xml
(6) 按下"**Esc**"键,输入"**:**",然后输入"**wq**"保存并退出。
(7) 输入指令"**roslaunch beginner_hiwonder turtlesim_launch_test.lanuch**",即可启动小乌龟程序。
```bash
roslaunch beginner_hiwonder turtlesim_launch_test.lanuch
```
## 13. TF坐标系广播与监听的编程实现
### 13.1 TF介绍
- #### 13.1.1 TF概念
TF(TransForm),就是坐标转换(是一个坐标在不同坐标系下的表示),包括了位置和姿态两个方面的变换。
ROS中机器人模型包含大量的部件,每一个部件统称之为link(比如手部、头部、某个关节、某个连杆),每一个link上面对应着一个frame(坐标系),用frame表示该部件的坐标系,frame和link是绑定在一起的。
TF是一个树状结构,维护坐标系之间的关系,靠话题通信机制来持续地发布不同link之间的坐标关系。作为树状结构,要保证父子坐标系都有某个节点在持续地发布他们之间的位姿关系,才能使树状结构保持完整。只有父子坐标系的位姿关系能被正确的发布,才能保证任意两个frame之间的连通。
如果出现某一环节的断裂,就会引发error系统报错.所以完整的tf tree不能有任何断层的地方,这样我们才能查清楚任意两个frame之间的关系。
每两个相邻frame之间靠节点发布它们之间的位姿关系,这种节点称为broadcaster。broadcaster就是一个发布器publisher,如果两个frame之间发生了相对运动,broadcaster就会发布相关消息。
- #### 13.1.2 TF坐标系表示规范
每个坐标系都有一个父坐标系,可以有多个子坐标系。TF树就是以父子坐标系的形式来组织的,最上面是父坐标系,往下是子坐标系。
在TF树中具有父子关系的坐标系是相邻的,用带箭头的线连接起来。在TF树中用箭头表示这种父子关系。
上图所表示的TF树中base_link坐标系是base_footprint的子坐标系,base_cover_link坐标系也是base_footprint的子坐标系。
- #### 13.1.3 TF树的通信规范
TF树的建立和维护是基于Topic通信机制的。
根据TF树的原理,它是靠建立与维护每个父子坐标系的变换关系来维护整个系统的所有坐标系的变换关系的。每个parent 坐标系到child坐标系变换关系是靠被称为broadcastor的发布器节点来持续发布的。
虽然是靠Topic通信机制发布的parent 坐标系到child坐标系的变换,但并不是让每一对父子坐标系都发布一个话题,实际上发布的唯一个话题是/topic,该话题集合了所有发布的父子坐标系的变换关系。
也就是说TF机制并不是让每一对父子坐标系都发布一个话题,而是将所有的父子坐标系都集合到到一个话题上,该话题的消息中传递的数据是所有父子坐标系的变换关系,是父子坐标系变换关系的一个大数组。
使用TF的tflisener就可以监听从任意两个坐标系的变换。前提是TF的树上能把这两个联通。
### 13.2 机器人的坐标变换
在进行编程前,先需要了解机器人的坐标变换。这里以运行海龟案例来进行解说,步骤如下:
(1) 输入指令"**sudo apt-get install ros-melodic-turtle-tf**",安装功能包。
```bash
sudo apt-get install ros-melodic-turtle-tf
```
其中"**melodic**"对应的是ROS版本。
(2) 输入指令"**roslaunch turtle_tf turtle_tf_demo.launch**",启动launch文件。
```bash
roslaunch turtle_tf turtle_tf_demo.launch
```
(3) 输入指令"**rosrun turtlesim turtle_teleop_key**",运行海龟键盘控制节点。
```bash
rosrun turtlesim turtle_teleop_key
```
(4) 输入指令"**rosrun rqt_tf_tree rqt_tf_tree**",可视化框架。
可以看到当前系统TF坐标之间的位置关系,如下图:
### 13.3 创建功能包
下面,就开始创建功能包,步骤如下:
(1) 输入指令"**cd catkin_ws/src/**",回车,进入工作空间。
```bash
cd catkin_ws/src/
```
5) 输入指令"**catkin_create_pkg tf_hiwonder rospy std_msgs**",回车,创建功能包。
```bash
catkin_create_pkg tf_hiwonder rospy std_msgs
```
### 13.4 编程方法
- #### 13.4.1 编写广播和监听程序
(1) 打开Linux命令行终端。
(2) 输入进入功能包所在目录的指令"**roscd tf_hiwonder**",并按下回车。
```bash
roscd tf_hiwonder
```
(3) 输入指令"**mkdir scripts**",并按下回车,新建用于存放Python脚本的文件夹"**scripts**"。
```bash
mkdir scripts
```
(4) 输入指令"**cd scripts/**",并按下回车,进入用于存放Python脚本的文件夹"**scripts**"。
```bash
cd scripts/
```
(5) 输入指令"**vi turtle_tf_broadcaster.py**"编辑程序,复制下面程序。如需修改,再按下"**i**"即可修改。修改完成,按下"**Esc**",输入"**:wq**"保存并退出。
```bash
vi turtle_tf_broadcaster.py
```
```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将请求/show_person服务,服务数据类型learning_service::Person
import tf
import rospy
import turtlesim.msg
def handle_turtle_pose(msg, turtlename):
br = tf.TransformBroadcaster()
br.sendTransform((msg.x, msg.y, 0),
tf.transformations.quaternion_from_euler(0, 0, msg.theta),
rospy.Time.now(),
turtlename,
"world")
if __name__ == '__main__':
rospy.init_node('turtle_tf_broadcaster')
turtlename = rospy.get_param('~turtle')
rospy.Subscriber('/%s/pose' % turtlename,
turtlesim.msg.Pose,
handle_turtle_pose,
turtlename)
rospy.spin()
```
(6) 输入指令"**vi turtle_tf_listener.py**"编辑程序,复制下面程序。如需修改,再按下"**i**"即可修改。修改完成,按下"**Esc**",输入"**:wq**"保存并退出。
```bash
vi turtle_tf_listener.py
```
```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将请求/show_person服务,服务数据类型learning_service::Person
import roslib
import rospy
import math
import tf
import geometry_msgs.msg
import turtlesim.srv
if __name__ == '__main__':
rospy.init_node('turtle_tf_listener')
listener = tf.TransformListener()
rospy.wait_for_service('spawn')
spawner = rospy.ServiceProxy('spawn', turtlesim.srv.Spawn)
spawner(4, 2, 0, 'turtle2')
turtle_vel = rospy.Publisher('turtle2/cmd_vel', geometry_msgs.msg.Twist,queue_size=1)
rate = rospy.Rate(10.0)
while not rospy.is_shutdown():
try:
(trans,rot) = listener.lookupTransform('/turtle2', '/turtle1', rospy.Time(0))
except (tf.LookupException, tf.ConnectivityException, tf.ExtrapolationException):
continue
angular = 4 \* math.atan2(trans\[1\], trans\[0\])
linear = 0.5 \* math.sqrt(trans\[0\] \*\* 2 + trans\[1\] \*\* 2)
cmd = geometry_msgs.msg.Twist()
cmd.linear.x = linear
cmd.angular.z = angular
turtle_vel.publish(cmd)
rate.sleep()
```
(7) 输入指令"**chmod +x turtle_tf_broadcaster.py**"和"**chmod +x turtle_tf_listener.py**",并按下回车,赋予文件可执行权限。
```bash
chmod +x turtle_tf_broadcaster.py
```
```bash
chmod +x turtle_tf_listener.py
```
(8) 输入指令"**cd ..**"和"**mkdir launch**",新建用于存放launch脚本的文件夹"**launch**"。
```bash
cd ..
```
```bash
mkdir launch
```
(9) 输入指令"**cd launch/**",并按下回车,进入用于存放Python脚本的文件夹"**launch**"。
```bash
cd launch/
```
(10) 输入指令"**vi start_tf_demo_py.launch**"编辑程序,复制下面程序。如需修改,再按下"**i**"即可修改。修改完成,按下"**Esc**",输入"**:wq**"保存并退出。
```bash
vi start_tf_demo_py.launch
```
```xml
- #### 13.4.2 运行程序
(1) 输入指令"**source ./devel/setup.bash**",并按下回车,设置工作环境。
```bash
source ./devel/setup.bash
```
(2) 输入指令"**roslaunch tf_hiwonder start_tf_demo_py.launch**",并按下回车,运行launch程序。
```bash
roslaunch tf_hiwonder start_tf_demo_py.launch
```
一只海龟自动行走到另一只海龟位置,显示如下图:
(3) 如需程序,可按下快捷键"**Ctrl+C**"。
## 14. 常用可视化工具的使用
### 14.1 RQT工具介绍
- #### 14.1.1 概述
RQT是ROS提供的一个图形化用户接口框架,它允许以插件的形式来实现各种图形工具和接口。
RQT中能够以可停靠窗口的形式运行所有存在的GUI工具。使用时,可以通过命令"**rqt**"来运行RQT工具和插件。这个GUI允许用户载入并运行任何插件。此外,用户还可以以独立窗口的形式运行插件。
- #### 14.1.2 组件的结构
RQT包含三个metapackages,分别是:
(1) rqt:核心的基础结构模块
(2) rqt_common_plugins:用于build的后端工具
(3) rqt_robot_plugins:用于与机器人交互的工具
- #### 14.1.3 框架的优点
相比于自己从零构建GUI,有如下优点:
(1) 具有标准化的公共的GUI例程(start-shutdown钩子,保持之前状态等);
(2) 多个widgets可以停靠在单一的窗口中;
(3) 可以很容易将已有的Qt widgets变为RQt插件;
(4) 可从ROS Answers得到支撑。
从系统构架的观点:
(1) 支撑跨平台和多编程语言(Python, C++);
(2) 可管理生命周期,RQT插件使用公共的API,使得其易维护和重用。
### 14.2 RQT的运行
:::{Note}
ROS安装成功后,自带RQT工具,无需重新安装。
:::
打开终端,输入命令"**rosrun rqt\_**",按下"**Tab**"键即可展开以下指令:
```bash
rosrun rqt_
```
rqt_image_view用来显示回传图像。
这里给大家介绍以下几个工具:
(1) rqt_console:日志输出工具箱
(2) rqt_graph:计算图可视化工具
(3) rqt_plot:计算图可视化工具
### 14.3 插件功能介绍
下面就简单列举一些十分有用的插件功能:
| **插件** | **功能描述** |
|:--:|:--:|
| topics monitor | 可以监视当前的某一话题的传输数据、占用带宽和话题频率等信息,相当于原来的rostopic echo msg_name。 |
| message publisher | 可以自定义名称发布一个话题,并指定话题发布的消息类型、发布数据以及发布频率。 |
| message type brower | 可以查看当前所有已定义的消息类型,包括自定义的msg,功能与rosmsg show msg_name 基本相同。 |
| robot steering | 可以发布/cmd_vel类型的消息,发布Twist话题消息,可以可视化地修改速度,转角变量,用于测试一些控制指令十分方便。 |
| bag | 可以用于录制一个bag文件包,可以任意选择录制的话题。也可以打开一个bag文件包,里面可以很方便地控制bag包play的播放或暂停,同时可以指定播放前一帧或下一帧。 |
bag插件如下表所示:
| **插件** | **功能描述** |
|:--:|:--:|
| node_graph | 查看当前节点运行的所有节点。 |
| process monitor | 查看当前的所有节点,以及节点的PID、占用CPU和占用内存。 |
| launch | 可以方便地在可视化界面下选择package和launch文件, 以及运行或停止launch一个节点。 |
| image view | 可以很方便地查看ROS话题中传递的图片消息,这点便于我们观察机器人当前看到的图像。 |
| plot | 可以将某一话题的数据(全部数据或部分数据)进行绘图显示,这样可以更加直观地看到话题消息的变化,便于调试。 |
| tf tree | 可以显示当前的tf树的结构。 |
| rviz | rqt里集成了rviz工具,可以很方便地从这里打开rviz工具。 |