当前位置: 首页 > news >正文

ROS Master多设备连接

Bash Shell

Shell是位于用户与操作系统内核之间的桥梁,当用户在终端敲入命令后,这些输入首先会进入内核中的tty子系统,TTY子系统负责捕获并处理终端的输入输出流,确保数据正确无误的在终端和系统内核之中。Shell在此过程不仅仅是一个监听者,还会积极地从tty子系统读取用户的命令输入,并对其进行解析来识别用户意图(比如当你输入ls时,是Shell解析这个命令并调用/bin/ls文件的来直接解析)。Bash Shell(基础 shell)是 Linux/Unix 系统中用户与操作系统内核交互的基本命令行界面,它是系统启动后为用户提供的默认命令解释器环境

Bash和Shell其实是包含关系。Shell是命令行解释器的统称 ,有Bash、Zsh、Fish、Dash等多种命令行解释器,Bash是Shell的最流行方式,Ubuntu系统默认使用的也是Bash,当然你可以通过在终端中输入特定命令行可以切换(一般这几种命令行解释器的命令是兼容的,但是存在一些语法和交互功能的差异),一般使用Bash就足够了。

Bash Shell与终端不同点:Bash Shell是命令行解释器程序,终端则是输入输出设备/界面。可以理解为终端是"显示器+键盘",而Bash是运行在这个显示器上的"智能程序"。一般的执行流程是-------你在终端输入命令 → 终端将输入传给Shell → Shell解释执行 → 结果返回终端显示

交互式Shell与非交互式Shell 

 简单来说,交互式Shell用户可以 直接输入命令 并 实时看到输出 的 Shell,会显示 PS1 提示符(如 user@host:~$),等待用户输入。比较常见的场景:1,直接打开终端 2,通过 SSH 登录后手动操作(如 ssh user@192.168.1.1 后进入 Shell3,手动运行 bash -i(强制交互模式)

非交互式Shell,不等待用户输入,直接执行 单条命令 后退出,所以说一般是看不到的,不会显示 PS1 提示符,执行完命令后立即关闭。比较常见的场景:1,通过 ssh user@host "command" 远程执行命令。2,使用 Python paramiko.exec_command("command")。3,运行 Shell 脚本(如 bash script.sh),如果输入bash -i script.sh会强制交互式

登录式Shell和非登录式Shell

登录式 Shell 的关键特征是:

  1. 以用户身份初始化完整的登录会话(加载登录配置文件,如 ~/.bash_profile)。

  2. 通常出现在系统首次登录时(如 SSH 登录、本地终端登录、su - username)。

.sh脚本文件

我们平常为了方便而写的脚本文件,实际上就是一个纯文本文件,包含一系列 Shell 命令(如 Bash、Zsh 等支持的语法),将需要手动逐条输入的命令,预先整体写入文件,实现 自动化执行。比如,以下脚本文件(文件名demo.sh),Shell解析器就会一行一行的解析每一行(即每一条)内容。

#!/bin/bash
echo "Hello World"
ls -l
date

执行的.sh文件的方式有以下几种

  1. bash demo.sh:显式指定解释器(bash),启动一个新的子 Shell 进程来执行脚本。直接调用 /bin/bash 程序,将 demo.sh 作为参数传递给它,忽略 Shebang 行(即首行的#!/bin/bash)
  2. ./demo.sh:依赖脚本首行的 Shebang(如 #!/bin/bash)。与bash的区别还有重要的一点就是bash demo.sh不需要赋予文件执行权限,而./demo.sh必须赋予文件执行权限
  3. source demo.sh(也可以简写为. demo.sh):不启动子Shell,直接在当前 Shell 进程中逐行执行脚本,并且会忽视Shebang。脚本中定义的变量、函数、别名等会影响当前 Shell。而前两种执行方式脚本中定义的变量、函数不会影响当前 Shell 环境。一般用于加载环境配置,比如
# 加载环境配置(如 ~/.bashrc)
source ~/.bashrc# 脚本中修改当前 Shell 的工作目录
source change_dir.sh  # 脚本内容: cd /some/path

在交互式Shell和非交互式Shell说到过,bash  运行Shell脚本时会启动一个非交互式Shell,也就是启动一个新的子Shell来运行这个脚本,并且这个子Shell进程是非交互式的Shell,执行完毕后,控制权返回给父 Shell。而source不会启动子Shell,所以说它会在当前的交互式Shell运行。

.bashrc文件

.bashrc 文件是 Linux 系统中非常重要的配置文件,它与是否安装 ROS 无关,是 Bash shell的标准配置文件(它是一个纯文本文件,使用 Bash 语法 编写),"rc" 通常代表 "run commands" (运行命令)。文件名中的点(.)表示它是隐藏文件,在Linux系统用户主目录下,按ctrl+h键可以显示隐藏文件。

.bashrc的内容语法(完全遵循Bash语法):

  1. export PATH="$PATH:/my/custom/path" 变量定义。用来设置环境变量,影响所有子进程
  2. alias ll='ls -alF' 起别名,在终端输入ll就相当于输入ls -alF
  3. greet() { echo "Hello, $USER!"; } 函数定义
  4. if [ -d ~/projects ]; then
      echo "Projects directory exists"
    fi   条件循环判断

.bashrc如何运行?

当启动非登录的交互式 Bash shell 时,打开新的终端时,通过bash命令启动新的Shell时,.bashrc文件都会自动启动

必须需要注意的是在非交互式Shell中默认不会自动加载.bashrc,也就是说你在使用bash执行脚本时在新打开的Shell子进程中不会加载.bashrc也就不会启动对应的环境(但是子进程会继承父进程的环境变量)。在交互式Shell中默认会加载.bashrc(因为 ~/.bash_profile 或 ~/.profile 通常会显式调用 .bashrc)。登录式Shell会加载 ~/.bash_profile 或 ~/.profile,~/.bash_profile 或 ~/.profile 通常会显式调用 .bashrc所以.bashrc也会自动调用。非登录式Shell不会加载配置文件。

其实在非交互式Shell不会自动加载.bashrc,这是因为.bashrc的开头有以下代码。这表示:仅当Shell是交互式时,才继续执行后续内容。非交互式Shell会直接return退出,也就是说即使你在非交互式Shell单独调用source ~/.bashrc,也不会加载.bashrc的配置内容。这是为了避免用户自定义配置影响自动化任务而设置的,为了安全起见也不要试图去修改它!!!

case $- in*i*) ;;*) return;;
esac

除此之外还有.bash_profile和.profile文件。.bashrc在非登录的交互式Bash Shell(不需要重新认证的子会话,如图形终端新建窗口、bash 命令启动等,直接继承父 Shell 的环境变量)自动加载;.bash_profile在Bash登录Shell(需要用户认证的完整会话,如系统登录、SSH 连接等,全新环境(会重新读取配置))自动加载,也就是说.bash_profile登录时一次性设置。.profile是在所有Shell的登录会话都会加载,但是前提是.bash_profile不存在。也就是说只有在用户使用Bash并且存在./bash_profile时才会跳过.profile的加载,如果用户使用其他命令解释器则会自动加载.profile,所以说.profile是跨 Shell 的通用环境变量。

1,网络配置

确保所有设备(PC端,嵌入式端等等)连接在同一个局域网下,在每台设备的终端输入ifconfig查看IP地址,由于不同网络下IP地址经常改变,所有推荐将每台设备设置为静态IP地址。

使用ping命令测试各PC之间的连通性,如果都能ping通后就可以开始下一步了

2,环境变量配置

在所有PC上编辑~/.bashrc文件,添加以下环境变量:

export ROS_MASTER_URI=http://<master_ip>:11311  # 主机的IP地址。ROS 默认使用 11311 端口 作为 roscore 的通信端口,这是由 ROS 的设计者设定的标准配置。
export ROS_IP=<local_ip>  # 本机的IP地址
export ROS_HOSTNAME=<local_ip>  # 本机的IP地址

然后执行

source ~/.bashrc

3,主机名解析

主机名解析就是将上面的ROS_MASTER_URI=http://<master_ip>:11311中的master_ip用一个名字来代替,比如master-pc=192.168.1.1,这时只需要将192.168.1.1替换为master-pc即可,类似于变量赋值。当然,你也可以直接输入为192.168.1.1而不需要主机解析,但是这样的话如果主机的ip地址频繁变换,就需要在每个从机的./bashrc中重新修改主机的ip地址,从机数量少的话还可以,从机数量多的话就会很麻烦。

主机名解析的实现方式一般有以下几种:

1,使用/etc/hosts文件:

首先,在所有参与ROS通信的计算机上编辑/etc/hosts文件,添加所有ROS计算机的IP和主机名映射,格式如下:

192.168.1.100   master-pc
192.168.1.101   slave1-pc
192.168.1.102   slave2-pc

保存文件后测试解析:

ping master-pc
ping slave1-pc

 但是这种方式看起来是使用了主机解析,但它只是增强了可读性,而没有解决频繁手动修改IP的缺点,如果 Master 的 IP 地址变了,还是需要手动修改所有从机的/etc/hosts文件的配置

 2,使用DNS:

DNS一般是用于学校或者企业,适用于本地有DNS服务器或路由器支持DNS绑定的场景

在路由器或 DNS 服务器上,将主机名(如 master-pc)绑定到 Master 的 IP。所有从机自动通过 DNS 解析 master-pc,无需手动改 IP。这样IP地址变动时,只需改DNS记录所有从机自动生效

 3,使用mDNS:

适用于小型网络,如实验室或者家用

确保所有机器安装 avahi-daemon(Linux 默认通常已安装):

sudo apt install avahi-daemon  # Ubuntu/Debian

直接使用 .local 主机名(无需配置 /etc/hosts):

export ROS_MASTER_URI=http://master-pc.local:11311

4,使用静态DHCP绑定:

适用于家用/实验室路由器支持DHCP静态绑定的场景

在路由器后台,将 Master 的 MAC 地址绑定到一个固定 IP(如 192.168.1.100)。所有从机直接用这个 IP,因为 Master 的 IP 永远不会变

4,防火墙配置

UFW(Uncomplicated Firewall)是一款基于 iptables 的简单易用的防火墙配置工具,广泛应用于基于 Debian 和 Ubuntu 的 Linux 系统中,用于管理和配置网络防火墙规则。UFW 支持允许或拒绝特定的网络连接。即使系统中没有安装 UFW,也不意味着没有防火墙阻拦网络连接。UFW 只是一个简化的防火墙管理工具,而在 Linux 系统中,底层的防火墙功能通常由 iptables 或 nftables 实现(iptables 是 Linux 系统中强大的防火墙配置工具,但它的命令复杂,规则编写难度较大,对普通用户不太友好。UFW 则提供了一种简化的接口,使用户可以用更直观、简洁的命令来管理防火墙规则,比如,启用防火墙只需执行sudo ufw enable,而使用 iptables 则需要编写多条复杂的命令)。

先使用命令查看防火墙配置工具ufw是否安装

dpkg -l | grep ufw

如果 ufw 已经安装,会显示相关的软件包信息;如果没有任何输出,说明 ufw 未安装。此时需要输入命令进行安装:

sudo apt update
sudo apt install ufw

安装后查看防火墙活跃状态

 sudo ufw status

如果输出Status: inactive,表示防火墙处于未启用状态,网络端口处于相对开放状态,外界可以直接访问系统暴露的端口。

如果防火墙处于活跃状态,则需要确保所有PC的防火墙允许ROS通信(默认端口11311)

sudo ufw allow 11311/tcp

就能允许外部设备通过 22 端口(通常用于 SSH 服务)访问本地系统 

 5,测试连接

在主PC上启动ROS Master:

roscore

在其他PC上测试连接:

rostopic list

如果连接成功,会显示 Master 上已发布的 Topic 列表。如果 Master 刚启动 roscore,默认只有 /rosout 和 /rosout_agg

$ rostopic list
/rosout
/rosout_agg

6,同步时间

需要时可以选用此功能

在ROS多机通信中,时间同步(Time Synchronization)是一个关键但容易被忽视的配置。指的是让所有参与ROS通信的计算机保持高度一致的系统时间(最好误差在毫秒级)。

通常使用NTP来实现时间同步 :

 NTP是一种网络协议,用于同步计算机的系统时间,计算机通过NTP客户端从时间服务器(如ntp.ubuntu.com)获取精确时间,局域网内通常可达毫秒级同步

 基本原理

NTP(Network Time Protocol)实现时间同步的原理是一个分层、多源校正的精密时间同步体系,其核心设计目标是在不可靠的网络环境中实现高精度的时间同步(局域网内通常可达毫秒级,理想条件下可达亚毫秒级)。

NTP采用层级化的时间源结构,类似于金字塔:

  • Stratum 0
    最顶层,直接连接原子钟、GPS或铯钟等高精度物理时钟设备,不直接参与网络通信

    • 示例:实验室原子钟、卫星时间信号。

  • Stratum 1
    直接与Stratum 0设备同步的NTP服务器(时间误差通常<100μs)。

    • 示例:国家授时中心服务器、Google的time.google.com

  • Stratum 2
    从Stratum 1同步的服务器,误差逐层递增(每层增加约1ms)。

    • 示例:企业级NTP服务器、公共NTP池(如pool.ntp.org)。

  • Stratum 3及以下
    更低层级的同步节点,适用于普通客户端设备。

NTP通过以下四个时间戳计算时间偏差(Clock Offset)和网络延迟(Round-Trip Delay):

假设客户端(A)与服务器(B)交互:

  1. T₁:客户端发送请求时的本地时间(A的时钟)。

  2. T₂:服务器收到请求时的本地时间(B的时钟)。

  3. T₃:服务器回复响应时的本地时间(B的时钟)。

  4. T₄:客户端收到响应时的本地时间(A的时钟)。

 最终时间偏差是多次测量的统计结果(通常采用最小二乘法Marzullo算法过滤异常值)。

中国的NTP服务架构是分层级的,国家授时中心是stratum1,其他运营商比如阿里云,腾讯云等部署了多台次级服务器。所以你执行命令时会使自己的PC端自动连接到附近最优的服务器,由于所有的NTP服务器本身已经同步(都溯源到国家授时中心或GPS/原子钟) ,所以连接了NTP的各个服务器就可以实现同步。

比如下面的方式一就是将其连接到了最优的服务器,但是如果你需要更高的精度,还可以指定同一NTP服务器,这时就需要在文件/etc/systemd/timesyncd.conf,添加如下内容指定特定服务器(比如阿里云)

[Time]
NTP=ntp.aliyun.com

实现方式(Ubuntu系统)

方法一:使用系统默认的timesyncd(使用简单)

如果使用 systemd-timesyncd(即 timedatectl 管理的 NTP 客户端),通常不需要额外安装 ntp 或 ntpdate,因为 timesyncd 已经是一个轻量级的 NTP 客户端,默认集成在 systemd 中。

# 检查当前同步状态
timedatectl status# 如果未启用NTP,运行:
sudo timedatectl set-ntp on# 手动强制同步
sudo systemctl restart systemd-timesyncd

方法二:安装完成的ntp包(更精确控制)

sudo apt install ntp
sudo systemctl restart ntp  # 启动或重启 NTP 服务,立即应用配置并开始同步。# 查看同步状态
ntpq -p

ntpq -p输出示例如下

   remote           refid      st t when poll reach   delay   offset  jitter
============================================================================
*ntp.ubuntu.com  .POOL.          16 u   25   64    1    5.123   -0.432   0.871
+time.google.com .GOOG.           1 u   12   64    7    1.234    0.567   0.123
  • * 表示当前主同步源。

  • offset:本地时钟与服务器的偏差(单位:毫秒)。

  • jitter:网络延迟的波动程度。

验证时间同步:

ntpdate -q 192.168.1.100  # 查询与某台机器的时间差

 7,共享ROS包

此功能如果需要可以选用,不做详细解释

方法1:同步工作空间

  • 使用rsync或git同步工作空间

  • 确保所有PC上的包路径相同

方法2:NFS共享

  • 设置NFS服务器共享工作空间

  • 其他PC挂载该共享目录

方法3:独立编译

  • 在各PC上独立维护代码库

  • 确保版本一致

 8,启动管理

可以使用roslaunch在多台机器上启动节点:

<launch><machine name="pc1" address="192.168.1.101" user="user" password="pass" env-loader="/opt/ros/noetic/env.sh"/><machine name="pc2" address="192.168.1.102" user="user" password="pass" env-loader="/opt/ros/noetic/env.sh"/><node machine="pc1" name="node1" pkg="your_pkg" type="node1"/><node machine="pc2" name="node2" pkg="your_pkg" type="node2"/>
</launch>


http://www.mrgr.cn/news/97264.html

相关文章:

  • 【计算机网络】Linux配置SNAT策略
  • Kubernetes 集群搭建(一):k8s 从环境准备到 Calico 网络插件部署(1.16版本)
  • T113s3远程部署Qt应用(dropbear)
  • 通过枚举、AOP、注解、反射填充公共字段
  • 在线记事本——支持Markdown
  • JavaScript基础--01-JS简介
  • 数据蒸馏:Dataset Distillation by Matching Training Trajectories 论文翻译和理解
  • 【Python基础】循环语句(2215字)
  • DDPM 做了什么
  • Go语言-初学者日记(七):用 Go 写一个 RESTful API 服务!
  • JavaScript基础--09-流程控制语句:选择结构(if和switch)
  • Windows 安装和使用 ElasticSearch
  • Python实现ssh自动连接
  • 【双维畅聊】网页版聊天室测试报告
  • 服务器磁盘io性能监控和优化
  • 道路裂缝数据集CrackForest-156-labelme
  • 3D图像重建中Bundle Adjustment的推导与实现
  • 【Python爬虫高级技巧】BeautifulSoup高级教程:数据抓取、性能调优、反爬策略,全方位提升爬虫技能!
  • 001 vue
  • Springboot切换到3.3.4后,使用spring security一些小问题记录