1
0
forked from zbw/yiliao2026
Files
yiliao2026/docs/crucial_change/2026-07-23-fastdds-164-network-change.md

1063 lines
38 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Fast DDS `.164` 专用链路设计与回滚规格
- 日期2026-07-23
- 适用环境RDKx5ROS 2 Humble与 WSLROS 2 Humble
- ROS Domain`22`
- 状态设计已确认DDS 配置尚未部署
## 1. 目标
将 WSL 与 RDKx5 之间的 ROS 2/DDS 数据固定在以下链路:
```text
WSL 192.168.10.151 <-> RDKx5 192.168.10.164 (wlx200db0c3fca5)
```
RDKx5 的 `192.168.10.210``wlan0`)继续用于 SSH 和 VS Code不承担 WSL 与 RDKx5 之间的 DDS 数据。
本次不开发 `obstacle_nav_web`,只优化 DDS 网络选择。
## 2. 已确认的现状
### RDKx5
- 主机:`sunrise@192.168.10.210`
- ROS 2Humble
- 默认 RMW`rmw_fastrtps_cpp`
- `~/.bashrc` 已设置 `ROS_DOMAIN_ID=22`
- DDS 专用网卡:`wlx200db0c3fca5`,地址 `192.168.10.164/24`
- 管理网卡:`wlan0`,地址 `192.168.10.210/24`
- 两张网卡处于同一子网,普通路由优先级为 `.210` 的 metric 600、`.164` 的 metric 601。因此不能依赖普通路由保证 DDS 使用 `.164`
### WSL
- 用户:`hikos`
- 默认 RMW`rmw_fastrtps_cpp`
- ROS 2 接口:`eth4`,地址 `192.168.10.151/24`
-`.164``.210` 均经 `eth4` 直连
- WSL 端配置必须放在 `/home/hikos/Yiliao2026/`
## 3. 采用方案
继续使用 Fast DDS不修改系统路由、网卡 metric 或防火墙。双方通过 Fast DDS 默认 participant profile 显式选择接口,并设置对端 discovery peer。
### 跨主机 UDP
- RDKx5 的自定义 UDPv4 transport 只允许本地地址 `192.168.10.164`
- WSL 的自定义 UDPv4 transport 只允许本地地址 `192.168.10.151`
- RDKx5 discovery peer 指向 `192.168.10.151`
- WSL discovery peer 指向 `192.168.10.164`
- 不对单个 DDS 端口做端口转发DDS 发现和数据端口由 Fast DDS 按 Domain 和 participant 管理。
### 同主机通信
配置保留 SHM transport。RDKx5 内部 ROS 节点之间及 WSL 内部 ROS 节点之间优先使用共享内存,避免将同主机的大流量消息无意义地送入无线链路。
### 生效范围
只有从指定环境脚本启动的 ROS 2 participant 才受该配置约束。为保证实际 Nav2 数据都走 `.164`RDKx5 的底盘、雷达、`obstacle_scanner` 和 Nav2 必须从同一个已加载 RDK 环境脚本的终端或其子进程启动WSL 现有软件必须从已加载 WSL 环境脚本的终端或其子进程启动。
## 4. 计划新增文件
### RDKx5
```text
/home/sunrise/yiliao_ws/config/dds/fastdds_rdk_164.xml
/home/sunrise/yiliao_ws/config/dds/use_rdk_dds_164.sh
```
### WSL
```text
/home/hikos/Yiliao2026/config/dds/fastdds_wsl_151.xml
/home/hikos/Yiliao2026/config/dds/use_wsl_dds_164_link.sh
```
### 变更与回滚记录
```text
/home/sunrise/yiliao_ws/docs/crucial_change/2026-07-23-fastdds-164-network-change.md
```
当前设计规格即保存在上述变更文档中。实施时必须在同一文档中追加实际文件内容、执行命令、验证结果、文件校验值和回滚结果,不另建无法互相对应的零散说明。
## 5. 环境脚本行为
两个脚本均设计为由 Bash `source` 加载,不作为独立子进程执行。
脚本必须:
1. 检查当前主机是否存在预期的本地 IP不存在时输出明确错误并返回非零。
2. 检查 XML 文件存在且可读。
3. 设置 `ROS_DOMAIN_ID=22`
4. 设置 `RMW_IMPLEMENTATION=rmw_fastrtps_cpp`
5. 将 Humble 使用的 `FASTRTPS_DEFAULT_PROFILES_FILE` 指向对应 XML如当前 Fast DDS 同时支持新变量,则将 `FASTDDS_DEFAULT_PROFILES_FILE` 指向同一文件。
6. 输出本次选择的 Domain、RMW、配置文件和本地 DDS 地址,便于启动前人工核对。
7. 不修改 `~/.bashrc``~/.profile` 或系统服务环境。
## 6. 使用流程
### RDKx5
```bash
source /opt/ros/humble/setup.bash
source /home/sunrise/yiliao_ws/install/setup.bash
source /home/sunrise/yiliao_ws/config/dds/use_rdk_dds_164.sh
ros2 launch obstacle_nav2 obstacle_nav2.launch.py
```
### WSL
```bash
source /opt/ros/humble/setup.bash
source /home/hikos/Yiliao2026/config/dds/use_wsl_dds_164_link.sh
# 在同一终端启动现有软件
```
## 7. 精简验证
实施后只执行以下必要验证:
1. 双端加载环境脚本,确认本地 IP、XML、`ROS_DOMAIN_ID=22``rmw_fastrtps_cpp` 正确。
2. 使用唯一命名的临时 ROS 2 话题验证 WSL 与 RDKx5 能互相发现并收发消息。
3. 从该环境启动实际 `ros2 launch`,确认 WSL 能看到关键话题;观察 DDS 数据经过 `.164``.210` 上的 SSH 保持正常,并且没有 WSL 相关 DDS 数据使用 `.210`
验证记录应包含执行命令、成功或失败、关键输出摘要。无需进行长时间带宽统计、完整 Nav2 功能回归或 costmap 性能调优。
## 8. 失败保护和回滚
### 快速回滚
1. 停止从专用 DDS 环境启动的 ROS 2 节点。
2. 关闭已加载环境脚本的终端,或在当前终端取消 DDS 配置变量。
3. 新开终端,仅加载原有 ROS 2 和工作空间环境,然后按原命令重新启动。
4. 验证默认 ROS graph 恢复。
### 文件级回滚
配置验证失败且不再保留时,只删除本规格第 4 节列出的四个新增配置文件;如果目录为空,再删除新增的 `config/dds` 目录。不得删除工作空间、现有 package、路由表或其他用户文件。
实施文档必须记录精确的删除命令。在执行删除前,应再次解析并核对绝对路径分别位于:
- `/home/sunrise/yiliao_ws/config/dds/`
- `/home/hikos/Yiliao2026/config/dds/`
### 不需要回滚的项目
因为本方案不修改以下项目,所以回滚不得操作它们:
- RDKx5 与 WSL 的路由表
- 防火墙规则
- 网卡 metric
- `~/.bashrc``~/.profile`
- `obstacle_nav2``obstacle_scanner` 和其他 ROS package
- SSH 与 VS Code 配置
## 9. 变更记录要求
实施时,本文件必须追加:
- 每个新增文件的绝对路径与完整内容
- 修改前的网络和 ROS 环境摘要
- 实际执行命令及执行顺序
- 每项精简验证的结果
- 新增文件的 SHA-256
- 完整回滚命令
- 若发生失败,失败现象、停止位置以及是否已回滚
如果实施内容与本设计不一致,必须先在本文件记录差异及原因,再执行该项变更。
## 10. 验收标准
- WSL 与 RDKx5 在 Domain 22 中能发现并收发 ROS 2 消息。
- 由专用环境启动的跨主机 DDS 通信只使用 WSL `.151` 与 RDKx5 `.164`
- `.210` 上的 SSH 和 VS Code 管理链路保持可用。
- 未修改路由表、系统启动文件、现有 ROS package 或 Nav2 参数。
- 所有实际修改、验证和回滚方式均记录在本文件中。
# Fast DDS `.164` 专用链路实施计划
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 让从专用环境启动的 WSL 与 RDKx5 ROS 2 participant 只通过 `.151 <-> .164` 交换跨主机 DDS 数据,同时保持 `.210` 的管理链路不变。
**Architecture:** 双端保持 `rmw_fastrtps_cpp` 和 Domain 22分别加载一个 Fast DDS 默认 participant profile。profile 保留 SHM 供同主机通信,并用带接口白名单的自定义 UDPv4 transport 约束跨主机通信sourceable Bash 脚本负责前置检查和环境变量设置。
**Tech Stack:** ROS 2 Humble、Fast DDS 2.6.x、Bash、Fast DDS XML profiles、`tcpdump`、Git。
---
## 文件职责
- `/home/sunrise/yiliao_ws/config/dds/fastdds_rdk_164.xml`RDKx5 participant transport只允许 UDPv4 使用 `.164`peer 为 WSL `.151`
- `/home/sunrise/yiliao_ws/config/dds/use_rdk_dds_164.sh`:验证 RDKx5 网卡和 XML 后,导出 Domain、RMW 和 profile 环境变量。
- `/home/hikos/Yiliao2026/config/dds/fastdds_wsl_151.xml`WSL participant transport只允许 UDPv4 使用 `.151`peer 为 RDKx5 `.164`
- `/home/hikos/Yiliao2026/config/dds/use_wsl_dds_164_link.sh`:验证 WSL 网卡和 XML 后,导出 Domain、RMW 和 profile 环境变量。
- `/home/sunrise/yiliao_ws/docs/crucial_change/2026-07-23-fastdds-164-network-change.md`:设计、计划、实际变更、证据、提交号和回滚命令的唯一记录。
### Task 1实施前保护与基线
**Files:**
- Modify: `/home/sunrise/yiliao_ws/docs/crucial_change/2026-07-23-fastdds-164-network-change.md`
- [ ] **Step 1确认目标文件不会被覆盖**
在 RDKx5 执行:
```bash
for path in \
/home/sunrise/yiliao_ws/config/dds/fastdds_rdk_164.xml \
/home/sunrise/yiliao_ws/config/dds/use_rdk_dds_164.sh; do
if [ -e "$path" ]; then
echo "STOP: existing file: $path" >&2
exit 1
fi
done
```
在 WSL 执行:
```bash
for path in \
/home/hikos/Yiliao2026/config/dds/fastdds_wsl_151.xml \
/home/hikos/Yiliao2026/config/dds/use_wsl_dds_164_link.sh; do
if [ -e "$path" ]; then
echo "STOP: existing file: $path" >&2
exit 1
fi
done
```
Expected两段命令均无输出且返回 `0`。任何文件已存在都停止实施先将其路径、SHA-256 和内容写入本文件,不能覆盖。
- [ ] **Step 2采集最小基线**
RDKx5
```bash
ip -br -4 addr
ip -4 route
source /opt/ros/humble/setup.bash
python3 -c 'from rclpy.utilities import get_rmw_implementation_identifier; print(get_rmw_implementation_identifier())'
grep -n 'ROS_DOMAIN_ID' /home/sunrise/.bashrc
git -C /home/sunrise/yiliao_ws status --short
```
WSL
```bash
ip -br -4 addr
ip -4 route get 192.168.10.164
source /opt/ros/humble/setup.bash
python3 -c 'from rclpy.utilities import get_rmw_implementation_identifier; print(get_rmw_implementation_identifier())'
git -C /home/hikos/Yiliao2026 status --short
```
ExpectedRDKx5 存在 `.164``.210`WSL 存在 `.151`,双方 RMW 均为 `rmw_fastrtps_cpp`。记录现有 dirty files后续提交不得包含它们。
- [ ] **Step 3把基线摘要追加到唯一变更文档**
`apply_patch` 在本文件末尾增加 `## 实施记录``### 实施前基线`,写入上述命令的关键输出、实施开始时间以及“目标文件原先不存在”。不要粘贴无关的大段 package 列表。
- [ ] **Step 4提交基线记录**
```bash
cd /home/sunrise/yiliao_ws
git add -- docs/crucial_change/2026-07-23-fastdds-164-network-change.md
git diff --cached --check
git diff --cached --name-only
git commit -m "docs: record Fast DDS network baseline" -- \
docs/crucial_change/2026-07-23-fastdds-164-network-change.md
```
Expected待提交文件列表只有该 Markdown 文档。
### Task 2RDKx5 Fast DDS 配置
**Files:**
- Create: `/home/sunrise/yiliao_ws/config/dds/fastdds_rdk_164.xml`
- Create: `/home/sunrise/yiliao_ws/config/dds/use_rdk_dds_164.sh`
- Modify: `/home/sunrise/yiliao_ws/docs/crucial_change/2026-07-23-fastdds-164-network-change.md`
- [ ] **Step 1运行存在性测试并确认失败**
```bash
test -f /home/sunrise/yiliao_ws/config/dds/fastdds_rdk_164.xml && \
test -f /home/sunrise/yiliao_ws/config/dds/use_rdk_dds_164.sh
```
Expected返回非零因为两个文件尚未创建。
- [ ] **Step 2创建 RDKx5 XML**
创建目录 `/home/sunrise/yiliao_ws/config/dds`
```bash
mkdir -p /home/sunrise/yiliao_ws/config/dds
```
然后用 `apply_patch` 创建 `fastdds_rdk_164.xml`,完整内容为:
```xml
<?xml version="1.0" encoding="UTF-8" ?>
<profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles">
<transport_descriptors>
<transport_descriptor>
<transport_id>rdk_udp_164</transport_id>
<type>UDPv4</type>
<interfaceWhiteList>
<address>192.168.10.164</address>
</interfaceWhiteList>
</transport_descriptor>
<transport_descriptor>
<transport_id>rdk_shm</transport_id>
<type>SHM</type>
</transport_descriptor>
</transport_descriptors>
<participant profile_name="rdk_dds_164" is_default_profile="true">
<rtps>
<builtin>
<initialPeersList>
<locator>
<udpv4>
<address>192.168.10.151</address>
</udpv4>
</locator>
</initialPeersList>
</builtin>
<userTransports>
<transport_id>rdk_udp_164</transport_id>
<transport_id>rdk_shm</transport_id>
</userTransports>
<useBuiltinTransports>false</useBuiltinTransports>
</rtps>
</participant>
</profiles>
```
- [ ] **Step 3创建 RDKx5 环境脚本**
`apply_patch` 创建 `use_rdk_dds_164.sh`,完整内容为:
```bash
#!/usr/bin/env bash
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
echo "ERROR: source this file instead of executing it" >&2
exit 64
fi
_rdk_dds_profile="/home/sunrise/yiliao_ws/config/dds/fastdds_rdk_164.xml"
if ! ip -4 addr show dev wlx200db0c3fca5 2>/dev/null | grep -q 'inet 192\.168\.10\.164/'; then
echo "ERROR: wlx200db0c3fca5 does not own 192.168.10.164" >&2
unset _rdk_dds_profile
return 1
fi
if [[ ! -r "${_rdk_dds_profile}" ]]; then
echo "ERROR: unreadable Fast DDS profile: ${_rdk_dds_profile}" >&2
unset _rdk_dds_profile
return 1
fi
export ROS_DOMAIN_ID=22
export RMW_IMPLEMENTATION=rmw_fastrtps_cpp
export ROS_LOCALHOST_ONLY=0
export FASTRTPS_DEFAULT_PROFILES_FILE="${_rdk_dds_profile}"
export FASTDDS_DEFAULT_PROFILES_FILE="${_rdk_dds_profile}"
printf 'DDS link enabled: domain=%s rmw=%s local=192.168.10.164 profile=%s\n' \
"${ROS_DOMAIN_ID}" "${RMW_IMPLEMENTATION}" "${_rdk_dds_profile}"
unset _rdk_dds_profile
```
设置权限:
```bash
chmod 0644 /home/sunrise/yiliao_ws/config/dds/fastdds_rdk_164.xml
chmod 0755 /home/sunrise/yiliao_ws/config/dds/use_rdk_dds_164.sh
```
- [ ] **Step 4验证语法和 Fast DDS 实际加载**
```bash
bash -n /home/sunrise/yiliao_ws/config/dds/use_rdk_dds_164.sh
python3 -c "import xml.etree.ElementTree as ET; ET.parse('/home/sunrise/yiliao_ws/config/dds/fastdds_rdk_164.xml'); print('XML well-formed')"
source /opt/ros/humble/setup.bash
source /home/sunrise/yiliao_ws/config/dds/use_rdk_dds_164.sh
python3 -c "import rclpy; rclpy.init(); n=rclpy.create_node('rdk_dds_profile_check'); print('RMW participant created'); n.destroy_node(); rclpy.shutdown()"
```
Expected依次输出 `XML well-formed`、环境摘要和 `RMW participant created`stderr 中没有 XML profile 或 transport 错误。
- [ ] **Step 5记录 RDKx5 文件内容与校验值**
```bash
sha256sum \
/home/sunrise/yiliao_ws/config/dds/fastdds_rdk_164.xml \
/home/sunrise/yiliao_ws/config/dds/use_rdk_dds_164.sh
```
`apply_patch` 在本文件的实施记录中加入两个文件的完整内容、权限、SHA-256 和 Step 4 的结果。
- [ ] **Step 6只提交 RDKx5 配置和文档**
```bash
cd /home/sunrise/yiliao_ws
git add -- \
config/dds/fastdds_rdk_164.xml \
config/dds/use_rdk_dds_164.sh \
docs/crucial_change/2026-07-23-fastdds-164-network-change.md
git diff --cached --check
git diff --cached --name-only
git commit -m "feat: add dedicated Fast DDS 164 profile" -- \
config/dds/fastdds_rdk_164.xml \
config/dds/use_rdk_dds_164.sh \
docs/crucial_change/2026-07-23-fastdds-164-network-change.md
```
Expected提交只包含上述三个路径。
### Task 3WSL Fast DDS 配置
**Files:**
- Create: `/home/hikos/Yiliao2026/config/dds/fastdds_wsl_151.xml`
- Create: `/home/hikos/Yiliao2026/config/dds/use_wsl_dds_164_link.sh`
- Modify: `/home/sunrise/yiliao_ws/docs/crucial_change/2026-07-23-fastdds-164-network-change.md`
- [ ] **Step 1运行存在性测试并确认失败**
```bash
test -f /home/hikos/Yiliao2026/config/dds/fastdds_wsl_151.xml && \
test -f /home/hikos/Yiliao2026/config/dds/use_wsl_dds_164_link.sh
```
Expected返回非零因为两个文件尚未创建。
- [ ] **Step 2创建 WSL XML**
创建目录 `/home/hikos/Yiliao2026/config/dds`
```bash
mkdir -p /home/hikos/Yiliao2026/config/dds
```
然后用 `apply_patch` 创建 `fastdds_wsl_151.xml`,完整内容为:
```xml
<?xml version="1.0" encoding="UTF-8" ?>
<profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles">
<transport_descriptors>
<transport_descriptor>
<transport_id>wsl_udp_151</transport_id>
<type>UDPv4</type>
<interfaceWhiteList>
<address>192.168.10.151</address>
</interfaceWhiteList>
</transport_descriptor>
<transport_descriptor>
<transport_id>wsl_shm</transport_id>
<type>SHM</type>
</transport_descriptor>
</transport_descriptors>
<participant profile_name="wsl_dds_151" is_default_profile="true">
<rtps>
<builtin>
<initialPeersList>
<locator>
<udpv4>
<address>192.168.10.164</address>
</udpv4>
</locator>
</initialPeersList>
</builtin>
<userTransports>
<transport_id>wsl_udp_151</transport_id>
<transport_id>wsl_shm</transport_id>
</userTransports>
<useBuiltinTransports>false</useBuiltinTransports>
</rtps>
</participant>
</profiles>
```
- [ ] **Step 3创建 WSL 环境脚本**
`apply_patch` 创建 `use_wsl_dds_164_link.sh`,完整内容为:
```bash
#!/usr/bin/env bash
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
echo "ERROR: source this file instead of executing it" >&2
exit 64
fi
_wsl_dds_profile="/home/hikos/Yiliao2026/config/dds/fastdds_wsl_151.xml"
if ! ip -4 addr show dev eth4 2>/dev/null | grep -q 'inet 192\.168\.10\.151/'; then
echo "ERROR: eth4 does not own 192.168.10.151" >&2
unset _wsl_dds_profile
return 1
fi
if [[ ! -r "${_wsl_dds_profile}" ]]; then
echo "ERROR: unreadable Fast DDS profile: ${_wsl_dds_profile}" >&2
unset _wsl_dds_profile
return 1
fi
export ROS_DOMAIN_ID=22
export RMW_IMPLEMENTATION=rmw_fastrtps_cpp
export ROS_LOCALHOST_ONLY=0
export FASTRTPS_DEFAULT_PROFILES_FILE="${_wsl_dds_profile}"
export FASTDDS_DEFAULT_PROFILES_FILE="${_wsl_dds_profile}"
printf 'DDS link enabled: domain=%s rmw=%s local=192.168.10.151 peer=192.168.10.164 profile=%s\n' \
"${ROS_DOMAIN_ID}" "${RMW_IMPLEMENTATION}" "${_wsl_dds_profile}"
unset _wsl_dds_profile
```
设置权限:
```bash
chmod 0644 /home/hikos/Yiliao2026/config/dds/fastdds_wsl_151.xml
chmod 0755 /home/hikos/Yiliao2026/config/dds/use_wsl_dds_164_link.sh
```
- [ ] **Step 4验证语法和 Fast DDS 实际加载**
```bash
bash -n /home/hikos/Yiliao2026/config/dds/use_wsl_dds_164_link.sh
python3 -c "import xml.etree.ElementTree as ET; ET.parse('/home/hikos/Yiliao2026/config/dds/fastdds_wsl_151.xml'); print('XML well-formed')"
source /opt/ros/humble/setup.bash
source /home/hikos/Yiliao2026/config/dds/use_wsl_dds_164_link.sh
python3 -c "import rclpy; rclpy.init(); n=rclpy.create_node('wsl_dds_profile_check'); print('RMW participant created'); n.destroy_node(); rclpy.shutdown()"
```
Expected依次输出 `XML well-formed`、环境摘要和 `RMW participant created`stderr 中没有 XML profile 或 transport 错误。
- [ ] **Step 5记录 WSL 文件并提交**
```bash
sha256sum \
/home/hikos/Yiliao2026/config/dds/fastdds_wsl_151.xml \
/home/hikos/Yiliao2026/config/dds/use_wsl_dds_164_link.sh
cd /home/hikos/Yiliao2026
git add -- \
config/dds/fastdds_wsl_151.xml \
config/dds/use_wsl_dds_164_link.sh
git diff --cached --check
git diff --cached --name-only
git commit -m "feat: bind WSL Fast DDS to 192.168.10.151" -- \
config/dds/fastdds_wsl_151.xml \
config/dds/use_wsl_dds_164_link.sh
git rev-parse HEAD
```
Expected提交只包含两个 WSL 配置文件。用 `apply_patch` 把文件完整内容、权限、SHA-256、加载验证结果和 WSL commit 写入 RDKx5 的唯一变更文档,然后单独提交该文档:
```bash
cd /home/sunrise/yiliao_ws
git add -- docs/crucial_change/2026-07-23-fastdds-164-network-change.md
git diff --cached --check
git diff --cached --name-only
git commit -m "docs: record WSL Fast DDS deployment" -- \
docs/crucial_change/2026-07-23-fastdds-164-network-change.md
```
ExpectedRDKx5 本次提交只包含该 Markdown 文档。
### Task 4双向通信与网卡检查
**Files:**
- Modify: `/home/sunrise/yiliao_ws/docs/crucial_change/2026-07-23-fastdds-164-network-change.md`
- [ ] **Step 1清理 ROS 2 daemon 并加载双方环境**
RDKx5
```bash
source /opt/ros/humble/setup.bash
source /home/sunrise/yiliao_ws/install/setup.bash
source /home/sunrise/yiliao_ws/config/dds/use_rdk_dds_164.sh
ros2 daemon stop || true
```
WSL
```bash
source /opt/ros/humble/setup.bash
source /home/hikos/Yiliao2026/config/dds/use_wsl_dds_164_link.sh
ros2 daemon stop || true
```
Expected两个终端显示 Domain 22、Fast DDS 和各自本地专用地址。
- [ ] **Step 2验证 WSL 到 RDKx5**
先在 RDKx5 运行:
```bash
timeout 20 ros2 topic echo /dds_164_smoke_20260723 std_msgs/msg/String --once
```
随后在 WSL 运行:
```bash
ros2 topic pub --once /dds_164_smoke_20260723 std_msgs/msg/String "{data: wsl_to_rdk}"
```
ExpectedRDKx5 输出 `data: wsl_to_rdk`
- [ ] **Step 3验证 RDKx5 到 WSL**
先在 WSL 运行:
```bash
timeout 20 ros2 topic echo /dds_164_smoke_return_20260723 std_msgs/msg/String --once
```
随后在 RDKx5 运行:
```bash
ros2 topic pub --once /dds_164_smoke_return_20260723 std_msgs/msg/String "{data: rdk_to_wsl}"
```
ExpectedWSL 输出 `data: rdk_to_wsl`
- [ ] **Step 4确认 DDS 使用 `.164` 而非 `.210`**
在 RDKx5 两个终端同时开始短抓包:
```bash
sudo timeout 15 tcpdump -ni wlx200db0c3fca5 -c 5 'udp and host 192.168.10.151'
```
```bash
sudo timeout 15 tcpdump -ni wlan0 -c 1 'udp and host 192.168.10.151'
```
抓包期间重复 Step 2 的一次发布。Expected`wlx200db0c3fca5` 捕获到 UDP`wlan0` 超时且捕获 `0 packets`。当前 SSH 命令仍能返回:
```bash
ssh sunrise@192.168.10.210 'echo management-link-ok'
```
- [ ] **Step 5记录并提交精简验证结果**
`apply_patch` 写入双向消息结果、两张网卡的抓包摘要和 `management-link-ok`。如果任一步失败,停止到 Task 6 的快速回滚,不启动 Nav2。
```bash
cd /home/sunrise/yiliao_ws
git add -- docs/crucial_change/2026-07-23-fastdds-164-network-change.md
git diff --cached --check
git commit -m "docs: record dedicated DDS link verification" -- \
docs/crucial_change/2026-07-23-fastdds-164-network-change.md
```
### Task 5实际 `obstacle_nav2` 最小验证
**Files:**
- Modify: `/home/sunrise/yiliao_ws/docs/crucial_change/2026-07-23-fastdds-164-network-change.md`
- [ ] **Step 1安全启动 Nav2**
在已加载 RDKx5 专用 DDS 环境的终端运行:
```bash
ros2 launch obstacle_nav2 obstacle_nav2.launch.py enable_motion:=false
```
Expectedlaunch 启动,真实底盘速度输出仍映射到 `/cmd_vel_disabled`
- [ ] **Step 2WSL 检查关键话题**
在已加载 WSL 专用 DDS 环境的终端运行:
```bash
ros2 topic list | grep -E '^/obstacles$|^/local_costmap/costmap$|^/global_costmap/costmap$'
```
Expected至少出现 `/obstacles`,并出现 local/global costmap 话题;如果当前 Nav2 使用 `costmap_raw` 命名,则记录实际名称,不修改 Nav2 参数。
- [ ] **Step 3结束测试并记录结果**
使用 `Ctrl+C` 正常停止本次 launch。用 `apply_patch` 记录启动命令、关键话题、停止方式和最终结论;不执行运动目标、不修改 costmap 参数。
- [ ] **Step 4提交最终记录**
```bash
cd /home/sunrise/yiliao_ws
git add -- docs/crucial_change/2026-07-23-fastdds-164-network-change.md
git diff --cached --check
git commit -m "docs: finalize Fast DDS 164 deployment record" -- \
docs/crucial_change/2026-07-23-fastdds-164-network-change.md
```
### Task 6回滚演练说明与最终核对
**Files:**
- Modify: `/home/sunrise/yiliao_ws/docs/crucial_change/2026-07-23-fastdds-164-network-change.md`
- [ ] **Step 1写明快速回滚命令**
停止由专用环境启动的 ROS 节点后,在当前终端执行:
```bash
unset FASTRTPS_DEFAULT_PROFILES_FILE
unset FASTDDS_DEFAULT_PROFILES_FILE
unset RMW_IMPLEMENTATION
unset ROS_LOCALHOST_ONLY
export ROS_DOMAIN_ID=22
```
推荐的实际快速回滚方式是关闭该终端并新开终端,避免残留环境变量。将上述命令原样保存在实施记录中。
- [ ] **Step 2写明文件级回滚命令但成功时不执行**
只有用户要求撤销或部署失败时才执行。执行前分别确认四个绝对路径仍位于批准目录,然后删除具体文件,不递归删除工作空间:
```bash
rm -- \
/home/sunrise/yiliao_ws/config/dds/fastdds_rdk_164.xml \
/home/sunrise/yiliao_ws/config/dds/use_rdk_dds_164.sh
rmdir --ignore-fail-on-non-empty /home/sunrise/yiliao_ws/config/dds
```
```bash
rm -- \
/home/hikos/Yiliao2026/config/dds/fastdds_wsl_151.xml \
/home/hikos/Yiliao2026/config/dds/use_wsl_dds_164_link.sh
rmdir --ignore-fail-on-non-empty /home/hikos/Yiliao2026/config/dds
```
- [ ] **Step 3最终范围核对**
```bash
git -C /home/sunrise/yiliao_ws status --short
git -C /home/sunrise/yiliao_ws log -5 --oneline
git -C /home/hikos/Yiliao2026 status --short
git -C /home/hikos/Yiliao2026 log -3 --oneline
```
Expected新提交只涉及四个 DDS 配置文件和本 Markdown原有 dirty files 仍保持原状态,未被暂存、修改或清理。
## 实施记录
### 实施前基线
- 实施日期2026-07-23Asia/Shanghai
- 用户已明确允许直接在 RDKx5 `master` 和 WSL `zbw` 当前分支实施,并要求仅按明确路径提交。
- 四个目标配置文件在实施前均不存在,未覆盖任何已有文件。
- RDKx5
- `wlx200db0c3fca5``UP`,地址 `192.168.10.164/24`
- `wlan0``UP`,地址 `192.168.10.210/24`
- 默认路由优先使用 `wlan0`metric 600`.164` 网卡 metric 为 601。
- `~/.bashrc:141``export ROS_DOMAIN_ID=22`
- 当前 RMW 为 `rmw_fastrtps_cpp`
- 实施开始时仓库已有用户内容:`?? src/origincar_birdseye/`
- WSL
- `eth4``UP`,地址 `192.168.10.151/24`
- `ip route get 192.168.10.164` 的结果为 `dev eth4 src 192.168.10.151`
- 当前 RMW 为 `rmw_fastrtps_cpp`
- 实施开始时仓库已有用户内容:`.vscode/browse.vc.db*` 修改,以及 `.codex``resource/``src/navigation/``src/obstacle_scanner/``src/origincar_birdseye/``src/third_party/``tf_bag/` 等未跟踪路径。
- 本任务不会暂存、修改或清理上述已有用户内容。
### RDKx5 配置实施结果
- 新增目录:`/home/sunrise/yiliao_ws/config/dds/`
- `/home/sunrise/yiliao_ws/config/dds/fastdds_rdk_164.xml`
- 权限:`0644`
- SHA-256`f6714ed471930500bc42d5100113782fb585ce50d48326118a0d0a3c8903d1be`
- `/home/sunrise/yiliao_ws/config/dds/use_rdk_dds_164.sh`
- 权限:`0755`
- SHA-256`5b40b2d3c61bd9d7eedfdb11ef1bb43dd60b3cdbb67ddcb1e2da01ab79996059`
XML 完整内容:
```xml
<?xml version="1.0" encoding="UTF-8" ?>
<profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles">
<transport_descriptors>
<transport_descriptor>
<transport_id>rdk_udp_164</transport_id>
<type>UDPv4</type>
<interfaceWhiteList>
<address>192.168.10.164</address>
</interfaceWhiteList>
</transport_descriptor>
<transport_descriptor>
<transport_id>rdk_shm</transport_id>
<type>SHM</type>
</transport_descriptor>
</transport_descriptors>
<participant profile_name="rdk_dds_164" is_default_profile="true">
<rtps>
<builtin>
<initialPeersList>
<locator>
<udpv4>
<address>192.168.10.151</address>
</udpv4>
</locator>
</initialPeersList>
</builtin>
<userTransports>
<transport_id>rdk_udp_164</transport_id>
<transport_id>rdk_shm</transport_id>
</userTransports>
<useBuiltinTransports>false</useBuiltinTransports>
</rtps>
</participant>
</profiles>
```
环境脚本完整内容:
```bash
#!/usr/bin/env bash
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
echo "ERROR: source this file instead of executing it" >&2
exit 64
fi
_rdk_dds_profile="/home/sunrise/yiliao_ws/config/dds/fastdds_rdk_164.xml"
if ! ip -4 addr show dev wlx200db0c3fca5 2>/dev/null | grep -q 'inet 192\.168\.10\.164/'; then
echo "ERROR: wlx200db0c3fca5 does not own 192.168.10.164" >&2
unset _rdk_dds_profile
return 1
fi
if [[ ! -r "${_rdk_dds_profile}" ]]; then
echo "ERROR: unreadable Fast DDS profile: ${_rdk_dds_profile}" >&2
unset _rdk_dds_profile
return 1
fi
export ROS_DOMAIN_ID=22
export RMW_IMPLEMENTATION=rmw_fastrtps_cpp
export ROS_LOCALHOST_ONLY=0
export FASTRTPS_DEFAULT_PROFILES_FILE="${_rdk_dds_profile}"
export FASTDDS_DEFAULT_PROFILES_FILE="${_rdk_dds_profile}"
printf 'DDS link enabled: domain=%s rmw=%s local=192.168.10.164 profile=%s\n' \
"${ROS_DOMAIN_ID}" "${RMW_IMPLEMENTATION}" "${_rdk_dds_profile}"
unset _rdk_dds_profile
```
验证结果:
- `bash -n`:通过。
- XML well-formed通过。
- Fast DDS/RMW participant 实际创建:通过,输出 `RMW participant created`
- 环境摘要Domain `22`、RMW `rmw_fastrtps_cpp`、本地 DDS 地址 `.164`
- 首次从 PowerShell 直接拼接远端 `python3 -c` 时,引号在 SSH 边界被破坏Python 在读取 XML 前即报 `SyntaxError`。该失败与 XML 内容无关,未修改配置;改为通过 WSL Bash 和 stdin 传入验证程序后,相同验证完整通过。
### WSL 配置实施结果
- 新增目录:`/home/hikos/Yiliao2026/config/dds/`
- `/home/hikos/Yiliao2026/config/dds/fastdds_wsl_151.xml`
- 权限:`0644`
- SHA-256`bcf9c6e8e8b724cda1c6d83f02491ae0ad9ad7faec5be5dc01b8d60ea826d7ba`
- `/home/hikos/Yiliao2026/config/dds/use_wsl_dds_164_link.sh`
- 权限:`0755`
- SHA-256`7fe539eab3ddaa5b79a32145cd1d10834468ae47a73de239944b34c61be61f52`
- WSL Git commit`b8840ec94bca8668f7d56d80b75c9db0298d18a3`,该提交只包含上述两个文件。
XML 完整内容:
```xml
<?xml version="1.0" encoding="UTF-8" ?>
<profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles">
<transport_descriptors>
<transport_descriptor>
<transport_id>wsl_udp_151</transport_id>
<type>UDPv4</type>
<interfaceWhiteList>
<address>192.168.10.151</address>
</interfaceWhiteList>
</transport_descriptor>
<transport_descriptor>
<transport_id>wsl_shm</transport_id>
<type>SHM</type>
</transport_descriptor>
</transport_descriptors>
<participant profile_name="wsl_dds_151" is_default_profile="true">
<rtps>
<builtin>
<initialPeersList>
<locator>
<udpv4>
<address>192.168.10.164</address>
</udpv4>
</locator>
</initialPeersList>
</builtin>
<userTransports>
<transport_id>wsl_udp_151</transport_id>
<transport_id>wsl_shm</transport_id>
</userTransports>
<useBuiltinTransports>false</useBuiltinTransports>
</rtps>
</participant>
</profiles>
```
环境脚本完整内容:
```bash
#!/usr/bin/env bash
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
echo "ERROR: source this file instead of executing it" >&2
exit 64
fi
_wsl_dds_profile="/home/hikos/Yiliao2026/config/dds/fastdds_wsl_151.xml"
if ! ip -4 addr show dev eth4 2>/dev/null | grep -q 'inet 192\.168\.10\.151/'; then
echo "ERROR: eth4 does not own 192.168.10.151" >&2
unset _wsl_dds_profile
return 1
fi
if [[ ! -r "${_wsl_dds_profile}" ]]; then
echo "ERROR: unreadable Fast DDS profile: ${_wsl_dds_profile}" >&2
unset _wsl_dds_profile
return 1
fi
export ROS_DOMAIN_ID=22
export RMW_IMPLEMENTATION=rmw_fastrtps_cpp
export ROS_LOCALHOST_ONLY=0
export FASTRTPS_DEFAULT_PROFILES_FILE="${_wsl_dds_profile}"
export FASTDDS_DEFAULT_PROFILES_FILE="${_wsl_dds_profile}"
printf 'DDS link enabled: domain=%s rmw=%s local=192.168.10.151 peer=192.168.10.164 profile=%s\n' \
"${ROS_DOMAIN_ID}" "${RMW_IMPLEMENTATION}" "${_wsl_dds_profile}"
unset _wsl_dds_profile
```
验证结果:
- `bash -n`:通过。
- XML well-formed通过。
- Fast DDS/RMW participant 实际创建:通过,输出 `RMW participant created`
- 环境摘要Domain `22`、RMW `rmw_fastrtps_cpp`、本地 DDS 地址 `.151`、peer `.164`
- WSL 提交命令在工具等待窗口内没有返回,但后台提交随后正常完成;复核 commit `b8840ec9` 只包含两个批准的配置文件,原有 `.vscode` 暂存内容未进入该提交。
### 实施偏差WSL 接口名不稳定
- 发现时间2026-07-23 双向通信复核期间。
- 复现WSL 重启前 `.151` 位于 `eth4`;重启后仍为 `192.168.10.151/24`,但接口名变为 `eth3`。原脚本执行时返回 `ERROR: eth4 does not own 192.168.10.151`
- 根因WSL 镜像网络接口编号会在实例重启后变化,接口名不是稳定标识。
- 修正WSL 环境脚本不再要求接口名为 `eth4`,改为在所有本地 IPv4 接口中查找 `192.168.10.151/`。Fast DDS XML 仍按稳定 IP `.151` 建立 interface whitelist网络约束不变。
- 范围:只修改 `/home/hikos/Yiliao2026/config/dds/use_wsl_dds_164_link.sh` 的前置检查和错误文本;不修改 XML、路由表、RDKx5 配置或 ROS package。
- 失败保护:如果 `.151` 在任何接口上都不存在,脚本仍返回非零并拒绝启用 DDS 环境。
### 实施偏差:关闭 Domain 22 内建发现多播
- 发现时间2026-07-23 受控双向通信与双网卡抓包期间。
- 受控条件:测试前 RDKx5 无其他 Domain 22 socketRDK 测试 participant 的 UDP socket 只绑定 `.164`WSL 测试 participant 只绑定 `.151`
- 消息结果WSL 到 RDKx5 发布/订阅成功。
- 抓包结果:`.164` 捕获 189 个 Domain 22 包;`.210` 捕获 3 个包,三者均为 WSL `.151` 发往 `239.255.0.1:12900` 的 SPDP 多播,没有发往 `.210` 的 Domain 22 单播。
- 根因:配置 initial peer 不会自动关闭 Fast DDS 内建发现多播;同一局域网中的两张 RDKx5 网卡都会收到该多播帧。
- 修正:在 RDKx5 和 WSL profile 的 `<builtin>` 中加入 `<avoid_builtin_multicast>true</avoid_builtin_multicast>`,保留双端 initial peer 进行单播发现。
- 范围:只修改两个已批准的 Fast DDS XML不修改系统网卡的多播设置、路由、防火墙或 ROS package。
- 修正后的必要验收:双向消息仍成功,`.164` Domain 22 抓包大于零,`.210` Domain 22 抓包为零。
### WSL 接口名修正结果
- 修正提交:`9349f53cbc78851d9d053799af26f8055f58f9d3`
- 修正后脚本 SHA-256`4dd272d34bbc480e7f5d112348fad7bb59532f155cdabbdc7e7b98dda7ff6155`
- 当前 WSL 接口为 `eth3`、地址仍为 `.151` 时,脚本加载通过。
- 实际 participant socket 为 `.151:12900``.151:12910``.151:12911``.151` 上的自定义 UDP socket没有绑定 WSL 的其他地址。
修正后脚本完整内容:
```bash
#!/usr/bin/env bash
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
echo "ERROR: source this file instead of executing it" >&2
exit 64
fi
_wsl_dds_profile="/home/hikos/Yiliao2026/config/dds/fastdds_wsl_151.xml"
if ! ip -o -4 addr show 2>/dev/null | grep -q 'inet 192\.168\.10\.151/'; then
echo "ERROR: no local IPv4 interface owns 192.168.10.151" >&2
unset _wsl_dds_profile
return 1
fi
if [[ ! -r "${_wsl_dds_profile}" ]]; then
echo "ERROR: unreadable Fast DDS profile: ${_wsl_dds_profile}" >&2
unset _wsl_dds_profile
return 1
fi
export ROS_DOMAIN_ID=22
export RMW_IMPLEMENTATION=rmw_fastrtps_cpp
export ROS_LOCALHOST_ONLY=0
export FASTRTPS_DEFAULT_PROFILES_FILE="${_wsl_dds_profile}"
export FASTDDS_DEFAULT_PROFILES_FILE="${_wsl_dds_profile}"
printf 'DDS link enabled: domain=%s rmw=%s local=192.168.10.151 peer=192.168.10.164 profile=%s\n' \
"${ROS_DOMAIN_ID}" "${RMW_IMPLEMENTATION}" "${_wsl_dds_profile}"
unset _wsl_dds_profile
```
### 关闭发现多播的文件结果
- RDKx5 XML
- 新 SHA-256`9c7acb168af9eacd93b41e03e02f8554570c94853ab5cd485782ba9483b72be8`
- commit`e7c3fe9`
- WSL XML
- 新 SHA-256`990904e92ff54c76e04b70a7aa27fc9331484b2292635f1c22dddaeb0b16d52d`
- commit`4b11f35`
- 两个 XML 均只在 `<builtin>` 下新增:
```xml
<avoid_builtin_multicast>true</avoid_builtin_multicast>
```
- 两端 XML well-formed 检查通过Fast DDS/RMW participant 实际创建通过,没有 profile 或 transport 解析错误。
### 双向与网卡验证过程
1. 首次使用 `ros2 topic` CLI 测试时,既有 Domain 0 daemon 干扰等待逻辑,改用不依赖 CLI daemon 的临时 `rclpy` 发布/订阅节点。
2. 关闭发现多播前的受控测试:双向消息成功,`.164` 捕获 189 个 Domain 22 包,`.210` 只捕获 3 个 SPDP 多播包,没有 `.210` 单播。
3. 关闭发现多播后的首次重测开始前RDKx5 上出现一套由其他终端启动的未配置 `obstacle_nav2`,其 Domain 22 socket 绑定 `0.0.0.0`,破坏了“无其他 participant”的受控前提。该次消息超时不作为 XML 结论。
4. 当前运行命令确认为 `ros2 launch obstacle_nav2 obstacle_nav2.launch.py enable_motion:=true`,来源终端 `pts/3`;进程环境只有 `ROS_DOMAIN_ID=22``ROS_LOCALHOST_ONLY=0`,没有 Fast DDS profile 变量。
5. 因该 launch 已启用真实运动,实施者未擅自终止。最终双向和双网卡验证等待该 launch 停止,或获得明确授权后用专用 DDS 环境重新启动。
### 双向与网卡最终验证结果
- 用户在收到“需要停止或明确授权”的说明后指示继续;实施者对 PID `12541``enable_motion:=true` launch 发送一次 `SIGINT`
- launch 在正常清理后退出,复核子进程数为 `0`;未终止其父 shell未修改启动文件。
- 在 RDKx5 无其他 Domain 22 participant 的受控条件下:
- RDK 测试 participant socket 只绑定 `.164`
- WSL 测试 participant socket 只绑定 `.151`
- WSL -> RDKx5收到 `wsl_to_rdk`
- RDKx5 -> WSL收到 `rdk_to_wsl`
- 抓包探针消息 `capture_probe` 收到。
- `wlx200db0c3fca5` 的 Domain 22 抓包:`163 packets captured`
- `wlan0` 的 Domain 22 抓包:`0 packets captured`
- `.210` SSH 返回 `management-link-ok`
- 结论:对从专用环境启动的 Domain 22 participant跨主机 DDS 数据只使用 WSL `.151` 与 RDKx5 `.164``.210` 保持为管理链路。