目錄
- 目錄
- 一、ROS1和RO2之間的橋接概述
- 二、橋接流程
- 三、ROS 1 talker -> ROS 2 listener
- 四、ROS 2 talker -> ROS 1 listener
- 五、ROS 2 拍攝圖像 -> ROS 1 顯示圖像
- 六、傳輸Service
- 七、僅橋接選定的主題和服務(wù)
- 八、參數(shù)化服務(wù)質(zhì)量
一、ROS1和RO2之間的橋接概述
ROS2提供了一個(gè)ROS2 package,這個(gè)包提供了一個(gè)橋(bridge),可以在 ROS 1 和 ROS 2 之間交換消息。
該橋目前在 C++ 中實(shí)現(xiàn),因?yàn)楫?dāng)時(shí) ROS 2 的 Python API 尚未開發(fā)。因此,它的支持僅限于橋編譯時(shí)可用的消息/服務(wù)類型。
目前ros1_bridge這個(gè)包的功能有限,還不提供python實(shí)現(xiàn),預(yù)構(gòu)建 ROS 2 二進(jìn)制文件提供的橋包括對(duì)通用 ROS 接口(消息/服務(wù))的支持,僅支持ros2_common_interfaces中列出的通訊類型和tf2_msgs。
如果想使用自定義類型的ros1_bridge,則必須在單獨(dú)的 ROS 1 和 ROS 2 工作區(qū)中構(gòu)建自定義類型后,從源代碼構(gòu)建ros1_bridge。
出于效率原因,只有當(dāng)匹配的發(fā)布者-訂閱者對(duì)在ros1_bridge的任一側(cè)都處于活動(dòng)狀態(tài)時(shí),才會(huì)橋接topic。因此,如果沒(méi)有其他訂閱者存在,使用命令行工具ros2 topic echo <topic-name>不起作用,但會(huì)失敗并顯示錯(cuò)誤消息Could not determine the type for the passed topic,因?yàn)?code>dynamic_bridge尚未橋接topic。
作為解決方法,可以明確指定topic類型ros2 topic echo <topic-name> <topic-type>,這會(huì)觸發(fā)topic的橋接,因?yàn)樵?code>echo命令表示必要的訂閱者。
但在 ROS 1 端rostopic echo沒(méi)有明確指定topic類型的選項(xiàng)。因此,如果沒(méi)有其他訂閱者,它不能與ROS2的dynamic_bridge一起使用。作為替代方案,可以使用ros2 run ros1_bridge dynamic_bridge --bridge-all-2to1-topics選項(xiàng)把所有 ROS 2的topic橋接到 ROS 1,以便即使沒(méi)有匹配的 ROS 1 訂閱者,rostopic echo、rostopic list和rqt這些工具也會(huì)看到topic。運(yùn)行ros2 run ros1_bridge dynamic_bridge -- --help以獲得更多選項(xiàng)。
注意,ROS2官方提示目前ros1_bridge已經(jīng)存在的一些問(wèn)題:
-
可能需要
ros2 run ros1_bridge dynamic_bridge --bridge-all-topics才能正確橋接。 經(jīng)過(guò)測(cè)試并報(bào)告說(shuō),當(dāng)至少一種自定義消息類型在 ROS 2 中發(fā)布并在 ROS 1 中訂閱時(shí),--bridge-all-topics是必需的。還有非正式地報(bào)告說(shuō),在相同條件下,內(nèi)置消息類型需要--bridge-all-topics選項(xiàng)。 - 最后
ros1_bridge一旦與 ROS 1 主服務(wù)器建立了映射,就可以在沒(méi)有--bridge-all-topics的情況下重新運(yùn)行ros1_bridge,以便有選擇地橋接主題。 但是,這不能保證。
二、橋接流程
橋接過(guò)程至少需要開啟四個(gè)終端:
Terminal 1 |
Terminal 2 |
Terminal 3 |
Terminal 4 |
|
|---|---|---|---|---|
| ROS環(huán)境變量 | source ros1 |
source ros1 |
source ros1, source ros2
|
source ros2 |
| 命令 | roscore |
運(yùn)行你需要使用的ros1的包 |
export ROS_MASTER_URI=http://localhost_IP:11311ros2 run ros1_bridge dynamic_bridge
|
運(yùn)行你需要使用的ros2的包 |
注意:當(dāng)運(yùn)行這些demo時(shí),確保僅提供指定ROS版本的環(huán)境變量。如果在某些節(jié)點(diǎn)中有兩個(gè)ROS工作區(qū),將收到錯(cuò)誤消息。
三、ROS 1 talker -> ROS 2 listener
3.1 運(yùn)行命令
Terminal 1 |
Terminal 2 |
Terminal 3 |
Terminal 4 |
|
|---|---|---|---|---|
| ROS環(huán)境變量 | source ros1 |
source ros1 |
source ros1, source ros2
|
source ros2 |
| 命令 | roscore |
rosrun rospy_tutorials talker |
export ROS_MASTER_URI=http://localhost_IP:11311ros2 run ros1_bridge dynamic_bridge
|
ros2 run demo_nodes_cpp listener |
首先啟動(dòng)roscore(左上角),接著運(yùn)行自己的ROS1節(jié)點(diǎn)(左下角),ROS 1 節(jié)點(diǎn)開始將發(fā)布的消息打印到控制臺(tái)。
然后啟動(dòng)ros1_bridge(右上角),它將監(jiān)視可用的 ROS 1 和 ROS 2 主題,一旦檢測(cè)到匹配的主題,它就會(huì)開始橋接關(guān)于該主題的消息。ros1_bridge開始定期輸出 ROS 1 和 ROS 2 中當(dāng)前可用的主題。
最后運(yùn)行自己的ROS2節(jié)點(diǎn)(右下角),ROS 2 節(jié)點(diǎn)開始將收到的消息打印到控制臺(tái)。
3.2 輸出結(jié)果
在橋接的過(guò)程中,Terminal 3(右上角)有一行說(shuō)明該topic的bridge已創(chuàng)建:
created 1to2 bridge for topic '/chatter' with ROS 1 type 'std_msgs/String' and ROS 2 type 'std_msgs/String'
在停止了 talker 或 listener 中的任何一個(gè),就會(huì)有一行表明橋已被拆除:
removed 1to2 bridge for topic '/chatter'

四、ROS 2 talker -> ROS 1 listener
4.1 運(yùn)行命令
Terminal 1 |
Terminal 2 |
Terminal 3 |
Terminal 4 |
|
|---|---|---|---|---|
| ROS環(huán)境變量 | source ros1 |
source ros1 |
source ros1, source ros2
|
source ros2 |
| 命令 | roscore |
rosrun roscpp_tutorials listener |
export ROS_MASTER_URI=http://localhost_IP:11311ros2 run ros1_bridge dynamic_bridge
|
ros2 run demo_nodes_py talker |
首先啟動(dòng)roscore(左上角),接著運(yùn)行自己的ROS2節(jié)點(diǎn)(左下角),ROS 2 節(jié)點(diǎn)開始將發(fā)布的消息打印到控制臺(tái)。
然后啟動(dòng)ros1_bridge(右上角),它將監(jiān)視可用的 ROS 1 和 ROS 2 主題,一旦檢測(cè)到匹配的主題,它就會(huì)開始橋接關(guān)于該主題的消息。ros1_bridge開始定期輸出 ROS 1 和 ROS 2 中當(dāng)前可用的主題。
最后運(yùn)行自己的ROS1節(jié)點(diǎn)(右下角),ROS 1 節(jié)點(diǎn)開始將收到的消息打印到控制臺(tái)。
4.2 輸出結(jié)果
在橋接的過(guò)程中,Terminal 3(右上角)有一行說(shuō)明該topic的bridge已創(chuàng)建:
created 2to1 bridge for topic '/chatter' with ROS 2 type 'std_msgs/String' and ROS 1 type 'std_msgs/String'
在停止了 talker 或 listener 中的任何一個(gè),就會(huì)有一行表明橋已被拆除:
removed 2to1 bridge for topic '/chatter'
五、ROS 2 拍攝圖像 -> ROS 1 顯示圖像
ros1_bridge也可以傳輸大數(shù)據(jù)消息,如圖像數(shù)據(jù)。
ROS 2 節(jié)點(diǎn)發(fā)布相機(jī)圖像,ROS 1 使用rqt_image_view在 GUI 中渲染圖像。
5.1 運(yùn)行命令
Terminal 1 |
Terminal 2 |
Terminal 3 |
Terminal 4 |
|
|---|---|---|---|---|
| ROS環(huán)境變量 | source ros1 |
source ros1 |
source ros1, source ros2
|
source ros2 |
| 命令 | roscore |
rqt_image_view /image |
export ROS_MASTER_URI=http://localhost_IP:11311ros2 run ros1_bridge dynamic_bridge
|
ros2 run image_tools cam2image |
首先啟動(dòng)roscore(左上角),接著運(yùn)行自己的ROS1節(jié)點(diǎn)(左下角)。
然后啟動(dòng)ros1_bridge(右上角),它將監(jiān)視可用的 ROS 1 和 ROS 2 主題,一旦檢測(cè)到匹配的主題,它就會(huì)開始橋接關(guān)于該主題的消息。ros1_bridge開始定期輸出 ROS 1 和 ROS 2 中當(dāng)前可用的主題。
最后運(yùn)行自己的ROS2節(jié)點(diǎn)(右下角)。
5.2 輸出結(jié)果

六、傳輸Service
在這個(gè)例子中,我們將橋接來(lái)自 ros/roscpp_tutorials的服務(wù) TwoInts和來(lái)自 ros2/roscpp_examples 的 AddTwoInts。
在構(gòu)建時(shí),ros1_bridge 會(huì)查找所有已安裝的 ROS 和 ROS2 服務(wù)。通過(guò)比較請(qǐng)求和響應(yīng)中的包名稱、服務(wù)名稱和字段來(lái)匹配找到的服務(wù)。如果 ROS 和 ROS2 服務(wù)中的所有名稱都相同,則將創(chuàng)建網(wǎng)橋。也可以通過(guò)創(chuàng)建包含相應(yīng)服務(wù)名稱的 yaml 文件來(lái)手動(dòng)配對(duì)服務(wù)。
為了使這個(gè)示例正常運(yùn)行,請(qǐng)確保在構(gòu)建 ros1_bridge 時(shí)系統(tǒng)上安裝了 roscpp_tutorials 包并且環(huán)境設(shè)置正確。
6.1 運(yùn)行命令
Terminal 1 |
Terminal 2 |
Terminal 3 |
Terminal 4 |
|
|---|---|---|---|---|
| ROS環(huán)境變量 | source ros1 |
source ros1 |
source ros1, source ros2
|
source ros2 |
| 命令 | roscore |
rosrun roscpp_tutorials add_two_ints_server |
export ROS_MASTER_URI=http://localhost_IP:11311ros2 run ros1_bridge dynamic_bridge
|
ros2 run demo_nodes_cpp add_two_ints_client |
首先啟動(dòng)roscore(左上角),接著運(yùn)行自己的ROS1節(jié)點(diǎn)(左下角)。
然后啟動(dòng)ros1_bridge(右上角),它將監(jiān)視可用的 ROS 1 和 ROS 2 服務(wù),一旦檢測(cè)到匹配的服務(wù),它就會(huì)開始橋接關(guān)于該服務(wù)的消息。ros1_bridge開始定期輸出 ROS 1 和 ROS 2 中當(dāng)前可用的服務(wù)。
最后運(yùn)行自己的ROS2節(jié)點(diǎn)(右下角)。
6.2 輸出結(jié)果

七、僅橋接選定的主題和服務(wù)
ros1_bridge通過(guò)配置文件可以選擇性橋接自己需要的主題和服務(wù)。
ros1_bridge包使用dynamic_bridge節(jié)點(diǎn)來(lái)橋接所有主題和服務(wù),使用parameter_bridge節(jié)點(diǎn)通過(guò)ROS1的參數(shù)服務(wù)器來(lái)選擇橋接哪些主題和服務(wù)。
橋接所有主題和服務(wù)
ros2 run ros1_bridge dynamic_bridge
通過(guò)ROS1的參數(shù)服務(wù)器來(lái)選擇橋接指定的主題和服務(wù)
ros2 run ros1_bridge parameter_bridge
注意:service的bridge是單向的,必須相應(yīng)地使用services_2_to_1橋接 ROS 2 -> ROS 1 和services_1_to_2來(lái)橋接 ROS 1 -> ROS 2 的service。
例如,使得主題/chatter時(shí)雙向橋接的,而服務(wù)/add_two_ints service僅從 ROS 2 -> ROS 1,可以創(chuàng)建如下配置文件bridge.yaml:
topics:
-
topic: /chatter # Topic name on both ROS 1 and ROS 2
type: std_msgs/msg/String # Type of topic to bridge
queue_size: 1 # Queue size
services_2_to_1:
-
service: /add_two_ints # ROS 1 service name
type: roscpp_tutorials/TwoInts # The ROS 1 service type name
7.1 運(yùn)行命令
Terminal 1 |
Terminal 2 |
Terminal 3 |
Terminal 4 |
Terminal 5 |
Terminal 6 |
|
|---|---|---|---|---|---|---|
| ROS環(huán)境變量 | source ros1 |
source ros1 |
source ros1 |
source ros2 |
source ros2 |
source ros2 |
| 命令 | roscore |
rosparam load bridge.yaml;rosrun rospy_tutorials talker
|
rosrun roscpp_tutorials add_two_ints_server |
ros2 run ros1_bridge parameter_bridge |
ros2 run demo_nodes_cpp listener |
ros2 service call /add_two_ints example_interfaces/srv/AddTwoInts "{a: 1, b: 2}" |
首先啟動(dòng)roscore,接著加載 bridge.yaml 配置文件,然后啟動(dòng) talker和server。
啟動(dòng)ros1_bridge中的parameter_bridge,日志顯示它正在為主題和服務(wù)創(chuàng)建橋梁,如果一切順利,就能夠調(diào)用該服務(wù)并從 ROS 2 收聽 ROS 1 talker。
對(duì)于ROS2的listener,這時(shí)應(yīng)該輸出I heard: [hello world ...]帶有時(shí)間戳的文本。
對(duì)于ROS2的client,這時(shí)應(yīng)該輸出example_interfaces.srv.AddTwoInts_Response(sum=3)。
八、參數(shù)化服務(wù)質(zhì)量
ROS 2 優(yōu)于 ROS 1 的一個(gè)優(yōu)勢(shì)是可以為每個(gè)主題定義不同的服務(wù)質(zhì)量設(shè)置。
parameter_bridge 也可以通過(guò)ROS 1的參數(shù)配置文件修改ROS2相應(yīng)的話題的服務(wù)質(zhì)量(Qos)。
ROS 1 中的/tf_static話題用來(lái)描述不同靜態(tài)坐標(biāo)系的變換關(guān)系,在ROS1中只會(huì)發(fā)布一次,若ROS2節(jié)點(diǎn)需要該數(shù)據(jù),可以通過(guò)ROS 2 中parameter_bridge設(shè)置Qos中的history參數(shù)來(lái)獲取數(shù)據(jù),該/tf_static的主題配置為:
topics:
-
topic: /tf_static
type: tf2_msgs/msg/TFMessage
queue_size: 1
qos:
history: keep_all
durability: transient_local
所有其他 QoS 選項(xiàng)(如https://docs.ros.org/en/foxy/Concepts/About-Quality-of-Service-Settings.html中所述)均可用:
topics:
-
topic: /some_ros1_topic
type: std_msgs/msg/String
queue_size: 1
qos:
history: keep_last # OR keep_all, then you can omit `depth` parameter below
depth: 10 # Only required when history == keep_last
reliability: reliable # OR best_effort
durability: transient_local # OR volatile
deadline:
secs: 10
nsecs: 2345
lifespan:
secs: 20
nsecs: 3456
liveliness: liveliness_system_default # Values from https://design.ros2.org/articles/qos_deadline_liveliness_lifespan.html, eg. LIVELINESS_AUTOMATIC
liveliness_lease_duration:
secs: 40
nsecs: 5678
請(qǐng)注意,該qos部分可以完全省略,未設(shè)置的選項(xiàng)保留為默認(rèn)值。
參考:
ros1_bridge官方:https://github.com/ros2/ros1_bridge
ros1_bridge無(wú)法建立通訊解決辦法:https://blog.csdn.net/weixin_37669024/article/details/122348311
ros1_bridge運(yùn)行結(jié)果不成功,報(bào)錯(cuò)No executable found:https://blog.csdn.net/wsc820508/article/details/81408251