ROS多設備交互

ROS多設備連接同一個Master:ROS Master多設備連接-CSDN博客

在多個PC端連接同一個ROS Master后,接下來就可以實現不同設備之間的話題交流,Master主機端啟動不同PC端的功能包等功能了

盡管多個PC端擁有不同的ROS工作空間,但是只要他們都連接在同一個ROS Master下,它們就能互相通信(工作空間只是存放ROS代碼(功能包)的目錄(如 ~/catkin_ws),它不影響ROS節點如何連接Master)

一,跨設備文件啟動

要在 PC1(運行ROS Master的PC) 上啟動 PC2(另一個PC) 的 ROS 功能包,你需要確保:

  1. PC2 的功能包已經編譯catkin_makecolcon build)。

  2. PC1 能夠訪問 PC2 的 ROS 功能包(通常通過 SSH 遠程執行命令)。

  3. PC2 的 ROS_MASTER_URI 指向 PC1 的 Master(確保節點注冊到正確的 Master)。

一般啟動方式有兩種,使用ssh啟動和roslaunch啟動

1, SSH遠程運行

最基本的就是在終端中連接到另一個PC端,然后執行終端命令

ssh <PC2_USER>@<PC2_IP> "source /opt/ros/noetic/setup.bash && source ~/catkin_ws/devel/setup.bash && rosrun <package_name> <node_name>"

例如

ssh user@192.168.1.101 "source /opt/ros/noetic/setup.bash && source ~/catkin_ws/devel/setup.bash && rosrun my_package my_node"

在文章(Python實現ssh自動連接-CSDN博客)中我們使用了Python代碼進行遠程ssh連接和命令執行,同樣的我們也可以在這里使用Python代碼執行

import paramikodef ssh_run_ros_node(host, username, password, package, node):"""通過SSH遠程執行ROS節點:param host: 遠程PC的IP地址:param username: 遠程PC的用戶名:param password: 遠程PC的密碼:param package: ROS包名:param node: 節點名"""# 創建SSH客戶端ssh = paramiko.SSHClient()ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())try:# 連接遠程主機ssh.connect(host, username=username, password=password)# 構造ROS運行命令command = f"source /opt/ros/noetic/setup.bash && source ~/catkin_ws/devel/setup.bash && rosrun {package} {node}"# 執行命令(非阻塞方式)stdin, stdout, stderr = ssh.exec_command(command, get_pty=True)print(f"已在 {host} 上啟動 {package}/{node}")# 返回SSH連接和通道,以便后續管理return ssh, stdin, stdout, stderrexcept Exception as e:print(f"SSH連接失敗: {str(e)}")ssh.close()return None, None, None, None

啟動bash文件,只需要將command替換一下即可。由于bash啟動腳本是非交互式Shell(在上一篇文章說過),所以不會加載.bashrc配置文件,為了加載運行需要的環境,需要單獨調用各條命令

def run_bash_script(ssh_client, script_path, arguments=""):"""通過SSH遠程執行bash腳本:param ssh_client: 已建立的SSH連接:param script_path: 遠程機器上的腳本路徑(如 ~/catkin_ws/scripts/start_robot.sh):param arguments: 傳遞給腳本的參數"""command = f"source /opt/ros/noetic/setup.bash && source ~/catkin_ws/devel/setup.bash && bash {script_path} {arguments}"stdin, stdout, stderr = ssh_client.exec_command(command)# 讀取輸出(可選)print(stdout.read().decode())print(stderr.read().decode())  # 如果有錯誤

如果腳本依賴 ROS 環境,需要先?source

command = ("source /opt/ros/noetic/setup.bash && ""source ~/catkin_ws/devel/setup.bash && "f"bash {script_path} {arguments}"
)
ssh.exec_command(command)

啟動Python文件,也是將command替換一下即可

def run_python_script(ssh_client, script_path, arguments=""):"""通過SSH遠程執行Python腳本:param script_path: 遠程機器上的Python腳本路徑:param arguments: 傳遞給腳本的參數"""command = f"source ~/.bashrc && python3 {script_path} {arguments}"stdin, stdout, stderr = ssh_client.exec_command(command)print(stdout.read().decode())  # 輸出print(stderr.read().decode())  # 錯誤

2,roslaunch遠程啟動

使用roslaunch啟動方式可以一次性啟動多個節點。

使用launch文件啟動有兩種方式:第一種是先要使用ssh連接后再運行command命令執行,實際上相當于在被連接端使用roslaunch命令。第二種直接使用<machine>標簽實現多機協同,無需手動調用ssh(無需手動編寫 SSH 代碼,ROS 內部自動處理遠程連接)。

第一種

import paramikodef remote_roslaunch(host, username, password, package, launch_file, args=""):"""遠程執行roslaunch:param host: 遠程PC的IP:param username: 遠程PC的用戶名:param password: 遠程PC的密碼:param package: ROS包名:param launch_file: launch文件名(不含.launch后綴):param args: 傳遞給launch文件的參數(如 "arg1:=value1 arg2:=value2")"""ssh = paramiko.SSHClient()ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())try:ssh.connect(host, username=username, password=password)# 構造roslaunch命令command = (f"source /opt/ros/noetic/setup.bash && "f"source ~/catkin_ws/devel/setup.bash && "f"roslaunch {package} {launch_file}.launch {args}")# 執行命令(非阻塞)stdin, stdout, stderr = ssh.exec_command(command, get_pty=True)print(f"已在 {host} 上啟動 {package}/{launch_file}.launch")return ssh  # 返回SSH連接,用于后續管理except Exception as e:print(f"SSH執行失敗: {str(e)}")ssh.close()return None

如果希望?roslaunch?在 SSH 斷開后繼續運行,使用?nohup:?

command = ("nohup roslaunch {package} {launch_file}.launch {args} ""> /dev/null 2>&1 &"
)

第二種?

?<machine>?標簽:定義遠程計算機的配置(IP、用戶名、密碼、環境加載腳本等)。ROS 的?roslaunch?工具會自動通過 SSH 在指定機器上啟動節點。但第一次使用時需要手動ssh連接一次你要連接的主機,連接后主機會將其自動添加到~/.ssh/kown_hosts,之后再退出ssh后,<machine>即可正常工作

<launch><!-- 定義遠程機器 pc1 --><machine name="pc1"                   <!-- 邏輯名稱(用于node的machine屬性) -->address="192.168.1.101"      <!-- 遠程IP -->user="user"                  <!-- 用戶名 -->password="pass"              <!-- 密碼(可選,建議用密鑰替代) -->env-loader="/opt/ros/noetic/env.sh"  <!-- 環境加載腳本 -->/><!-- 定義遠程機器 pc2 --><machine name="pc2" address="192.168.1.102" user="user" password="pass" env-loader="/opt/ros/noetic/env.sh" /><!-- 在 pc1 上啟動 node1 --><node machine="pc1" name="node1" pkg="your_pkg" type="node1"/><!-- 在 pc2 上啟動 node2 --><node machine="pc2" name="node2" pkg="your_pkg" type="node2"/>
</launch>

env-loader:當啟動節點時,該腳本會在指定的機器上被執行,從而設置環境變量。這意味著在啟動節點前,此腳本里的環境變量設置會生效。其主要用途是為特定節點或者一組節點設定所需的環境變量,像 ROS 工作空間的路徑、依賴庫的路徑等。?其一般內容如下

#!/bin/bash
source /opt/ros/noetic/setup.bash
source /home/ubuntu20_04/gazebo_ws/devel/setup.bash
export ROS_MASTER_URI=http://<CAR_IP_ADDRESS>:11311  # 小車IP
export ROS_HOSTNAME=<PC_IP_ADDRESS>                  # PC端IP

?

復用機器定義:用于模塊化地定義和復用遠程機器配置,并啟動對應的節點。假設你有兩臺機器人(robot1?和?robot2),需要分別在它們上面啟動相同的節點組(如導航、感知等),通過將主launch文件中定義機器配置,并引用子launch文件(定義節點邏輯),就可以實現同一個節點在不同機器上復用

<!-- 定義機器模板 -->
<group><!-- 定義一個名為robot1的遠程機器 --><machine name="robot1"                <!-- 邏輯名稱(用于后續引用) -->address="192.168.1.101"      <!-- 遠程機器的IP地址 -->user="user"                  <!-- SSH登錄用戶名 -->env-loader="~/env.sh"        <!-- 遠程機器的環境加載腳本 -->/><!-- 包含另一個launch文件,并傳遞參數 --><include file="$(find your_pkg)/launch/robot_nodes.launch"><arg name="machine" value="robot1"/>  <!-- 將machine名稱傳遞給子launch文件 --></include>
</group>

?子launch文件內容示例如下:

<launch><!-- 接收從主文件傳遞的machine名稱 --><arg name="machine"/><!-- 在指定的遠程機器上啟動節點 --><node machine="$(arg machine)" name="nav_node" pkg="your_pkg" type="nav.py"/><node machine="$(arg machine)" name="sensor_node" pkg="your_pkg" type="sensor.py"/>
</launch>

比如下面的多機器并行啟動,均使用同樣的節點?

<!-- main.launch -->
<launch><!-- 啟動robot1 --><group><machine name="robot1" address="192.168.1.101" .../><include file="robot_nodes.launch"><arg name="machine" value="robot1"/></include></group><!-- 同時啟動robot2 --><group><machine name="robot2" address="192.168.1.102" .../><include file="robot_nodes.launch"><arg name="machine" value="robot2"/></include></group>
</launch>

3,命名沖突問題

有時在不同的PC端可能需要啟動同一個功能包來分別完成對應的功能,這些功能包會發布同一個話題,但是所有設備都只有一個ROS Master,這時就會出現話題名沖突的問題和節點名沖突的問題,這時就要進行命名空間的隔離

通過為每臺PC的節點分配獨立命名空間,避免話題和節點沖突。如下所示

group結構加命名空間

<launch><!-- PC1節點放入 /PC1 命名空間 --><group ns="PC1"><node pkg="navigation_pkg" name="nav" type="nav_node" output="screen"></node></group>
</launch>
<launch><!-- PC2節點放入 /PC2 命名空間 --><group ns="PC2"><node pkg="sim_navigation_pkg" name="nav" type="nav_node" output="screen"></node></group>
</launch>

node加命名空間?

<launch><!-- 定義 PC2 --><machine name="pc2" address="192.168.1.102" user="user" password="pass"  env-loader="/opt/ros/noetic/env.sh"  <!-- PC2 的環境腳本 -->/><!-- 定義 PC3 --><machine name="pc3" address="192.168.1.103" user="user" env-loader="/opt/ros/noetic/env.sh" /><!-- 在 PC2 上運行 PC1 的節點 --><node machine="pc2" name="nav_node" pkg="navigation_pkg" type="nav_node" ns="pc2"/><!-- 在 PC3 上運行同一節點(通過命名空間隔離) --><node machine="pc3" name="nav_node" pkg="navigation_pkg" type="nav_node" ns="pc3"/>
</launch>

這樣輸出話題時就會加一個前綴,如下所示

/pc2/cmd_vel
/pc3/cmd_vel
/pc2/odom
/pc3/odom

?如果無法修改命名空間,也可以重映射話題名稱,但是話題如果很多的話這種方式就比較麻煩

<!-- PC1的Launch文件 -->
<node pkg="navigation_pkg" name="nav" type="nav_node"><remap from="cmd_vel" to="PC1_cmd_vel"/>  <!-- PC1的控制話題 -->
</node><!-- PC2的Launch文件 -->
<node pkg="sim_navigation_pkg" name="nav" type="nav_node"><remap from="cmd_vel" to="PC2_cmd_vel"/>   <!-- PC2的控制話題 -->
</node>

二,跨設備通信

我們將各PC端連接到同一個ROS Master下之后,它們的話題服務等就都是一樣的了,設備之間就可以同步發布話題,訂閱話題等進行數據之間的交換,與一個PC端各節點之間訂閱話題是一樣的

以話題為例(服務一樣)

PC1發布話題/cmd_vel

# PC1的節點
pub = rospy.Publisher('/cmd_vel', Twist, queue_size=10)

PC2訂閱同一話題

# PC2的節點
rospy.Subscriber('/cmd_vel', Twist, callback)

?三,工作空間同步

通過?rsync?將 PC1 的工作空間完整拷貝到 PC2。注意PC2 需安裝與 PC1?相同版本的 ROS 和系統依賴(如?Ubuntu 20.04 + ROS Noetic)。

# 在 PC1 上執行(同步到 PC2)
rsync -avz ~/catkin_ws/ user@192.168.1.101:~/catkin_ws/

rsync?會將 PC1 的?~/catkin_ws/?目錄(包括源代碼、編譯生成的節點和消息)同步到 PC2 的相同路徑下。PC2 的工作空間內容與 PC1?完全一致(包括編譯后的可執行文件)。PC2 可以直接運行?功能包中的節點,無需重新編譯。

# 在 PC1 上執行(將工作空間同步到 PC2)
rsync -avz --delete ~/catkin_ws/ user@192.168.1.101:~/catkin_ws/
  • 參數說明

    • -a:歸檔模式(保留權限、符號鏈接等)。

    • -v:顯示同步詳情。

    • -z:壓縮傳輸數據。

    • --delete:刪除 PC2 上多余的文件(保持嚴格一致)。

如果 PC1 修改了代碼,需重新運行?rsync?同步到 PC2,可以搭配?inotifywait?工具實現自動同步。

?除此之外,也可以僅同步必要的功能包,如下:

rsync -avz ~/catkin_ws/src/navigation_pkg/ user@192.168.1.101:~/catkin_ws/src/navigation_pkg/
# 在 PC2 上單獨編譯該包:
cd ~/catkin_ws/ && catkin_make --pkg navigation_pkg

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/75125.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/75125.shtml
英文地址,請注明出處:http://en.pswp.cn/web/75125.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于國內環境 在Ubuntu 上安裝 Docker 指南

前言 在容器化技術主導云原生時代的今天&#xff0c;Docker 憑借其輕量化、高移植性和秒級部署能力&#xff0c;已成為開發與運維的必備工具。然而&#xff0c;國內用戶在 Ubuntu 系統上安裝 Docker 時&#xff0c;常因 ?官方鏡像源訪問受限、網絡延遲高、依賴包安裝失敗 等問…

數據結構:二叉樹(三)·(重點)

二叉樹的存儲結構 ?叉樹?般可以使?兩種結構存儲&#xff0c;?種順序結構&#xff0c;?種鏈式結構。 順序結構 順序結構存儲就是使?數組來存儲&#xff0c;?般使?數組只適合表?完全?叉樹&#xff0c;因為不是完全?叉樹會有 空間的浪費&#xff0c;完全?叉樹更適合…

EasyExcel實現圖片導出功能(記錄)

背景&#xff1a;在舊系統的基礎上&#xff0c;導出一些工單信息時&#xff0c;現需要新添加處理人的簽名或者簽章&#xff0c;這就涉及圖片的上傳、下載、寫入等幾個操作。 1、EasyExcel工具類 &#xff08;1&#xff09;支持下拉框的導出。 import com.alibaba.excel.Easy…

Android Material Design 3 主題配色終極指南:XML 與 Compose 全解析

最小必要顏色配置 <!-- res/values/themes.xml --> <style name"Theme.MyApp" parent"Theme.Material3.DayNight"><!-- 基礎三原色 --><item name"colorPrimary">color/purple_500</item><item name"col…

【Git】“warning: LF will be replaced by CRLF”的解決辦法

一、原因分析 不同操作系統的換行符標準不同&#xff1a; ? Windows&#xff1a;使用 CRLF&#xff08;\r\n&#xff09;表示換行&#xff1b; ? Linux/Mac&#xff1a;使用 LF&#xff08;\n&#xff09;表示換行 Git 檢測到本地文件的換行符與倉庫設置或目標平臺不兼容時…

PyTorch 深度學習實戰(33):聯邦學習與隱私保護

在上一篇文章中,我們探討了多模態學習與CLIP模型的應用。本文將深入介紹聯邦學習(Federated Learning)這一新興的分布式機器學習范式,它能夠在保護數據隱私的前提下實現多方協作的模型訓練。我們將使用PyTorch實現一個基礎的聯邦學習框架,并在圖像分類任務上進行驗證。 一…

藍橋杯 web 展開你的扇子(css3)

普通答案&#xff1a; #box:hover #item1{transform: rotate(-60deg); } #box:hover #item2{transform: rotate(-50deg); } #box:hover #item3{transform: rotate(-40deg); } #box:hover #item4{transform: rotate(-30deg); } #box:hover #item5{transform: rotate(-20deg); }…

LLM驅動的智能體:基于GPT的對話智能體開發指南

前言 大語言模型&#xff08;LLM, Large Language Model&#xff09;正在徹底改變智能體&#xff08;Agent&#xff09;的設計和實現方式。從簡單的聊天機器人到復雜的自動化助手&#xff0c;基于GPT等LLM的對話智能體已經在客服、教育、辦公自動化、編程助手等領域得到了廣泛…

深度解析 C# 中介者模式:設計與實戰應用

中介者模式&#xff08;Mediator Pattern&#xff09;是一種行為型設計模式&#xff0c;其核心思想是將多個對象之間的交互集中到一個中介者對象中&#xff0c;從而減少對象之間的直接交互&#xff0c;降低耦合度。在實現復雜系統時&#xff0c;中介者模式有助于提高系統的可維…

每日算法-250408

記錄今天解決的兩道 LeetCode 算法題&#xff0c;主要涉及二分查找的應用。 1283. 使結果不超過閾值的最小除數 題目描述 思路 核心思路是 二分查找。 解題過程 為什么可以使用二分&#xff1f; 關鍵在于單調性。對于一個固定的數組 nums&#xff0c;當除數 divisor 增大時&…

MySQL的子查詢

一、前言 MySQL 子查詢是指嵌套在其他 SQL 語句&#xff08;如 SELECT、WHERE、FROM 等&#xff09;內部的查詢。用于輔助主查詢完成復雜的數據篩選或計算。 二、子查詢分類 標量子查詢 描述&#xff1a;返回 單行單列&#xff08;一個值&#xff09;&#xff0c;常用于比較運…

Linux 基礎入門操作 前言 VIM的基本操作 2

1 VIM的背景介紹 Vi 的誕生與1976年&#xff0c;Vim 的前身是 Vi&#xff08;Visual Editor&#xff09;&#xff0c;由 Bill Joy 在 BSD Unix 系統上開發&#xff0c;作為 ed&#xff08;行編輯器&#xff09;的改進版本&#xff0c;提供全屏編輯功能&#xff0c;成為 Unix/L…

Java:Set操作

目錄 Set 轉 List Set 轉 List Set<String>set new HashSet<String>(); set.add("c"); set.add("d"); set.add("a"); set.add("a");//方法一&#xff1a; List<String>list new ArrayList<String>(set);//…

算力驅動未來:從邊緣計算到高階AI的算力革命

算力驅動未來&#xff1a;從邊緣計算到高階AI的算力革命 摘要 本文深入探討了不同算力水平&#xff08;20TOPS至160TOPS&#xff09;在人工智能領域的多樣化應用場景。從邊緣計算的實時目標檢測到自動駕駛的多傳感器融合&#xff0c;從自然語言處理的大模型應用到AI for Scie…

虛擬機上安裝openEuler和openGauss數據庫

1.虛擬機版本選擇VM 16 PRO 2.openEuler版本選擇openEuler-22.03-LTS-SP4-x86_64 下載地址&#xff1a;https://mirrors.aliyun.com/openeuler/openEuler-22.03-LTS-SP4/ISO/x86_64/openEuler-22.03-LTS-SP4-x86_64-dvd.iso 3.虛擬機安裝openEuler過程&#xff1a; 4.安裝ope…

0_Pytorch中的張量操作

[引言]張量的概念 1.基本概念 張量是一個通用的多維數組&#xff0c;可以表示標量&#xff08;0 維&#xff09;、向量&#xff08;1 維&#xff09;、矩陣&#xff08;2 維&#xff09;以及更高維度的數據。張量是 PyTorch 中的核心數據結構&#xff0c;用于表示和操作數據。…

LS-LINUX-002 簡易創建SSH

LS-LINUX-002 簡易創建SSH 1. CentOS 8 創建和配置SSH服務 1.1 安裝SSH服務 CentOS 8 默認已經安裝了OpenSSH服務。如果沒有安裝&#xff0c;可以使用以下命令安裝&#xff1a; sudo dnf install -y openssh-server1.2 啟動SSH服務 安裝完成后&#xff0c;需要啟動SSH服務…

計算機專業求職面試的常見題目分類整理

以下是計算機專業求職面試的常見題目分類整理&#xff0c;每個大類精選20道高頻問題&#xff0c;結合參考內容進行解析與擴展&#xff0c;幫助系統化備考&#xff1a; 一、數據結構與算法 解釋時間復雜度和空間復雜度 時間復雜度衡量算法執行時間隨輸入規模的增長趨勢&#xf…

腳本啟動 Java 程序

如果你想在后臺啟動一個 Java 程序&#xff0c;并在終端窗口中顯示一個自定義的名字&#xff0c;可以通過編寫一個簡單的腳本來實現。以下是一個基于 Linux/macOS 的解決方案&#xff0c;使用 Bash 腳本啟動 Java 程序&#xff0c;并在終端窗口中顯示自定義標題。 示例腳本 創建…

CentOS禁用nouveau驅動

1、驗證 nouveau 是否在運行 lsmod | grep nouveau如果命令返回結果&#xff0c;說明 nouveau 驅動正在運行。 2、編輯黑名單文件 通過編輯黑名單配置文件來禁用 nouveau 驅動&#xff0c;這樣在系統啟動時不會加載它。 vi /etc/modprobe.d/blacklist-nouveau.conf修改以下…