![b1375b116f87e748c40eebead94e3433.png](https://img-blog.csdnimg.cn/img_convert/b1375b116f87e748c40eebead94e3433.png)
1. 工程结构⚙
Catkin workspace---管理和组织ROS工程和代码(以Catkin工具编译)Catkin 是ros定制的编译构建系统,是对CMake的扩展,是用来编译ros程序的
--- src: 源文件空间※※※
--- --- 1. package 是ros软件的基本组织形式,是用来编译的基本单元;可以包含多个可执 行节点;至少包括CMakeList.txt与package.xml两个以上文件
--- --- --- 1.1 CMakeList.txt: 规定了catkin编译的规则(比如源文件、依赖项、目标文件)
--- --- --- 1.2 package.xml: 用来定义package的属性(包名、版本号、包描述、编译时的依赖项、运行时的依赖项...), 符合.xml文件格式
--- --- --- 1.3 package下的代码文件(shell、python、cpp、.h)
--- --- --- --- 1.3.1 scripts文件夹 存放.sh和.py的脚本文件
--- --- --- --- 1.3.2 include文件夹 存放.h的头文件
--- --- --- --- 1.3.3 src文件夹 存放.cpp或者*.py中import的模块包
--- --- --- --- 1.3.4 自定义通信格式文件(包括msg下的*.msg消息、src下的*.srv服务、action下的*.action动作)
--- --- --- --- 1.3.5 launch以及配置文件(launch文件可以一次性运行多个可执行文件,格式x.launch; 配置文件格式: x.yaml
--- build: 编译空间
--- devel: 开发空间
常用指令:
# 建立工作空间
$mkdir -p ~/catkin_ws/src
$cd ~/catkin_ws
$catkin_make
# 编译
$cd ~/catkin_ws
$catkin_make
$source ~/catkin_ws/devel/setup.bash # 编译完成后要source刷新环境
# rospack
# 查找某个pkg的地址
$ rospack find package_name
# 列出本地所有的pkg
$ rospack list
# roscd
# 跳转到某个pkg路径下
$ roscd package_name
# rosls
# 列举出某个pkg下的文件信息
$ rosls package_name
# rosed
# 编辑pkg中的文件
$ rosed package_name file_name
# catkin_create_pkg
# 创建一个pkg
$ catkin_create_pkg <pkg_name> [deps]
# rosdep
# 安装某个pkg所需的依赖
$ rosdep install [pkg_name}
![334db577bd80df3647000a477aa284ea.png](https://img-blog.csdnimg.cn/img_convert/334db577bd80df3647000a477aa284ea.png)
2. ROS计算图(通信架构)
进程(节点)管理,进程(节点)之间通讯。
2.1 master --- 各个node启动时候需要向master进行注册,同时,各个node也可借由master相互进行通讯(管理node通讯) ; 2.2 node --- ros的进程,是package里可执行文件运行的实例(x.cpp/.py/.sh)
大白话说,一个node负责一个function,比如控制小车底盘运行是一个node, 图像处理是一个node... node是按照功能进行划分的
2.3 roslaunch --- 启动master和多个node(package→launch→x.launch)
.launch文件中,对启动规则进行配置,同时会对roscore(master)有没有启动进行检测,若master没有启动,则会优先对master进行启动.
ros官网百科里,对.launch文件有详细的格式定义
<launch> <!--根标签-->
<!-- local machine already has a definition by default.
This tag overrides the default definition with
specific ROS_ROOT and ROS_PACKAGE_PATH values -->
<!-- 指定运行的机器-->
<machine name="local_alt" address="localhost" default="true" ros-root="/u/user/ros/ros/" ros-package-path="/u/user/ros/ros-pkg" />
<!-- a basic listener node -->
<node name="listener-1" pkg="rospy_tutorials" type="listener" /> <!--需要启动的node及参数-->
<!-- pass args to the listener node -->
<node name="listener-2" pkg="rospy_tutorials" type="listener" args="-foo arg2" />
<!-- a respawn-able listener node -->
<node name="listener-3" pkg="rospy_tutorials" type="listener" respawn="true" />
<!-- start listener node in the 'wg1' namespace -->
<node ns="wg1" name="listener-wg1" pkg="rospy_tutorials" type="listener" respawn="true" />
<!-- start a group of nodes in the 'wg2' namespace -->
<group ns="wg2"> <!--设定命名空间-->
<!-- remap applies to all future statements in this scope. -->
<!--设定参数映射-->
<remap from="chatter" to="hello"/>
<node pkg="rospy_tutorials" type="listener" name="listener" args="--test" respawn="true" />
<node pkg="rospy_tutorials" type="talker" name="talker">
<!-- set a private parameter for the node -->
<!--设定参数传入参数服务器-->
<param name="talker_1_param" value="a value" />
<!-- nodes can have their own remap args -->
<remap from="chatter" to="hello-1"/>
<!-- you can set environment variables for a node -->
<!--设定环境变量-->
<env name="ENV_EXAMPLE" value="some value" />
</node>
</group>
<arg> <!--定义参数传入到launch文件中-->
<remap> <!-- 设定参数映射-->
<rosparam> <!--启动yaml文件参数到参数服务器-->
<include> <!--包含其他的launch文件-->
<group> <!--设定命名空间--
</launch>
常用指令
# 启动 ros master
$ roscore
# 启动 node
$ rosrun [pkg_name] [node_name]
# rosnode
# 列出当前运行的node信息
$ rosnode list
# 显示某个node的详细信息
$ rosnode info [node_name]
$ rosnode kill [node_name]
# roslaunch 启动master和多个node
# roslaunch [pkg_name] [file_name]
![2dd8e52ce9210a697b7108d52e9d6581.png](https://img-blog.csdnimg.cn/img_convert/2dd8e52ce9210a697b7108d52e9d6581.png)
2.4 Topic通讯 --- 一个node发布Topic,另一个node订阅Topic;
Node之间通过publish/subscribe机制通信;
--- --- 1 ) Topic通讯是异步的,一个node只管发布Topic,它不在乎是谁订阅了这个Topic;另一个node只管订阅,它不在乎到底是谁发布了这个topic
--- --- 2 ) 一个node可以被多个node进行subscribe操作
--- --- 3 ) Topic在被发布时,需要调用publish()方法
--- --- 4 ) Topic有严格的格式要求,其数据类型为:***.Msg (Message)
基本msg包括bool、int8、int16、int32、int64、float32、float64、string、time、duration、hearder可变长数组array[],固定长度数组array[C].
![920fde22578d55ae0c9515cb03b24dec.png](https://img-blog.csdnimg.cn/img_convert/920fde22578d55ae0c9515cb03b24dec.png)
# 与Topic、Msg相关命令
# rostopic
# 列出当前所有的topic
$ rostopic list
# 显示某个topic的属性信息
$ rostopic info /topic_name
# 显示某个topic的内容
$ rostopic echo /topic_name
# 向某个topic发布内容
$ rostopic pub /topic_name
# rosmsg
# 列出系统上所有的msg
$ rosmsg list
# 显示某个msg内容
$ rosmsg show /msg_name
2.5 Service通信 --- ROS的同步通讯方式
/Topic是异步的,/Service是同步的,各个Node之间可以通过请求(Request)和应答(Reply)的方式进行通讯。
Service的应用场景,比如当前一个节点node1的任务非常耗费计算资源,现在node2需要node1发布的结果(比如目标检测、人体关键点识别结果等),但是node1运行起来是很费事费力的,现在如果node2订阅node1,node1会不停的进行任务发布,这很耗费资源,service解决了这种囧境,引入了请求响应,Request & Reply(RR)的机制,Server提供一个服务,某个节点只有需要这个服务才会请求。即Client发出请求,堵塞,Server返回结果后,完成通信。
Service与Topic的不同在于:
1. Service消息的通讯模型是Request-Reply即Client-Server模式,该模式可以一对一,也可以多对一(一个服务,可以有多个Client来请求;一个Client可以请求多个服务),远程过程调用服务器端服务;Topic的通讯模型是Publisher-Subscriber,可以一对一,也可以多对一,也可以多对多,接受者在收到数据后需要进行回调(Callback)。
2.Service常用于偶尔调用的功能,或者某具体任务(传感器的开关,是否进行拍照,坐标变化等), Topic常用于连续、高频的数据发布场景中(激光雷达,里程计,摄像头数据传输)。
![23cb3b17df19f885e78c8f8fe601054e.png](https://img-blog.csdnimg.cn/img_convert/23cb3b17df19f885e78c8f8fe601054e.png)
Service通信的数据格式: ***.srv; 注意,srv里只能嵌套msg,不能再嵌套srv;srv与msg定义好了后,需要对package.xml和CMakeList.txt进行修改。
常用命令
# rosservice
# 列出当前所有活跃的service
$ rosservice list
# 显示某个service的具体信息
$ rosservice info service_name
# 调用某个service
$rosservice call service_name args
# rossrv
# 列出系统上所有srv
$ rossrv list
# 显示某个srv内容
$ rossrv show srv_name
Parameter Server参数服务器, 用于存储各种参数的字典、可用命令行、launch文件和node(API)读写;维护起来很灵活,可通过命令行维护,也可通过launch和node进行读写。
常用命令行
$ rosparam list # 列出当前所有参数
$ rosparam get param_key # 显示某个参数的值
$ rosparam set param_key param_value # 设置某个参数的值
$ rosparam dump file_name # 保存参数到文件
$ rosparam load file_name # 从文件中读取参数
$ rosparam delete param_key # 删除参数
# 文件格式形如下:
name: 'XXX'
age: XXX
hobboy: 'XXX'
score: {XXX:XX,XXX:XX}
launch文件对参数服务器进行操作的方法:
<launch>
<!--读取机器人模型参数-->
<!--command命令,寻找xacro.py脚本,执行这个脚本,robot.xacro作为value值-->
<param name="robot description" command=$(find xacro)xacro.py$(find robot_sim_demo)/urdf/robot.xacro"/>
.....
<!--把关节控制的配置信息读到参数服务器-->
<rosparam file = "$(find robot_sim_demo)/config/xbot2_control.yaml" command="load"/>
2.5 action通讯方式---带有状态反馈的通信方式,类似Service
在Service的通讯方式中,Client不知道Server的执行状态,万一Server死机,没有状态反馈让Client没有头绪。 所以针对这个问题,出现了action的通讯方式,类似于一个升级版的Service。这种通信方式常常用在长时间,可抢占的任务中。比如小车导航、机械臂运动等。
![d96e2628d1d37c9c93b6813cd0868d9f.png](https://img-blog.csdnimg.cn/img_convert/d96e2628d1d37c9c93b6813cd0868d9f.png)
- goal --- 请求任务;
- cancel --- 删除任务;
- status --- Server状态;
- result --- 请求结果, 只传一次;
- feedback --- 实时状态需要进行反馈,多次回传, 比如回传当前进度 %xx;
3.常用工具包
- 仿真工具: Gazebo --- 机器人仿真工具,ODE物理引擎,用于动力学、导航、感知等任务的模拟;
- 调试、可视化工具: Rviz, rqt --- Rviz(The Robot Visualization tool) 方便调试和监控与开发; Rqt(Ros of Qt) 也是一种可视化工具,其中:
- rqt_graph: 显示有哪些node,哪些topic,消息流向... 可以反映系统的全貌,只管显示通信架构;
- rqt_plot: 绘制动态曲线;
- rqt_console: 用于查看日志;
- 命令行工具: rostopic, rosbag
- 机械臂专用工具: Moveit!
参考链接
cn - ROS Wikiwiki.ros.org 机器人操作系统入门_中科院软件所-重德智能机器人联合研究中心_中国大学MOOC(慕课)icourse163.org![1112d66327daad291d9fd194a29b8a63.png](https://img-blog.csdnimg.cn/img_convert/1112d66327daad291d9fd194a29b8a63.png)