ROS Noetic入门完整版
一、ROS基础概述
1、操作系统安装
ROS目前只能在基于Unix的平台上运行,因此我们使用Ubuntu来作为ROS的系统。这里我们安装了Ubuntu20.04
和ROS Noetic Ninjemys
。本机和虚拟机安装详见以下文章,选其中一种即可
笔记本安装 Windows10 和 Ubuntu20.04 双系统
2、ROS Noetic安装
官网ROS Noetic安装教程参考:https://wiki.ros.org/cn/noetic/Installation/Ubuntu
1、配置系统软件源
打开“软件更新”,进入到“Ubuntu软件“页面,允许universe、restricted、multiverse三项,源换成国内源即可。
2、添加ROS软件源
1 | sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list' |
3、设置密钥
1 | sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654 |
4、安装ROS
1 | #更新apt索引包 |
5、设置环境
1 | echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc |
注意: 在 ROS 版本 noetic 中无需构建软件包的依赖关系,没有rosdep
的相关安装与配置,其他版本需要安装。
6、小海龟测试
终端输入roscore
可以查看安装好的ros的发行版名称为noetic和版本号;ctrl+Alt+t
再次打开一个新的终端,输入rosrun turtlesim turtlesim_node
,即会出现小海龟的仿真界面;再次打开新终端,输入rosrun turtlesim turtle_teleop_key
,即可控制小海龟移动了。
7、ROS的卸载
1 | sudo apt remove ros-noetic-* |
8、安装构建依赖
1 | #安装构建依赖相关工具 |
3、常用工具安装
1、Terminator
1 | sudo apt install terminator |
1 | Alt+Up //移动到上面的终端 |
2、VScode
下载地址:https://code.visualstudio.com/docs?start=true,下载deb,双击进行安装。
1 | #第二种方式安装 |
VScode插件安装
1 | C/C++ |
vscode 中编译 ros
快捷键 ctrl + shift + B
调用编译,选择:catkin_make:build
可以点击配置设置为默认,修改.vscode/tasks.json 文件,此后ctrl + shift + B
可直接编译
1 | { |
添加功能包,选定 src 右击 —> create catkin package
PS1: 如果没有代码提示
如果VS没有智能提示,修改 .vscode/c_cpp_properties.json
设置 "cppStandard": "c++17"
PS2: main 函数的参数不可以被 const 修饰
PS3: 当ROS__INFO 终端输出有中文时,会出现乱码
1 | #添加任意一句即可 |
PS4:运行python文件可能会找不到文件或目录
因为ubuntu20.04默认使用python3,有三种解决方法
解决1: #!/usr/bin/env python3
直接使用 python3 (不推荐)
解决2: 创建一个链接符号到 python 命令:sudo ln -s /usr/bin/python3 /usr/bin/python
解决3:像C++一样进行链接编译,让程序自动寻找合适解释器
二、核心概念
1、ROS介绍
ROS (Robot Operating System, 机器人操作系统) 提供一系列程序库和工具以帮助软件开发者创建机器人应用软件。它提供了硬件抽象、设备驱动、函数库、可视化工具、消息传递和软件包管理等诸多功能。
ROS中文官网:https://wiki.ros.org/cn
2、ROS核心概念
节点与节点管理器
-
节点(Node)—— 执行单元
执行具体任务的进程、独立运行的可执行文件;不同节点可使用不同的编程语言,可分布式运行在不同的主机;节点在系统中的名称必须是唯一的。 -
节点管理器 (ROS Master)—— 控制中心
为节点提供命名和注册服务;跟踪和记录话题/服务通信,辅助节点相互查找、 建立连接;提供参数服务器,节点使用此服务器存储和检索 运行时的参数。
话题通信
-
话题(Topic)—— 异步通信机制
节点间用来传输数据的重要总线;使用发布(Publisher)/订阅(Subscriber)模型,数据由发布者传输到订阅者,同一个话题的订阅者或发布者可以不唯一。 -
消息(Message)——话题数据
话题的具体数据称为消息(Message),使用.msg文件定义;消息用来描述话题当中具体的数据类型,在ROS中,有些消息已经被预定义了,比如雷达、图像等,也可以自定义消息。
服务通信
- 服务(Service)—— 同步通信机制
使用客户端(Service)/服务器(Client)模型,客户端发送请求数据,服务器完成 处理后返回应答数据。使用.src文件定义。
话题与服务区别
话题 | 服务 | |
---|---|---|
同步性 | 异步 | 同步 |
通信模型 | 发布/订阅 | 服务器/客户端 |
底层协议 | ROSTCP/ROSUDP | ROSTCP/ROSUDP |
反馈机制 | 无 | 有 |
缓冲区 | 有 | 无 |
实时性 | 弱 | 强 |
节点关系 | 多对多 | 一对多(一个server) |
适用场景 | 数据传输,连续高频的数据发布与接收:雷达、里程计 | 逻辑处理,偶尔调用或执行某一项特定功能:拍照、语音识别 |
通信数据 | msg | srv |
参数
- 参数(Parameter)—— 全局共享字典
可通过网络访问的共享、多变量字典;节点使用此服务器来存储和检索运行时的参数;适合存储静态、非二进制的配置参数,不适合存储动态配置的数据。
文件系统
-
功能包(Package): ROS软件中的基本单元,包含节点源码、配置文件、数据定义等。
-
功能包清单(Package manifest):记录功能包的基本信息,包含作者信息、许可信息、依赖选项、编译标志等。
-
元功能包(Meta Packages):组织多个用于同一目的功能包。
3、ROS常用命令行工具
1 | #分别在四个终端打开运行 |
rosnode节点命令
1 | #查看活动节点 |
rostopic话题命令
1 | #打印pub发布的数据 |
rosmsg消息命令
1 | #查看消息 |
rosservice服务命令
1 | #打印可用服务 |
rosbag命令
1 | #保存所有步骤,-O代表保存的压缩包路径 |
rossrv
1 | #rossrv是用于显示有关ROS服务类型的信息的命令行工具,与 rosmsg 使用语法高度雷同。 |
rosparam
1 | #rosparam包含rosparam命令行工具,用于使用YAML编码文件在参数服务器上获取和设置ROS参数。 |
1 | #增 |
三、编程基础
步骤
- 先创建一个工作空间;
- 创建一个功能包;
- 编辑源文件;
- 编辑配置文件;
- 编译并执行。
1、工作空间创建
工作空间(workspace)是一个存放工程开发相关文件的文件夹。
- src:代码空间(Source Space)
- build:编译空间(Build Space)
- devel:开发空间(Development Space)
- install:安装空间(Install Space)
1、创建工作空间catkin_ws
1 | #创建目录 |
**2、编译工作空间 **
1 | #需要在整个工作目录下编译 |
3、设置环境变量
1 | echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc |
4、创建功能包
1 | #std_msgs:包含常见消息类型,标准消息库 |
package.xml
是功能包的描述文件,CMakeLists.txt
定义编译规则,编译出的文件在devel
目录下的include文件夹(头文件)和lib文件夹(可执行文件)
5、编译功能包
1 | cd ~/catkin_ws |
2、Topic话题通信
下载功能包
1 | #下面的服务功能都需要依赖以下功能包 |
1、发布者publisher编程实现
指发布程序代码给海龟仿真器,控制海龟运动
1、编写发布者代码
发布者流程
- 初始化ROS节点;
- 向ROS Master注册节点信息,包括发布的话题名和话题中的消息类型;
- 创建消息数据;
- 按照一定频率循环发布消息。
以下两种语言二选一即可
1 | /** |
python文件需要确保文件拥有可执行权限,这里我把python文件都放在了scripts文件夹下,在此打开终端,运行chmod +x *.py
1 | #!/usr/bin/env python3 |
2、定义编译规则
仅C++代码需要定义编译规则,python代码可直接运行
1 | #打开功能包的CMakeLists.txt文件,在build下添加以下规则 |
3、编译
仅C++代码需要编译,python代码可直接运行
1 | #要在工作空间下编译 |
4、运行
运行成功后海龟按照发布者的程序进行运动
1 | #首先刷新一下环境变量,放入本地环境变量了也可以不刷新 |
2、订阅者subscriber编程实现
流程步骤与发布者相似,订阅者可以监听海龟的位置信息变化并打印在屏幕
订阅者流程
- 初始化ROS节点;
- 订阅需要的话题;
- 循环等待话题消息,接收到消息后进入回调函数;
- 在回调函数中完成消息处理。
C++订阅代码
1 | /** |
python订阅代码
1 | #!/usr/bin/env python3 |
3、自定义话题通信
在 ROS 通信协议中,数据载体是一个较为重要组成部分,ROS 中通过 std_msgs 封装了一些原生的数据类型,比如:String、Int32、Int64、Char、Bool、Empty… 但是,这些数据一般只包含一个 data 字段,结构的单一意味着功能上的局限性,当传输一些复杂的数据,就会显得力不从心,这时候就需要自定义消息。
ROS Master作为节点管理者,负责节点之间的通信连接,一旦发布者和消息者之间连通后,master关机后两者仍可通信,但无法更改对象
在learning_topic
文件夹下创建msg
文件夹,在里面创建Person.msg
文件(注意一定要叫msg
文件夹,在CMakeLists.txt
规则有写),定义话题消息
1 | string name |
在功能包的package.xml
文件下添加依赖
1 | <build_depend>message_generation</build_depend> |
在CMakeLists.txt
文件下添加编译规则,C++和python都需要。找到对应的配置文件下添加编译选项
1 | find_package(catkin REQUIRED COMPONENTS |
最后编译生成相关依赖
1 | cd ~/catkin_ws |
C++ 需要调用的中间文件(…/工作空间/devel/include/包名/xxx.h)
Python 需要调用的中间文件(…/工作空间/devel/lib/python3/dist-packages/包名/msg)
1、C++文件
C++文件放置在功能包learning_topic下的src文件夹
为了方便代码提示,可在vscode中的c_cpp_properties.json
下的includePath
中添加编译好的头文件目录,若存在就无须配置,我的是"/home/shawn/catkin_ws/src/learning_parameter/include/**",
发布者
1 | /** |
订阅者
1 | /** |
在CMakeLists.txt
文件下的build下添加编译规则
1 | add_executable(person_publisher src/person_publisher.cpp) |
编译与运行
1 | cd ~/catkin_ws |
2、python文件
py文件都放置在功能包learning_topic下的scripts文件夹
为了方便代码提示,可在vscode中的settings.json
下的python.autoComplete.extraPaths
中添加编译好的头文件目录,若存在就无须配置,我的是"/home/shawn/catkin_ws/devel/lib/python3/dist-packages"
发布者
1 | #!/usr/bin/env python3 |
订阅者
1 | #!/usr/bin/env python3 |
运行
1 | #获得可执行权限 |
3、Service服务通信
下载功能包
1 | cd ~/catkin_ws/src |
1、客户端Client编程实现
C++代码
1 | /** |
在CMakeLists.txt
增加编译规则
1 | add_executable(turtle_spawn src/turtle_spawn.cpp) |
运行
1 | cd ~/catkin_ws |
python代码
1 | #!/usr/bin/env python3 |
运行
1 | cd ~/catkin_ws |
2、服务端Service编程实现
C++代码
1 | /** |
python代码
1 | #!/usr/bin/env python3 |
其他操作和客户端相似,海龟启动后通过rosservice call /turtle_command
命令改变海龟运动状态
3、自定义数据服务
自定义请求和应答内容,通过请求进行控制
在learning_service
文件夹下创建srv
文件夹,在里面创建Person.srv
文件(注意一定要叫srv文件夹,在CMakeLists.txt
规则有写),定义数据。三杠上方代表Request参数,下方代表Response参数
1 | string name |
在功能包的package.xml
文件下添加依赖
1 | <build_depend>message_generation</build_depend> |
在CMakeLists.txt
文件下添加编译规则,C++和python都需要。找到对应的配置文件下添加编译选项
1 | find_package(catkin REQUIRED COMPONENTS |
最后编译生成相关依赖
1 | cd ~/catkin_ws |
1、C++文件
服务器
1 | /** |
客户端
1 | /** |
在CMakeLists.txt
文件下的build下添加编译规则
1 | add_executable(person_server src/person_server.cpp) |
编译运行
1 | cd ~/catkin_ws |
2、python文件
服务器
1 | #!/usr/bin/env python3 |
客户端
1 | #!/usr/bin/env python3 |
运行
1 | #获得可执行权限 |
4、全局参数使用与编程
参数服务器以共享的方式实现不同节点之间数据交互的通信模式,存储一些多节点共享的数据,类似于全局变量。
下载功能包
1 | cd ~/catkin_ws/src |
1、C++文件
和前面一样,需要添加编译规则
1 | /** |
添加编译规则
1 | add_executable(parameter_config src/parameter_config.cpp) |
运行
1 | cd ~/catkin_ws |
2、python文件
1 | #!/usr/bin/env python3 |
运行
1 | cd ~/catkin_ws |
5、launch启动文件
传统启动节点的方法:每启动一个节点都要打开一个新的终端运行一个新的命令,当系统中的节点数量许多时,显然是很不方便的,而且命令的输入也可能会发生错误。
launch启动文件的引入:可以同时启动多个节点,并且可以自动启动ROS Master节点管理器以及实现每个节点的各种配置,为多个节点的操作提供很大的便利。
1、基本介绍
< launch >
launch文件中的根元素采用< launch >标签定义,里面包含所有节点的启动配置内容
1 | #该属性告知用户当前 launch 文件已经弃用 |
< node >
启动节点
1 | <node pkg="turtlesim" name="sim1" type="turtlesim_node"/> |
- pkg:节点所在的功能包名称
- type:节点的可执行文件名称
- name:节点运行时的名称
- output:“log | screen” (可选)日志发送目标,可以设置为 log 日志文件,或 screen 屏幕,默认是 log
- respawn, required, ns, args
< param > / < rosparam > 参数
设置ROS系统运行中的参数,存储在参数服务器中。其中不同层次的参数是不一样的,在
1 | <param name="output_frame" value="odom"/> |
- name:参数名
- value:参数值
加载参数文件中的多个参数:
1 | #command="load | dump | delete" (可选,默认 load) |
< arg > 参数
launch文件内部的局部变量,仅限于launch文件使用
1 | <arg name="arg-name" default="arg-value" /> |
- name:参数名
- value:参数值
==param设置的参数是存储在ROS参数服务器中的,而arg设置的参数仅限于launch文件中==
< remap > 重映射
重映射ROS计算图资源的命名。
1 | <remap from="/turtlebot/cmd_vel" to="/cmd_vel"/> |
- from:原命名
- to:映射之后的命名
< include > 嵌套
包含其他launch文件,类似C语言中的头文件包含。
1 | <include file="$(dirname)/other.launch" /> |
- file:包含的其他launch文件路径
< group > 组
- 标签可以对节点分组,具有 ns 属性,可以让节点归属某个命名空间
< arg > 参数
- 标签是用于动态传参,类似于函数的参数,可以增强launch文件的灵活性
1 | <launch> |
2、launch简单示例
首先创建功能包,在里面创建launch文件夹,一般launch都放在里面(可自定义文件夹名)
1 | cd ~/catkin_ws/src |
简单订阅者发布者
名为simple.launch
1 | <launch> |
1 | #需要编译才能识别 |
config的launch文件
在config/param.yml
文件下
1 | A: 123 |
turtlesim_parameter_config.launch
文件
1 | <launch> |
运行,可以看见节点参数的不同,不同位置显示的参数位置也不同
1 | #回到工作空间目录运行 |
remap使用
1 | <launch> |
四、通信机制进阶
API文档: http://wiki.ros.org/APIs
1、常用API
1、初始化
C++
1 | /* |
python
1 | """ |
2、话题和服务
1 | /** |
3、回旋函数
spin()和spinOnce()异同
**相同点:**二者都用于处理回调函数;
**不同点:**ros::spin() 是进入了循环执行回调函数,而 ros::spinOnce() 只会执行一次回调函数(没有循环),在 ros::spin() 后的语句不会执行到,而 ros::spinOnce() 后的语句可以执行。
4、时间
C++
1 | //时刻 |
python
1 | # 获取当前时刻 |
5、其他函数
在发布实现时,一般会循环发布消息,循环的判断条件一般由节点状态来控制,C++中可以通过 ros::ok()
来判断节点状态是否正常,而 python 中则通过 rospy.is_shutdown()
来实现判断,导致节点退出的原因主要有如下几种:
- 节点接收到了关闭信息,比如常用的
ctrl + c
快捷键就是关闭节点的信号; - 同名节点启动,导致现有节点退出;
- 程序中的其他部分调用了节点关闭相关的API(C++中是
ros::shutdown()
,python中是rospy.signal_shutdown()
)
1 | //C++ |
2、自定义头文件和源文件
1、自定义头文件
在功能包下的 include/功能包名
目录下新建头文件: hello.h
1 |
|
在 VScode 中,为了后续包含头文件时不抛出异常,配置 .vscode 下 c_cpp_properties.json
的 includepath
属性
1 | "/home/用户/工作空间/src/功能包/include/**" |
在 src 目录下新建文件hello.cpp
1 |
|
最后进行文件的配置和运行
1 | #取消include注释 |
2、自定义源文件
头文件设置和上一节相似,命名为hello1.h
,配置好VS。
在 src 目录下新建文件hello1.cpp
,示例内容如下:
1 |
|
在 src 目录下新建文件 use_head.cpp
,示例内容如下:
1 |
|
头文件与源文件相关配置:
1 | include_directories( |
可执行文件配置:
1 | add_executable(use_head src/use_head.cpp) |
3、python模块导入
在同一目录下导入另外的py文件,可能会报错:模块未找到。因为rosrun的工作目录时在当前工作空间中
1 | import os |
五、ROS运行管理
1、元功能包
MetaPackage是Linux的一个文件管理系统的概念。是ROS中的一个虚包,里面没有实质性的内容,但是它依赖了其他的软件包,通过这种方法可以把其他包组合起来,我们可以认为它是一本书的目录索引,告诉我们这个包集合中有哪些子包,并且该去哪里下载。
1、新建一个功能包
**2、修改package.xml **
1 | <exec_depend>被集成的功能包</exec_depend> |
3、修改 CMakeLists.txt
1 | cmake_minimum_required(VERSION 3.0.2) |
PS:CMakeLists.txt 中不可以有换行。
参考文档:http://wiki.ros.org/catkin/package.xml#Metapackages
2、ROS节点重命名
1 | #1、重定向命名空间和运行名字可分开 |
3、ROS话题名称
在 ROS 中节点终端,不同的节点之间通信都依赖于话题,话题名称也可能出现重复的情况,这种情况下,系统虽然不会抛出异常,但是可能导致订阅的消息非预期的,从而导致节点运行异常。这种情况下需要将两个节点的话题名称由相同修改为不同。
话题种类
- 全局(参数名称直接参考ROS系统,与节点命名空间平级)
- 相对(参数名称参考的是节点的命名空间,与节点名称平级)
- 私有(参数名称参考节点名称,是节点名称的子级)
在ROS中提供了一个比较好用的键盘控制功能包: ros-noetic-teleop-twist-keyboard
,该功能包,可以控制机器人的运动,作用类似于乌龟的键盘控制节点。如果没有,则sudo apt install ros-noetic-teleop-twist-keyboard
进行安装,然后执行: rosrun teleop_twist_keyboard teleop_twist_keyboard.py
1 | #1、通过rosrun重命名 |
4、ROS参数名设置
关于参数重名的处理,没有重映射实现,为了尽量的避免参数重名,都是使用为参数名添加前缀的方式,实现类似于话题名称,有全局、相对、和私有三种类型之分。
1 | #命令行设置 |
5、ROS分布式
ROS是一个分布式计算环境。一个运行中的ROS系统可以包含分布在多台计算机上多个节点。根据系统的配置方式,任何节点可能随时需要与任何其他节点进行通信。
1.准备
先要保证不同计算机处于同一网络中,最好分别设置固定IP,如果为虚拟机,需要将网络适配器改为桥接模式;
2.配置文件修改
分别修改不同计算机的 /etc/hosts
文件,在该文件中加入对方的IP地址和计算机名:
1 | #主机端: |
设置完毕,可以通过 ping 命令测试网络通信是否正常。
1 | #IP地址查看 |
3.配置主机IP
配置主机的 IP 地址
~/.bashrc
追加
1 | export ROS_MASTER_URI=http://主机IP:11311 |
4.配置从机IP
配置从机的 IP 地址,从机可以有多台,每台都做如下设置:
~/.bashrc
追加
1 | export ROS_MASTER_URI=http://主机IP:11311 |
完毕后即可分布式通信
六、ROS常用组件
1、TF坐标变换
创建功能包
1 | cd ~/catkin_ws/src |
1、坐标msg消息
订阅发布模型中数据载体 msg 是一个重要实现,首先需要了解一下,在坐标转换实现中常用的 msg:
geometry_msgs/TransformStamped
和geometry_msgs/PointStamped
。前者用于传输坐标系相关位置信息,后者用于传输某个坐标系内坐标点的信息。在坐标变换中,频繁的需要使用到坐标系的相对关系以及坐标点信息。
2、静态坐标建立
使用命令行设置静态坐标变换(推荐)
rosrun tf2_ros static_transform_publisher x偏移量 y偏移量 z偏移量 z偏航角度 y俯仰角度 x翻滚角度 父级坐标系 子级坐标系
1、C++实现
发布方
1 |
|
订阅者
1 |
|
2、python实现
发布方
1 | #! /usr/bin/env python |
订阅者
1 | #! /usr/bin/env python |
3、动态坐标建立
1、C++
发布方
1 | // 1.包含头文件 |
订阅方
1 | //1.包含头文件 |
2、python
发布方
1 | #! /usr/bin/env python |
订阅方
1 | #! /usr/bin/env python |
最后启动即可监听到动态坐标
1 | #启动海龟节点 |
4、多坐标点变换
发布方
为了方便,使用静态坐标变换发布
1 | <launch> |
订阅方
c++实现
1 | //1.包含头文件 |
python实现
1 | #!/usr/bin/env python |
5、坐标位置查看
可视化
启动后输入rviz
,可进入可视化界面,按要求添加即可观察
命令行
1 | #没安装进行安装 |
6、海龟跟随实战
这里使用python编写,C++和python原理一样
服务客户端(生成新海龟)
1 | #! /usr/bin/env python |
发布方(发布两只乌龟坐标信息)
1 | #! /usr/bin/env python |
订阅方(解析坐标信息并生成速度信息)
1 | #! /usr/bin/env python |
运行(launch文件)
1 | <launch> |
2、rosbag
在ROS中关于数据的留存以及读取实现
命令行
1 | #录制文件 |
代码运行
1、C++实现
1.写 bag
1 |
|
2.读bag
1 |
|
2、python实现
1.写 bag
1 | #! /usr/bin/env python |
2.读bag
1 | #! /usr/bin/env python |
1、简单介绍与使用
1 | #这里因为ubuntu20没有python命令,所以我复制了/usr/bin中的python3变成python |
2、广播与监听编程实现
如何实现一个tf广播器
- 定义TF广播器(TransformBroadcaster)
- 创建坐标变换值;
- 发布坐标变换(sendTransform)
如何实现一个TF监听器
- 定义TF监听器;(TransformListener)
- 查找坐标变换;(waitFor Transform、lookupTransform)
1 | cd ~/catkin_ws/src |
这里有点问题
3、可视化工具
rqt
rqt
的启动方式有两种:
- 方式1:
rqt
- 方式2:
rosrun rqt_gui rqt_gui
rqt_graph:计算图可视化工具
rqt_console:输出日志信息
rqt_plot:数据绘图工具
rqt_image_view:图像渲染工具
rqt_bag:录制和重放 bag 文件
Rviz:三维可视化工具
GazeBo:三维物理仿真平台
七、机器人系统仿真
1、概述
通过计算机对实体机器人系统进行模拟的技术,在 ROS 中,仿真实现涉及的内容主要有三:对机器人建模(URDF)、创建仿真环境(Gazebo)以及感知环境(Rviz)等系统性实现。
URDF是 Unified Robot Description Format 的首字母缩写,直译为统一(标准化)机器人描述格式,可以以一种 XML 的方式描述机器人的部分结构,比如底盘、摄像头、激光雷达、机械臂以及不同关节的自由度…该文件可以被 C++ 内置的解释器转换成可视化的机器人模型,是 ROS 中实现机器人仿真的重要组件。
RViz 是 ROS Visualization Tool 的首字母缩写,直译为ROS的三维可视化工具。它的主要目的是以三维方式显示ROS消息,可以将 数据进行可视化表达。例如:可以显示机器人模型,可以无需编程就能表达激光测距仪(LRF)传感器中的传感 器到障碍物的距离,RealSense、Kinect或Xtion等三维距离传感器的点云数据(PCD, Point Cloud Data),从相机获取的图像值等。
Gazebo是一款3D动态模拟器,用于显示机器人模型并创建仿真环境,能够在复杂的室内和室外环境中准确有效地模拟机器人。与游戏引擎提供高保真度的视觉模拟类似,Gazebo提供高保真度的物理模拟,其提供一整套传感器模型,以及对用户和程序非常友好的交互方式。
2、URDF集成Rviz基本流程
实现流程:
- 准备:新建功能包,导入依赖
- 核心:编写 urdf 文件
- 核心:在 launch 文件集成 URDF 与 Rviz
- 在 Rviz 中显示机器人模型
1.创建功能包,导入依赖
创建一个新的功能包,名称自定义,导入依赖包:urdf
与xacro
在当前功能包下,再新建几个目录:
urdf
: 存储 urdf 文件的目录
meshes
:机器人模型渲染文件(暂不使用)
config
: 配置文件
launch
: 存储 launch 启动文件
2.编写 URDF 文件
新建一个子级文件夹:urdf
(可选),文件夹中添加一个demo01.urdf
文件,复制如下内容:
1 | <robot name="mycar"> |
3.在 launch 文件中集成 URDF 与 Rviz
在launch
目录下,新建一个 launch 文件,该 launch 文件需要启动 Rviz,并导入 urdf 文件,Rviz 启动后可以自动载入解析urdf
文件,并显示机器人模型
1 | <launch> |
4.在 Rviz 中显示机器人模型
5.优化 rviz 启动
重复启动launch
文件时,Rviz 之前的组件配置信息不会自动保存,需要重复执行步骤4的操作,为了方便使用,需要保存配置,在file->save config as
保存在之前的config文件夹中。最后在launch文件中添加即可。
1 | <launch> |
3、URDF语法学习
robot标签
- name: 指定机器人模型的名称
link标签
urdf 中的 link 标签用于描述机器人某个部件(也即刚体部分)的外观和物理属性。比如: 机器人底座、轮子、激光雷达、摄像头…每一个部件都对应一个 link, 在 link 标签内,可以设计该部件的形状、尺寸、颜色、惯性矩阵、碰撞参数等一系列属性
-
name:为连杆命名
- visual —> 描述外观(对应的数据是可视的)
- geometry 设置连杆的形状
- 标签1: box(盒状)
- 属性:size=长(x) 宽(y) 高(z)
- 标签2: cylinder(圆柱)
- 属性:radius=半径 length=高度
- 标签3: sphere(球体)
- 属性:radius=半径
- 标签4: mesh(为连杆添加皮肤)
- 属性: filename=资源路径(格式:package:////文件)
- 标签1: box(盒状)
- origin 设置偏移量与倾斜弧度
- 属性1: xyz=x偏移 y便宜 z偏移
- 属性2: rpy=x翻滚 y俯仰 z偏航 (单位是弧度)
- metrial 设置材料属性(颜色)
- 属性: name
- 标签: color
- 属性: rgba=红绿蓝权重值与透明度 (每个权重值以及透明度取值[0,1])
- geometry 设置连杆的形状
- collision —> 连杆的碰撞属性
- Inertial —> 连杆的惯性矩阵
- visual —> 描述外观(对应的数据是可视的)
1 | <!-- 举例,执行需要通过launch--> |
joint
urdf 中的 joint 标签用于描述机器人关节的运动学和动力学属性,还可以指定关节运动的安全极限,机器人的两个部件(分别称之为 parent link 与 child link)以"关节"的形式相连接,不同的关节有不同的运动形式: 旋转、滑动、固定、旋转速度、旋转角度限制…,比如:安装在底座上的轮子可以360度旋转,而摄像头则可能是完全固定在底座上。
- name —> 为关节命名
- type —> 关节运动形式
- continuous: 旋转关节,可以绕单轴无限旋转
- revolute: 旋转关节,类似于 continues,但是有旋转角度限制
- prismatic: 滑动关节,沿某一轴线移动的关节,有位置极限
- planer: 平面关节,允许在平面正交方向上平移或旋转
- floating: 浮动关节,允许进行平移、旋转运动
- fixed: 固定关节,不允许运动的特殊关节
子级标签
-
parent(必需的)
parent link的名字是一个强制的属性:
- link:父级连杆的名字,是这个link在机器人结构树中的名字。
-
child(必需的)
child link的名字是一个强制的属性:
- link:子级连杆的名字,是这个link在机器人结构树中的名字。
-
origin
- 属性: xyz=各轴线上的偏移量 rpy=各轴线上的偏移弧度。
-
axis
- 属性: xyz用于设置围绕哪个关节轴运动。
实例
创建demo03_joint.urdf
1 | <robot name="mycar"> |
创建demo03_joint.launch
1 | <launch> |
URDF工具
在 ROS 中,提供了一些工具来方便 URDF 文件的编写,比如在文件所在路径运行:
1 | #检查复杂的 urdf 文件是否存在语法问题 |
工具之前,首先需要安装,安装命令:sudo apt install liburdfdom-tools
4、URDF之xacro
Xacro 是 XML Macros 的缩写,Xacro 是一种 XML 宏语言,是可编程的 XML。通过封装固定的逻辑,将逻辑中需要的可变的数据以参数的方式暴露出去,从而提高代码复用率以及程序的安全性。
1、快速体验
在功能包下的urdf->xacro
目录下新建demo01_urdf.xacro
1 | <robot name="mycar" xmlns:xacro="http://wiki.ros.org/xacro"> |
最后命令行进入 xacro文件 所属目录,执行:rosrun xacro xacro xxx.xacro > xxx.urdf
, 会将 xacro 文件解析为 urdf 文件
2、xacro语法学习
属性与算数运算
用于封装 URDF 中的一些字段
1 | <!--属性定义--> |
宏
类似于函数实现,提高代码复用率,优化代码结构,提高安全性
1 | <!--宏定义--> |
文件包含
机器人由多部件组成,不同部件可能封装为单独的 xacro 文件,最后再将不同的文件集成,组合为完整机器人
1 | <robot name="xxx" xmlns:xacro="http://wiki.ros.org/xacro"> |
3、xacro模型实现
在xacro文件中
1 | <!-- |
launch文件,注意文件名修改
1 | <launch> |
5、Rviz控制机器人运动(arbotix)
实现流程:
- 安装 Arbotix
- 创建新功能包,准备机器人 urdf、xacro 文件
- 添加 Arbotix 配置文件
- 编写 launch 文件配置 Arbotix
- 启动 launch 文件并控制机器人模型运动
安装
1 | sudo apt install ros-noetic-arbotix |
添加 arbotix 所需配置文件
1 | # 该文件是控制器配置,一个机器人模型可能有多个控制器,比如: 底盘、机械臂、夹持器(机械手).... |
launch 示例代码
1 | <launch> |
启动launch后,命令行输入rostopic pub -r 10 /cmd_vel geometry_msgs/Twist '{linear: {x: 0.2, y: 0, z: 0}, angular: {x: 0, y: 0, z: 0.5}}'
机器人即可成功启动
6、URDF集成Gazebo
1、快速体验
1.创建功能包
创建新功能包,导入依赖包: urdf、xacro、gazebo_ros、gazebo_ros_control、gazebo_plugins
2.编写URDF文件
1 | <!-- |
注意, 当 URDF 需要与 Gazebo 集成时,和 Rviz 有明显区别:
1.必须使用 collision 标签,因为既然是仿真环境,那么必然涉及到碰撞检测,collision 提供碰撞检测的依据。
2.必须使用 inertial 标签,此标签标注了当前机器人某个刚体部分的惯性矩阵,用于一些力学相关的仿真计算。
3.颜色设置,也需要重新使用 gazebo 标签标注,因为之前的颜色设置为了方便调试包含透明度,仿真环境下没有此选项。
3.启动Gazebo并显示模型
launch 文件实现:
1 | <launch> |
2、gazebo相关设置
1.collision
如果机器人link是标准的几何体形状,和link的 visual 属性设置一致即可。
2.inertial
惯性矩阵的设置需要结合link的质量与外形参数动态生成,标准的球体、圆柱与立方体的惯性矩阵公式如下(已经封装为 xacro 实现):
球体惯性矩阵
1 | <!-- Macro for inertia matrix --> |
圆柱惯性矩阵
1 | <xacro:macro name="cylinder_inertial_matrix" params="m r h"> |
立方体惯性矩阵
1 | <xacro:macro name="Box_inertial_matrix" params="m l w h"> |
需要注意的是,原则上,除了 base_footprint 外,机器人的每个刚体部分都需要设置惯性矩阵,且惯性矩阵必须经计算得出,如果随意定义刚体部分的惯性矩阵,那么可能会导致机器人在 Gazebo 中出现抖动,移动等现象。
3.颜色设置
在 gazebo 中显示 link 的颜色,必须要使用指定的标签:
1 | <gazebo reference="link节点名称"> |
**PS:**material 标签中,设置的值区分大小写,颜色可以设置为 Red Blue Green Black …
3、仿真环境的搭建与使用
对于使用已搭建完的世界,在空世界中包含world文件即可
1 | <include file="$(find gazebo_ros)/launch/empty_world.launch"> |
对于环境的搭建(要占用大量电脑资源)
- 方式1: 直接添加内置组件创建仿真环境
- 方式2: 手动绘制仿真环境(更为灵活)
7、URDF、Rviz和Gazebo综合使用
关于URDF(Xacro)、Rviz 和 Gazebo 三者的关系。 URDF 用于创建机器人模型、Rviz 可以显示机器人感知到的环境信息,Gazebo 用于仿真,可以模拟外界环境,以及机器人的一些传感器
参考文档: http://gazebosim.org/tutorials?tut=ros_gzplugins
八、机器人导航
1、导航概述
全局地图、自身定位、路径规划、运动控制、环境感知
2、导航实现
1、准备工作
- 安装 gmapping 包(用于构建地图):
sudo apt install ros-noetic-gmapping
- 安装地图服务包(用于保存与读取地图):
sudo apt install ros-noetic-map-server
- 安装 navigation 包(用于定位以及路径规划):
sudo apt install ros-noetic-navigation
最后创建新功能包,导入依赖gmapping map_server amcl move_base
2、SLAM建图
官方文档
创建launch文件
1 | <launch> |
首先启动 Gazebo 仿真环境
再启动地图绘制的 launch 文件:
然后启动键盘键盘控制节点,用于控制机器人运动建图
1 | rosrun teleop_twist_keyboard teleop_twist_keyboard.py |
最后在 rviz 中添加组件,显示栅格地图
3、地图服务
依次启动仿真环境,键盘控制节点与SLAM节点,绘制地图后启动保存地图的launch文件,即可保存地图信息
1 | <launch> |
对于地图的获取,启动新的launch文件,即可发布map地图信息了,之后只需要在rviz订阅/map即可
1 | <launch> |
nav.yaml部分详解
1 | #1.声明地图图片资源的路径 |
4、定位
编写launch文件
1 | <launch> |
测试launch文件
1 | <launch> |
执行
1.先启动 Gazebo 仿真环境
2.启动键盘控制节点:
1 | rosrun teleop_twist_keyboard teleop_twist_keyboard.py |
3.启动上一步中集成地图服务、amcl 与 rviz 的 launch 文件;
4.在启动的 rviz 中,添加RobotModel、Map组件,分别显示机器人模型与地图,添加 posearray 插件,设置topic为particlecloud来显示 amcl 预估的当前机器人的位姿,箭头越是密集,说明当前机器人处于此位置的概率越高;
5、路径规划
创建nav05_path.launch
文件
1 | <launch> |
costmap_common_params.yaml
该文件是move_base 在全局路径规划与本地路径规划时调用的通用参数,包括:机器人的尺寸、距离障碍物的安全距离、传感器信息等。配置参考如下:
1 | #机器人几何参,如果机器人是圆形,设置 robot_radius,如果是其他形状设置 footprint |
global_costmap_params.yaml
该文件用于全局代价地图参数设置:
1 | global_costmap: |
local_costmap_params.yaml
该文件用于局部代价地图参数设置:
1 | local_costmap: |
base_local_planner_params
基本的局部规划器参数配置,这个配置文件设定了机器人的最大和最小速度限制值,也设定了加速度的阈值。
1 | TrajectoryPlannerROS: |
最后文件集成
运行仿真环境、运行launch文件
1 | <launch> |
6、导航与SLAM建图
1.编写launch文件
当前launch文件实现,无需调用map_server的相关节点,只需要启动SLAM节点与move_base节点,示例内容如下:
1 | <launch> |
2.测试
1.首先运行gazebo仿真环境;
2.然后执行launch文件;
3.在rviz中通过2D Nav Goal设置目标点,机器人开始自主移动并建图了;
4.最后可以使用 map_server 保存地图。
九、学习资料
ROS: https://www.ros.org
ROS Wiki: http://wiki.ros.org
ROSCon 2012~2019:https://roscon.ros.org
ROS Robots: https://robots.ros.org
Ubuntu Wiki: https://wiki.ubuntu.org.cn
古月居:http://www.guyuehome.com
古月居泡泡:https://www.guyuehome.com/Bubble
古月学院:https://class.guyuehome.com
如何学习ROS:
https://mp.weixin.qq.com/s/uYvGuiG-TlOalWUynR2Nzg
一起从零手写URDF模型:
https://class.guyuehome.com/detail/p5eleea4fe1e5c_lgm126Xn/6
如何从Solidworks导出URDF模型
https://class.guyuehome.com/detail/p5e32dce7906e0_6TqS7BwX/6
如何在Gazebo中实现移动机器人仿真:
https://class.guyuehome.com/detail/p_5eb2366befe4aE4rbNmXt/6
Movelt可视化配置及仿真指南
https://class.guyuehome.com/detail/p_5e71966b3fdfd_g4DpRGg9/6