(一)ROS简介
1.ROS是什么
ROS 是一个适用于机器人的开源的元操作系统。它提供了操作系统应有的服务,包括硬件抽象,底层设备控制,常用函数的实现,进程间消息传递,以及包管理。它也提供用于获取、编译、编写、和跨计算机运行代码所需的工具和库函数。即ROS是一种机器人框架,它使得我们操作机器人像操作电脑系统一样。
ROS 运行时的“蓝图”是一种基于ROS通信基础结构的松耦合点对点进程网络。ROS并不是一个实时的框架,但ROS可以嵌入实时程序。ROS实现了几种不同的通信方式:
- 包括基于同步RPC样式通信的服务(services)机制
- 基于异步流媒体数据的话题(topics)机制
- 用于数据存储的参数服务器(Parameter Server)。
2.ROS的主要特点
ROS 的主要目的是支持分享和协作,主要目标是为机器人研究和开发提供代码复用的支持。ROS是一个分布式的进程(也就是节点)框架,这些进程被封装在易于被分享和发布的程序包和功能包集中。ROS也支持一种类似于代码储存库的联合系统,这个系统也可以实现工程的协作及发布。这个设计可以使一个工程的开发和实现从文件系统到用户接口完全独立决策(不受ROS限制)。同时,所有的工程都可以被ROS的基础工具整合在一起。ROS框架几个特点:
- 小型化:ROS尽可能设计的很小 -- 我们不封装您的 main() 函数 -- 所以为ROS编写的代码可以轻松的在其它机器人软件平台上使用。 由此得出的必然结论是ROS可以轻松集成在其它机器人软件平台:ROS已经可以与OpenRAVE,Orocos和Player集成。
- ROS不敏感库:ROS的首选开发模型都是用不依赖ROS的干净的库函数编写而成。
-
语言独立:ROS框架可以简单地使用任何的现代编程语言实现。我们已经实现了Python版本,C++版本和 Lisp版本。同时,我们也拥有Java 和 Lua版本的实验库。
-
方便测试:ROS内建一个了叫做rostest的单元/集成测试框架,可以轻松安装或卸载测试模块。
- 可扩展:ROS可以适用于大型运行时系统和大型开发进程。
(二)ROS的基本概念
1.Master(主机)
节点管理器,管理众多节点的运行,相当于管理中心。node在master下注册,node之间的通信也是由master牵线。ROS在运行时首先启动master,由此依次启动node。
2.Node(节点)
可执行程序以节点(进程)的形式依次运行,是一个执行单元。
3.启动Master和Node
- roscore:此时ROS master启动,同时启动的还有rosout和parameter server,其中rosout是负责日志输出的一个节点,其作用是告知用户当前系统的状态,包括输出系统的error、warning等等,并且将log记录于日志文件中,parameter server即是参数服务器,它并不是一个node,而是存储参数配置的一个服务器。每一次我们运行ROS的节点前,都需要把master启动起来,这样才能够让节点启动和注册。
- rosrun pkg_name node_name:一个package中存放着可执行文件,可执行文件是静态的,当系统执行这些可执行文件,将这些文件加载到内存中,它就成为了动态的node。
- 节点太多,我们会选择用launch文件来启动。
- rosnode info node_name(rosnode kill node_name):rosnode用来显示节点信息或结束节点等。
4.Launch(启动文件)
ROS为我们提供了一个命令能一次性启动master和多个node。该命令是:
$ roslaunch pkg_name file_name.launch
roslaunch命令首先会自动进行检测系统的roscore有没有运行,也即是确认节点管理器是否在运行状态中,如果master没有启动,那么roslaunch就会首先启动master,然后再按照launch的规则执行。launch文件里已经配置好了启动的规则。 所以roslaunch就像是一个启动工具,能够一次性把多个节点按照我们预先的配置启动起来,减少我们在终端中一条条输入指令的麻烦。
launch文件写法:
<launch> <!--根标签-->
<node> <!--需要启动的node及其参数-->
<include> <!--包含其他launch-->
<machine> <!--指定运行的机器-->
<env-loader> <!--设置环境变量-->
<param> <!--定义参数到参数服务器-->
<rosparam> <!--启动yaml文件参数到参数服务器-->
<arg> <!--定义变量-->
<remap> <!--设定参数映射-->
<group> <!--设定命名空间-->
</launch> <!--根标签-->
5.Topic(话题)
ROS中的通信方式中,topic是常用的一种单向异步通信。对于实时性、周期性的消息,使用topic来传输是最佳的选择。topic是一种点对点的单向通信方式,这里的“点”指的是node,也就是说node之间可以通过topic方式来传递信息。初始化过程:首先,publisher节点和subscriber节点都要到节点管理器进行注册,然后publisher会发布topic,subscriber在master的指挥下会订阅该topic,从而建立起sub-pub之间的通信。注意整个过程是单向的。
异步通信概念:在node1每发布一次消息之后,就会继续执行下一个动作,至于消息是什么状态、被怎样处理,它不需要了解;而对于node2图像处理程序,它只管接收和处理/camera_rgb上的消息,至于是谁发来的,它不会关心。所以node1、node2两者都是各司其责,不存在协同工作,我们称这样的通信方式是异步的。
【注】
- Talker向ROS Master注册
- Listener向ROS Master注册
- ROS Master通过RPC向Listener发送Talker的地址信息
- Listener接收到地址信息,通过RPC向Talker发送连接请求
- Talker确认连接请求,通过RPC向Listener确认连接
- Listener与Talker建立网络连接
- Talker向Listener发布数据
总结:前五步的通信协议都是RPC,最后两步传输数据才用TCP。topic相关指令详查:rostopic -h
6.Message(消息)
- Message按照定义解释就是topic内容的数据类型,也称之为topic的格式标准。它不仅是指一条消息,更是指定topic的格式标准。
- .msg文件就是定义消息格式的类(或结构体),每一条具体消息相当于类的对象。
- rosmsg是消息显示命令。
7.Service(服务)
service是一种请求-查询式的同步通信方式。Service通信是双向的,它不仅可以发送消息,同时还会有反馈。所以service包括两部分,一部分是请求方(Clinet),另一部分是应答方/服务提供方(Server)。这时请求方(Client)就会发送一个request,要等待server处理,反馈回一个reply,这样通过类似“请求-应答”的机制完成整个服务通信。具体指令详查rosservice -h。
8.Srv(服务)
类似msg文件,srv文件是用来描述服务(service数据类型的,service通信的数据格式定义在*.srv中。它声明了一个服务,包括请求(request)和响应(reply)两部分,另外响应部分可以嵌套msg。故srv可以嵌套msg在其中,但它不能嵌套srv。其格式声明如下:具体指令详查:rossrv -h。
bool start_detect
---
my_pkg/HumanPose[] pose_data
【注】自定义了srv,还是msg,必须修改CMakeList.txt和package.xml文件依赖项。
9.Parameter server(参数服务器)
Parameter server是基于RPC的参数服务器,他是另一种ROS通信方式,与前两种通信方式不同,参数服务器也可以说是特殊的“通信方式”。特殊点在于参数服务器是节点存储参数的地方、用于配置参数,全局共享参数。参数服务器使用互联网传输,在节点管理器中运行,实现整个通信过程。并且它更加的静态,维护着一个数据字典,字典里存储着各种参数和配置:
- Talker向ROS Master设置变量参数
- Listener向ROS Master查询参数值
- ROS Master向Listener发送参数值
总结:通信协议都是RPC: 远程过程调用(Remote Procedure Call, RPC),可以简单的理解为在一个进程里调用另一个进程的函数。
参数服务器的维护方式非常的简单灵活,总的来讲有三种方式:
- 命令行维护,详查rosparam -h。
- launch文件内读写
- node源码
10.Action(动作)
(1)Action的工作原理是client-server模式,也是一个双向的通信模式。通信双方在ROS Action Protocol下通过消息进行数据的交流通信。client和server为用户提供一个简单的API来请求目标(在客户端)或通过函数调用和回调来执行目标(在服务器端),特点:
- 一种问答通信机制;
- 带有连续反馈;
- 可以在任务过程中止运行;
- 基于ROS的消息机制实现。
(2)通信双方在ROS Action Protocal下进行交流通信是通过接口来实现,如下图:
Action的接口
- goal:发布任务目标;
- cancel:请求取消任务;
- status:通知客户端当前的状态;
- feedback:周期反馈任务运行的监控数据;
- result:向客户端发送任务的执行结果,只发布一次。
(3) Action 规范:利用动作库进行请求响应,动作的内容格式应包含三个部分,目标、反馈、结果。
- 目标:机器人执行一个动作,应该有明确的移动目标信息,包括一些参数的设定,方向、角度、速度等等。从而使机器人完成动作任务。
- 反馈:在动作进行的过程中,应该有实时的状态信息反馈给服务器的实施者,告诉实施者动作完成的状态,可以使实施者作出准确的判断去修正命令。
- 结果:当运动完成时,动作服务器把本次运动的结果数据发送给客户端,使客户端得到本次动作的全部信息,例如可能包含机器人的运动时长,最终姿势等等。
【注】action的实现是.action文件,类似与.msg和.srv文件,添加完文件也必须修改CMakList.txt和package.xml文件。
(三)ROS项目的结构
1.项目环境搭建
- 创建工作空间:
$ mkdir -p ~/catkin_ws/src # 创建了第二层级的文件夹src,这是放ROS软件包的地方 $ cd ~/catkin_ws/src # 进入工作空间,catkin_make必须在工作空间这个路径上执行 $ catkin_init_workspace # 初始化src目录,生成的CMakeLists.txt为功能包编译配置
-
编译工作空间(必须在工作空间下编译):
$ cd ~/catkin_ws # 回到工作空间,catkin_make必须在工作空间下执行; $ catkin_make # 开始编译,调用系统自动完成编译和链接过程,构建生成目标文件
-
每次编译完刷新一下环境变量:
$ source devel/setup.bash # 刷新坏境
-
检查环境变量:
$ echo $ROS_PACKAGE_PATH # 出现 /home/<youruser>/catkin_ws/src:/opt/ros/kinetic/share
2.catkin结构
- src/: ROS的catkin软件包(源代码包)
- build/: catkin(CMake)的缓存信息和中间文件
- devel/: 生成的目标文件(包括头文件,动态链接库,静态链接库,可执行文件等)、环境变量
后两个路径由catkin系统自动生成、管理,我们日常的开发一般不会去涉及,而主要用到的是src文件夹,我们写的ROS程序、网上下载的ROS源代码包都存放在这里。src中的源代码包package是catkin工作空间的基本单元。在编译时,catkin编译系统会递归的查找和编译src/下的每一个源代码包。因此也可以把几个源代码包放到同一个文件夹下。
3.Package软件包
(1)package特点:
- ROS程序只有组成package才能编译;
- package是ROS源代码存放的地方;
- ROS的代码无论是C++还是Python都要放到package中,这样才能正常的编译和运行;
- 一个package可以编译出来多个目标文件(ROS可执行程序、动态静态库、头文件等等)。
(2)package创建:
- 要在
catkin_ws/src
下,用到catkin_create_pkg
命令catkin_create_pkg package depends
-
新建一个package叫做
test_pkg
,依赖roscpp、rospy、std_msgs(常用依赖)。$ catkin_create_pkg test_pkg roscpp rospy std_msgs
【注】package中必不可少的两个文件是:CMakeList.txt与package.xml,在运用catkin_create_pkg创建package时,会自动创建这两个文件并进行填充(将依赖项填进两文件中)。
(3)package相关命令:
-
rospack:对package进行管理(rospack list、rospack depends、rosback find、rosback profile)
-
roscd:类似与cd命令,可以直接cd到ros的软件包
-
rosls:类似于ls命令
-
rosdep:管理package依赖项(rosdep check、rosdep install、rosdep update、rosdep db、rosdep init),常用命令:
rosdep install --from-paths src --ignore-src --rosdistro=kinetic -y #用于安装工作空间中`src`路径下所有package的依赖项(由pacakge.xml文件指定)
4.catkin中CMakeList的写法特点
CMakeLists.txt
的基本语法都还是按照CMake,而Catkin在其中加入了少量的宏,总体的结构如下:
cmake_minimum_required() #CMake的版本号
project() #项目名称
find_package() #找到编译需要的其他CMake/Catkin package
catkin_python_setup() #catkin新加宏,打开catkin的Python Module的支持
add_message_files() #catkin新加宏,添加自定义Message/Service/Action文件
add_service_files()
add_action_files()
generate_message() #catkin新加宏,生成不同语言版本的msg/srv/action接口
catkin_package() #catkin新加宏,生成当前package的cmake配置,供依赖本包的其他软件包调用
add_library() #生成库
add_executable() #生成可执行二进制文件
add_dependencies() #定义目标文件依赖于其他目标文件,确保其他目标已被构建
target_link_libraries() #链接
catkin_add_gtest() #catkin新加宏,生成测试
install() #安装至本机
5.package.mxl写法
pacakge.xml包含了package的名称、版本号、内容描述、维护人员、软件许可、编译构建工具、编译依赖、运行依赖等信息。
实际上rospack find、rosdep等命令之所以能快速定位和分析出package的依赖项信息,就是直接读取了每一个pacakge中的package.xml文件。它为用户提供了快速了解一个pacakge的渠道。
<pacakge> 根标记文件
<name> 包名
<version> 版本号
<description> 内容描述
<maintainer> 维护者
<license> 软件许可证
<buildtool_depend> 编译构建工具,通常为catkin
<depend> 指定依赖项为编译、导出、运行需要的依赖,最常用
<build_depend> 编译依赖项
<build_export_depend> 导出依赖项
<exec_depend> 运行依赖项
<test_depend> 测试用例依赖项
<doc_depend> 文档依赖项