3.5 話題重名
問(wèn)題描述
節(jié)點(diǎn)名稱可能出現(xiàn)重名的情況,同理話題名稱也可能重名,不過(guò)與節(jié)點(diǎn)重名不同的是,有些場(chǎng)景下需要避免話題重名的情況,但有些場(chǎng)景下又需要將不同的不同的話題名稱修改為相同。
在 ROS2 不同的節(jié)點(diǎn)之間通信都依賴于話題,話題名稱也可能出現(xiàn)重名的情況,話題重名時(shí),系統(tǒng)雖然不會(huì)拋出異常,但是通過(guò)相同話題名稱關(guān)聯(lián)到一起的節(jié)點(diǎn)可能并不屬于同一通信邏輯,從而導(dǎo)致通信錯(cuò)亂,甚至出現(xiàn)異常。這種情況下可能就需要將相同的話題名稱設(shè)置為不同。
又或者,兩個(gè)節(jié)點(diǎn)是屬于同一通信邏輯的,但是節(jié)點(diǎn)之間話題名稱不同,導(dǎo)致通信失敗。這種情況下就需要將兩個(gè)節(jié)點(diǎn)的話題名稱由不同修改為相同。
那么如何修改話題名稱呢?
解決思路
與節(jié)點(diǎn)重名的解決思路類似的,為了避免話題重名問(wèn)題,一般有兩種策略:
名稱重映射,也即為話題名稱起別名;
命名空間,是為話題名稱添加前綴,可以有多級(jí),格式:/xxx/yyy/zzz。
需要注意的是,通過(guò)命名空間設(shè)置話題名稱時(shí),需要保證話題是非全局話題。
解決方案
與節(jié)點(diǎn)重名解決方案類似的,修改話題名稱的方式主要有如下三種:
ros2 run 命令實(shí)現(xiàn);
launch 文件實(shí)現(xiàn);
編碼實(shí)現(xiàn)。
本節(jié)將逐一演示上述三種方案的實(shí)現(xiàn)語(yǔ)法。
3.5.1 ros2 run 修改話題名稱
1.ros2 run設(shè)置命名空間
該實(shí)現(xiàn)與3.4.1 ros2 run設(shè)置節(jié)點(diǎn)名稱中演示的語(yǔ)法使用一致。
1.1設(shè)置命名空間演示
語(yǔ)法:ros2 run 包名 節(jié)點(diǎn)名 --ros-args --remap __ns:=命名空間
示例:
ros2 run turtlesim turtlesim_node --ros-args --remap __ns:=/t1
1.2運(yùn)行結(jié)果
使用ros2 topic list
查看節(jié)點(diǎn)信息,顯示結(jié)果:

節(jié)點(diǎn)下的話題已經(jīng)添加了命名空間前綴。
2.ros2 run話題名稱重映射
2.1為話題起別名
語(yǔ)法:?ros2 run 包名 節(jié)點(diǎn)名 --ros-args --remap 原話題名稱:=新話題名稱
示例:
ros2 run turtlesim turtlesim_node --ros-args --remap /turtle1/cmd_vel:=/cmd_vel
2.2運(yùn)行結(jié)果
使用ros2 topic list
查看節(jié)點(diǎn)信息,顯示結(jié)果:

節(jié)點(diǎn)下的話題/turtle1/cmd_vel已經(jīng)被修改為了/cmd_vel。
注意:
當(dāng)為節(jié)點(diǎn)添加命名空間時(shí),節(jié)點(diǎn)下的所有非全局話題都會(huì)前綴命名空間,而重映射的方式只是修改指定話題。
3.5.2 launch 文件修改話題名稱
1.Python方式實(shí)現(xiàn)的launch文件修改話題名稱
在 Python 方式實(shí)現(xiàn)的 launch 文件中,可以通過(guò)類?launch_ros.actions.Node
的構(gòu)造函數(shù)中的參數(shù) remappings 修改話題名稱,使用示例如下:

2.XML方式實(shí)現(xiàn)的launch文件修改話題名稱
在 XML 方式實(shí)現(xiàn)的 launch 文件中,可以通過(guò) node 標(biāo)簽的子標(biāo)簽 remap(屬性from取值為被修改的話題名稱,屬性to的取值為修改后的話題名稱) 修改話題名稱,使用示例如下:

3.YAML方式實(shí)現(xiàn)的launch文件修改話題名稱
在 YAML 方式實(shí)現(xiàn)的 launch 文件中,可以通過(guò) node 屬性中 remap(屬性from取值為被修改的話題名稱,屬性to的取值為修改后的話題名稱) 修改話題名稱,使用示例如下:

4.測(cè)試
上述三種方式在修改話題名稱時(shí)雖然語(yǔ)法不同,但是實(shí)現(xiàn)功能類似,都是啟動(dòng)了兩個(gè)turtlesim_node
節(jié)點(diǎn),一個(gè)節(jié)點(diǎn)添加了命名空間,另一個(gè)節(jié)點(diǎn)將話題從/turtle1/cmd_vel
映射到了/cmd_vel
。使用ros2 topic list
查看節(jié)點(diǎn)信息,顯示結(jié)果:
添加命名空間的節(jié)點(diǎn)對(duì)應(yīng)的話題為:

3.5.3 編碼設(shè)置話題名稱
話題分類
話題的名稱的設(shè)置是與節(jié)點(diǎn)的命名空間、節(jié)點(diǎn)的名稱有一定關(guān)系的,話題名稱大致可以分為三種類型:
全局話題(話題參考ROS系統(tǒng),與節(jié)點(diǎn)命名空間平級(jí));
相對(duì)話題(話題參考的是節(jié)點(diǎn)的命名空間,與節(jié)點(diǎn)名稱平級(jí));
私有話題(話題參考節(jié)點(diǎn)名稱,是節(jié)點(diǎn)名稱的子級(jí))。
總之,以編碼方式設(shè)置話題名稱是比較靈活的。本節(jié)將介紹如何在 rclcpp 和 rclpy 中分別設(shè)置不同類型的話題。
準(zhǔn)備
請(qǐng)先分別創(chuàng)建 C++ 與 Python 相關(guān)的功能包以及節(jié)點(diǎn),且假定在創(chuàng)建節(jié)點(diǎn)時(shí),使用的命名空間為 xxx,節(jié)點(diǎn)名稱為 yyy。
話題設(shè)置
1.1全局話題
格式:定義時(shí)以/
開頭的名稱,和命名空間、節(jié)點(diǎn)名稱無(wú)關(guān)。
rclcpp示例:publisher_ = this->create_publisher<std_msgs::msg::String>("/topic/chatter", 10);
rclpy示例:self.publisher_ = self.create_publisher(String, '/topic/chatter', 10)
話題:話題名稱為 /topic/chatter,與命名空間 xxx 以及節(jié)點(diǎn)名稱 yyy 無(wú)關(guān)。
1.2相對(duì)話題
格式:非/
開頭的名稱,參考命名空間設(shè)置話題名稱,和節(jié)點(diǎn)名稱無(wú)關(guān)。
rclcpp示例:publisher_ = this->create_publisher<std_msgs::msg::String>("topic/chatter", 10);
rclpy示例:self.publisher_ = self.create_publisher(String, 'topic/chatter', 10)
話題:話題名稱為 /xxx/topic/chatter,與命名空間 xxx 有關(guān),與節(jié)點(diǎn)名稱 yyy 無(wú)關(guān)。
1.3私有話題
格式:定義時(shí)以~/
開頭的名稱,和命名空間、節(jié)點(diǎn)名稱都有關(guān)系。
rclcpp示例:publisher_ = this->create_publisher<std_msgs::msg::String>("~/topic/chatter", 10);
rclpy示例:self.publisher_ = self.create_publisher(String, '~/topic/chatter', 10)
話題:話題名稱為 /xxx/yyy/topic/chatter,使用命名空間 xxx 以及節(jié)點(diǎn)名稱 yyy 作為話題名稱前綴。
綜上,話題名稱設(shè)置規(guī)則在rclcpp與rclpy中基本一致,且上述規(guī)則也同樣適用于ros2 run指令與launch文件。

B站有完整的ros系列教程視頻,可以觀看完整內(nèi)容ros課程ROS2理論與實(shí)踐
更多內(nèi)容將在猛獅知識(shí)星球社區(qū)更新最新課程,后續(xù)將推出更多優(yōu)質(zhì)內(nèi)容——詳情可關(guān)注猛獅集訓(xùn)營(yíng)公眾號(hào)和猛獅集訓(xùn)營(yíng)官方網(wǎng)站。