ROS2 默认使用的通信中间件是DDS。
DDS基于Domain ID在一个物理网络内切分为若干逻辑网络。
在同一域(domain)中的ROS 2节点可以被自由发现并通信,在不同域中则不能互通。
所有的ROS 2节点默认使用domain ID 0。
为避免消息混淆,同网络内运行ROS 2的不同组的设备应该使用不同的domain ID1。
ROS_DOMAIN_ID有两种(short version / long version)。
正常使用推荐short version,在[0, 101]之间进行选择即可。
long version则可以在[0, 232]之间进行选择。
每个ROS节点在DDS中被称为参与者(participant)。默认情况下,每个Domain Participant需要打开四个UDP/IP端口:其中两个端口是组播端口,在同一个DomainId的所有Domain Participant之间共享;另外两个是单播端口,对于计算机中的每个参与者都不相同。
根据DDS-RTPS规范,用于发现的组播的IP地址默认为239.255.0.1。
在DDS中,端口号由DDS的domain ID以及通信域中的参与者数量决定。包括:
Multicast Ports (通常用于基于同一domainID的所有应用的广播通信):
DiscoveryMulticastPort = PB + DG * domainId + d0
UserMulticastPort = PB + DG * domainId + d2
Unicast Ports (对每个参与者不同,用于点对点通信):
DiscoveryUnicastPort = PB + DG * domainId + d1 + PG * participantId
UserUnicastPort = PB + DG * domainId + d3 + PG * participantId
上述公式依赖于两个变量 domainId和participantId
domainId DDS的Domain ID
participantId 从0开始的的参与者的编码,在一个操作系统(虚拟机或者实际的计算机)内进行排序给出;
第一个参与者为0,第二个为1,以此类推。
公式还涉及到一些常量,遵循OMG的DDS-RTPS标准,常量如下:
d0 (builtin_multicast_port_offset) = 0
d2 (user_multicast_port_offset) = 1
d1 (builtin_unicast_port_offset) = 10
d3 (user_unicast_port_offset) = 11
PB (port_base) = 7400
DG ( domain_id_gain) = 250
PG (participant_id_gain) = 2
注意:
按照上述公式,我们可以算出当participant Id到达120时,两个UnicastPort会与下一个domain ID的MulticastPort重叠,我们在使用时要注意ID的重叠情况。
如果您不能确定局域网内的domainId的情况,请不要在一个Domain中使用超过120个[0, 119]的节点。
在domainId=0下进行运行,如果我们的计算机中有两个参与者,则使用的端口如下:
所有节点共用
DiscoveryMulticastPort = 7400
UserMulticastPort = 7401
第一个ROS节点
DiscoveryUnicastPort = 7410
UserUnicastPort = 7411
第二个ROS节点
DiscoveryUnicastPort = 7412
UserUnicastPort = 7413
如果我们在domainId=0上进行通信,那么UDP端口范围[7400, 7649]将可以映射到各参与者使用。
其中7400是participantId=0使用的最低端口,7649是participantId=119使用的最高端口。
如果我们再domainId=10上通信,那么相应的UDP端口范围则为[9900, 10149]。
基于上述,为了使DDS在不同系统中获得兼容性,选择域ID时应遵循附加于平台的一些约束。特别要注意避免在操作系统的临时端口范围分配domain Id,从而避免ROS 2节点使用的端口与计算机上其他网络服务冲突。
Linux
默认情况下,Linux内核使用端口32768-60999作为临时端口。
这意味我们可以安全地使用的domain id范围是[0-101]和[215-232]。
当然,如果有需要,在Linux中,可以通过在/proc/sys/net/ipv4/ip_local_port_range中调整临时端口范围。
macOS
默认情况下,macOS上的临时端口范围为49152 ~ 65535。
这意味着可以安全地使用的domain id的范围是[0-166]。
通过设置net.inet.ip.portrange.first和net.inet.ip.portrange.last的自定义sysctl值,可以在macOS中配置临时端口范围。
Windows
Windows系统默认的临时端口范围与macOS一致,为49152 ~ 65535。
这意味着可以安全地使用的domain id的范围是[0-166]。
临时端口范围可以在Windows中使用netsh进行配置。 如果使用自定义临时端口范围,则可能需要相应地调整上述数字。
基于上述限制,若我们要构建跨平台的ROS网络,则可选择的domain ID范围应该是[0, 101]。
对计算机上运行的每个ROS 2节点,将创建一个DDS participant。
由于每个DDS参与者都使用了计算机上的两个端口,因此在一台计算机上运行超过120个ROS 2进程可能会溢出到其他域id所对应的端口,或系统临时端口。
例如,我们考虑domain ID 1和2:
当然,若我们在计算机上一次仅使用一个domain ID,且这个domain ID取的是一个较小的值,那么我们就可以使用超过120个的ROS2节点。
当我们选择了一个接近平台限制上限的domain ID,那么我们需要考虑一些额外的限制。
例如,我们考虑在Linux平台上使用domain ID 101
因此,在Linux上,当我们使用domain ID 101时,最多只能使用54个ROS2 节点。
在macOS和Windows上也是同样的情况,仅仅是数字可能不同。当我们选择domain ID 166时,ROS 2的最大进程数不要超过120,以免同预留端口冲突。