前言
经过前面四种通信机制的学习,ROS2的大致结构如下:
当然,其中还有一些问题。
文章目录
1.分布式
在许多机器人相关的应用场景中都涉及到多台ROS2设备协作,比如:无人车编队、无人机编队、远程控制等等。机器人编队时,机器人可能需要获取周边机器人的速度、位置、运行轨迹的相关信息,远程控制时,则可能需要控制端获取机器人采集的环境信息并下发控制指令…
这些数据的交互都依赖于分布式通信。
多机通信时,可以通过域ID对节点进行分组,组内的节点之间可以自由通信,不同组之间的节点则不可通信。如果所有节点都属于同一组,那么直接使用默认域ID即可,如果要将不同节点划分为多个组,那么可以在终端中启动节点前设置该节点的域ID(比如设置为6),具体执行命令为:
export ROS_DOMAIN_ID=6
如果要为当前设备下的所有节点设置统一的域ID,那么可以执行如下指令:
echo "export ROS_DOMAIN_ID=6" >> ~/.bashrc
然后重新启动终端,所有节点将自动被划分到ID为6的区域!
下图演示的就是一个对域ID进行分组的示例: 分组后,就不能接收到发布方发布的消息了!
提示: 1.建议ROS_DOMAIN_ID的取值在[0,101] 之间,包含0和101;
2.每个域ID内的节点总数是有限制的,需要小于等于120个;
3.如果域ID为101,那么该域的节点总数需要小于等于54个。
2.工作空间覆盖
同一工作空间下不允许出现功能包重名的情况,但是当存在多个工作空间时,不同工作空间下的功能包是可以重名的,那么当功能包重名时,会调用哪一个呢?
这就涉及到工作空间的覆盖知识了!
所谓工作空间覆盖,是指不同工作空间存在重名功能包时,重名功能包的调用会产生覆盖的情况。其没什么用,这种情况是需要极力避免出现的。
前面提到,工作空间覆盖的情况是需要极力避免出现的,因为导致一些安全隐患:
①可能会出现功能包调用混乱,出现实际调用与预期调用结果不符的情况;
②即便可以通过 ~/.bashrc 来配置不同工作空间的优先级,但是经过测试,修改 ~/.bashrc
文件之后不一定马上生效,还需要删除工作空间下build与install目录重新编译,才能生效,这个过程繁琐且有不确定性。
综上,在实际工作中,需要制定明确的包命名规范,避免包重名情况。
完成后大家记得删掉东西,别影响后续我们使用小乌龟!
3.元功能包
完成一个系统性的功能,可能涉及到多个功能包,比如实现了机器人导航模块,该模块下有地图、定位、路径规划…等不同的子级功能包。那么调用者安装该模块时,需要逐一的安装每一个功能包吗?
显而易见的,逐一安装功能包的效率低下,在ROS2中,提供了一种方式可以将不同的功能包打包成一个功能包,当安装某个功能模块时,直接调用打包后的功能包即可,该包又称之为元功能包。
例如:
sudo apt install ros-<ros2-distro>-desktop
命令安装 ros2 时就使用了元功能包,该元功能包依赖于 ROS2 中的其他一些功能包,安装该包时会一并安装依赖。
此时元功能包就把其他功能包整合起来了!!!
4.节点重名
在 ROS2 中不同的节点可以有相同的节点名称,比如可以启动多个 turtlesim_node 节点,这些节点的名称都是turtlesim。节点重名虽然是被允许的,但是开发者应该主动避免这种情况,因为节点重名时可能会导致操作上的混淆,仍以启动了多个turtlesim_node节点为例,当使用计算图(rqt_graph)查看节点运行状态时,由于他们的节点名称一致,那么虽然实际有多个节点,但是在计算图上显示一个。并且节点名称也会和话题名称、服务名称、动作名称、参数等产生关联,届时也可能会导致通信逻辑上的混乱。
避免重名问题,一般有两种策略:
①名称重映射,也即为节点起别名;
②命名空间,是为节点名称添加前缀,可以有多级,格式:/xxx/yyy/zzz。上述两种策略的实现途径主要有如下三种:
①ros2 run 命令实现;
②launch 文件实现;
③编码实现。
4.1 用ros2 run命令实现
设置命名空间:
语法:
ros2 run 包名 节点名 --ros-args --remap __ns:=命名空间
ros2 run turtlesim turtlesim_node --ros-args --remap __ns:=/t1
设置节点别名:
语法: ros2 run 包名 节点名 --ros-args --remap __name:=新名称
或
ros2 run 包名 节点名 --ros-args --remap __node:=新名称
示例:
ros2 run turtlesim turtlesim_node --ros-args --remap __name:=turtle1
设置节点别名与设置命名空间结合:
语法: ros2 run 包名 节点名 --ros-args --remap __ns:=新名称 --remap __name:=新名称
ros2 run turtlesim turtlesim_node --ros-args --remap __ns:=/t1 --remap __name:=turtle1
4.2 用launch设置节点名称
准备工作:
用paython的launch文件:
在launch中创建一个python的文件:
用.xml的launch文件:
在launch中创建一个.xml的文件:
用.yaml的launch文件:
在launch中创建一个.yaml的文件:
还可以同时设置,这里我只演示一个,其他的大家自己跑一下
也就是这样,会同时生成三个而已!
namespace是命名空间,那么是重命名!
4.3 编码设置
5.话题重名
节点名称可能出现重名的情况,同理话题名称也可能重名,不过与节点重名不同的是,有些场景下需要避免话题重名的情况,但有些场景下又需要将不同的不同的话题名称修改为相同。
在 ROS2不同的节点之间通信都依赖于话题,话题名称也可能出现重名的情况,话题重名时,系统虽然不会抛出异常,但是通过相同话题名称关联到一起的节点可能并不属于同一通信逻辑,从而导致通信错乱,甚至出现异常。这种情况下可能就需要将相同的话题名称设置为不同。
又或者,两个节点是属于同一通信逻辑的,但是节点之间话题名称不同,导致通信失败。这种情况下就需要将两个节点的话题名称由不同修改为相同。
与节点重名的解决思路类似的,为了避免话题重名问题,一般有两种策略:
①名称重映射,也即为话题名称起别名;
②命名空间,是为话题名称添加前缀,可以有多级,格式:/xxx/yyy/zzz。
与节点重名解决方案类似的,修改话题名称的方式主要有如下三种:
①ros2 run 命令实现;
②launch 文件实现;
③编码实现。
5.1 ros2 run实现
由于这一节和节点重名类似,就只放结果了!
设置话题空间(前缀):
起别名(重映射):
话题重名的作用:
5.2 launch文件实现
python:
.xml:
.yaml:
5.3 编码实现
再进行编码实现之前我们有必要了解一下话题的分类:
1.话题的分类
2.编码实现
首先添加依赖项:
全局话题:
qos是什么?
历史区域大小指定了发布者在发布消息时存储消息的数量。每当发布者发布一条消息时,消息会被存储在历史区域中。当订阅者订阅该话题时,它可以选择接收最近的一条或多条消息。在本例中,history depth设置为10,这意味着发布者会在历史区域中存储最近的10条消息。如果有订阅者在发布者之前订阅该话题,它将接收到这些历史消息作为初始数据。
通过调整历史区域大小,可以控制订阅者在订阅之前获取的历史消息数量。较大的历史区域大小可以提供更多的历史消息,但会占用更多的资源。较小的历史区域大小可能会导致订阅者在订阅之前丢失一些消息.需要注意的是,QoS配置还包括其他参数,如可靠性、延迟、带宽限制等,可以根据具体需求进行配置。
相对话题:
私有话题: