摘要:这篇文章主要介绍ROS常用工具、ROSPY和ROSCPP常用模块,完全看完三篇文章,可以说ROS就基本入门,可以自己动手做实验了。
ROS常用工具
ROS工具的 功能大概有以下几个方向:仿真、调试、可视化。这里主要介绍常用工具作用,如何添加模块,设置参数B站都有视频,这里不会有过多解读。
gazebo是一种最常用的机器人仿真工具,模拟器,也是目前独立的开源机器人仿真平台。gazebo可以进行机器人的动力学仿真,可以模仿机器人常用的传感器(比如激光雷达、摄像头、IMU等),也可以加载自定义的环境和场景。
RViz是可视化工具,是将接收到的信息呈现出来;rviz和gazebo非常相似,但是gazebo实现的是仿真,提供一个虚拟世界,RVIZ实现的是可视化,呈现接收到的信息。
rqt主要作用和RVIZ一致都是可视化,有了它我们可以直观的看到消息的通信架构和流通路径;
常用命令:
rqt_graph :显示通信架构
rqt_plot :绘制曲线
rqt_console :查看日志
rosbag是一套用于记录和回放ROS主题的工具,此外还提供代码API,对包进行操作编写。
常用命令:cheak 确定一个包是否可以在当前系统中进行,或者是否可以迁移。decompress 压缩一个或多个包文件。filter 解压一个或多个包文件。fix 在包文件中修复消息,以便在当前系统中播放。help 获取相关命令指示帮助信息info 总结一个或多个包文件的内容。play 以一种时间同步的方式回放一个或多个包文件的内容。record 用指定主题的内容记录一个包文件。reindex 重新索引一个或多个包文件。
rosbridge是一个用在ROS系统和其他系统之间的一个功能包,就像是它的名字一样,起到 一个”桥梁”的作用,使得ros系统和其他系统能够进行交互.Rosbridge为非ROS程序提供了 一个JSON API,有许多与Rosbridge进行交互的前端,包括一个用于Web浏览器交互的 WebSocket服务器。Rosbridge_suite是一个包含Rosbridge的元程序包,用于Rosbridge 的各种前端程序包(如WebSocket程序包)和帮助程序包。
moveit它融合了研究者在运动规划、操纵、3D感知、运动学、控制和导航方面的最新进展,为操作 者提供了一个易于使用的平台,使用它可以开发先进的机器人应用,也被广泛应用于工业, 商业,研发和其他领域。move结构图如下:
roscpp代码演示
ROS为我们机器人开发者提供了不同语言的 接口,比如roscpp是C++语言ROS接口(目前最广泛应用的ROS客户端库,执行效率高),rospy是python语言的ROS接口(开发效率高,通常用在对运行时间没有太大要求的场合,例如配置、初始化等操作),rosjava是java语言的ROS接口(测试版本) 我们直接调用它所 提供的函数就可以实现topic、service等通信功能。
roscpp位于 /opt/ros/kinetic 之下,用C++实现了ROS通信。在ROS中,C++的代码是通过 catkin这个编译系统(扩展的CMake)来进行编译构建的。每一个node的节点功能可能不一样,但是都包含初始化、销毁、句柄等操作。
- ROS代码逻辑整体
常见的ros代码逻辑包含下面的执行步骤:
1.调用ros::init()函数初始化节点的名称和其他信息
2.创建ros::NodeHandle对象,也就是节点句柄,用于创建Pub、Sub(NodeHandle就是节点资源的描述,需要借助“把手”才能操作资源)
3调用ros::shutdown()手动关闭节点(一般是系统自动帮我们完成)。
1 | #include<ros/ros.h> |
roscpp的主要部分包括:ros::init() : 解析传入的ROS参数,创建node第一步需要用到的函数**ros::NodeHandle : 和topic、service、param等交互的公共接口**ros::master : 包含从master查询信息的函数ros::this_node:包含查询这个进程(node)的函数ros::service:包含查询服务的函数**ros::param:包含查询参数服务器的函数,而不需要用到NodeHandle**ros::names:包含处理ROS图资源名称的函数
具体可见:http://docs.ros.org/api/roscpp/html/index.html
以上功能可以分为以下几类:Initialization and Shutdown 初始与关闭Topics 话题Services 服务Parameter Server 参数服务器Timers 定时器NodeHandles 节点句柄Callbacks and Spinning 回调和自旋(或者翻译叫轮询?)Logging 日志Names and Node Information 名称管理Time 时钟Exception 异常
回调函数与spin()方法
CallBack回调函数与ros::spin() 方法需要配合使用,当消息传来时,只指定回调函数,系统不会自动触发,必须要 ros::spin() 或 者 ros::spinOnce() 才能真正使回调函数生效。处理流程:回调函数一般作为参数传到另外一个函数(一般是函数指针),当消息message到达时,先会把消息放到一个队列中,当有spin函数执行时,就会处理消息队列队首的信息。spin具体的处理方法可以分成阻塞/非阻塞,单线程/多线程两种。
| spin方法 | 阻塞 | 线程 |
| —————————– | —— | —— |
| ros::spin() | 阻塞 | 单线程 |
| ros::spinOnce() | 非阻塞 | 单线程 |
| ros::MultiTreadedSpin() | 阻塞 | 多线程 |
| ros::AsyncMultiThreadedSpin() | 非阻塞 | 多线程 |ROS节点编写
基本流程,首先创建一个工作空间workplace,然后根据实际需要创建相应的包package,编写相应的需求文件,如源文件;根据编译运行需要,补充CMakeLists.txt、package.xml相应说明,如添加依赖,查找相关包,运行所需要的包,消息类型等等。
1
2
3
4mkdir -p xxx_ws //创建工作空间
catkin_make //编译工作空间
//打开.bashrc 设置xxx_ws工作空间的环境变量
catkin_create_pkg xxxx(包) xx(依赖) //创建包
\1. 编写一个talker的node
在工作空间的src/目录下,第1步,创建一个talker的包study:$ catkin_create_pkg study roscpp第2步,打开vcode(或者其他ide),study/src,创建源文件study_node.cpp,代码如下:
1 | #include"ros/ros.h" |
第3步,设置CMakeLists.txt&package.xmlCMakeLists.txt:
1 | find_package(catkin REQUIRED COMPONENTS |
package.xml:
1 | <build_depend>roscpp</build_depend> |
第4步,编译
1 | $ catkin_make #注意在要做工作空间的一级目录下使用该指令 |
第5步,验证,终端运行
1 | $ roscore & #后台运行一个ROS master |
这时,从零开始创建的talker节点node,成功创建完成
\2. 编写一个listener的node
在工作空间的src/目录下,第1步,创建一个listener的包study_listen:
1 | $ catkin_create_pkg study_listen roscpp |
第2步,study_listen/src,创建源文件study_listen_node.cpp
1 | #include"ros/ros.h" |
第3步,设置CMakeLists.txt&package.xmlCMakeLists.txt:
1 | find_package(catkin REQUIRED COMPONENTS |
package.xml:
1 | <build_depend>roscpp</build_depend> |
第4步,编译
1 | $ catkin_make #注意在要做工作空间的一级目录下使用该指令 |
第5步,验证
1 | $ roscore & #运行一个ROS master |
这时,从零开始创建的listener节点node,成功创建完成
\3. 自定义消息类型并发布演示
这里主要就是定义一个消息类型是重点,然后,在上面创建的talker以及listener包里面头文件包含,然后在CMakeLists.txt&package.xml两文件中,添加新的头文件类型即可使用新定义的消息类型了。
第一步,创建一个包:
1 | $ catkin_create_pkg study_msgs std_msgs roscpp |
第二步,在包创建一个msg文件夹(注意文件夹名称一定是这样子的,否则,在cmakelists要修改很多)
第三步,在文件夹中新建文件,StudyMsg.msg
(注意命名方式以及后缀)
1 | string detail |
注意,自定义的消息类型,记得一定不能写其他说明性内容进去,否则发生编译错误
第四步,设置CMakeLists.txt&package.xmlCMakeLists.txt:
1 | find_package(catkin REQUIRED COMPONENTS |
package.xml:
1 | <build_depend>message_generation</build_depend> |
第五步,编译,catkin_make
第六步,查看
1 | $ cd include/study_msgs |
这时候,自定义消息类型生成成功,并且,可以被其他包通过头文件#include”study_msgs/StudyMsg.h”方式,就可以正常使用。下面,以发布一个talker节点来展示,并且发布的topic名称为/study_topic_new当然,CMakeLists.txt&package.xml要做相应的补充,CMakeLists.txt:
1 | find_package(catkin REQUIRED COMPONENTS |
package.xml:
1 | <build_depend>study_msgs</build_depend> |
此时,study_node.cpp为:
1 | #include"ros/ros.h" |
终端查看:
1 | $ rostopic echo /study_topic_new |
\4. 参数中心rosparam的使用演示
开始展示之前,一定要记得在study_listen包的CMakeLists.txt&package.xml做好跟上面的talker包study一样准备,保证可以使用自定义消息类型。
study_node.cpp:
1 | #include"ros/ros.h" |
study_listen_node.cpp:
1 | #include"ros/ros.h" |
修改了上面的两个文件,接下来就是编译整个工作空间并成功,接着在终端执行
1 | $ roscore & #启动ros master |
这时候我们发现,上面我们定义的回调函数,都成功调用了(表示上面的talker/listener/自定义消息 类型都是编写并运行正常的)当我们在终端2启动参数中心rosparam设置参数:
1 | $ rosparam set /myparam "yqy" |
终端1的显示调整为:
1 | [ INFO] [1606048163.371016634]: I can see you again,hello study world!368 |
也就是将周期第三个,cc调整为yqy了。
本章小结:创建一个包,需要定义好CmakeLists.txt 、package.xml两个文件,主要就是告诉系统,我这个包编译和运行时依赖是什么;talker和listener的编写也是基本套路一样的,重新发布的主题以及消息类型以及内容就发布ok了;listener的回调函数,注意是无返回类型的;重新自定义一个消息类型,注意文件夹命名以及文件后缀名称。基本是这些。