Files
yiliao2026/docs/crucial_change/2026-07-23-fastdds-164-network-change.md

1380 lines
56 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` 保持为管理链路。
### 实施偏差:为同主机多进程增加本机 bootstrap peer
- 发现时间2026-07-23 `obstacle_nav2` 最小实际验证。
- 安全条件:使用专用 RDK 环境启动 `enable_motion:=false`,底盘速度被重映射到 `/cmd_vel_hardware_disabled`,未发布导航目标。
- 现象:底盘、雷达、`obstacle_scanner` 和 Nav2 进程均启动,但 lifecycle manager 持续输出 `Waiting for service controller_server/get_state...`WSL 只能看到 `/scan` 等基础话题,未看到 `/obstacles` 和 costmap。
- 根因:关闭 SPDP 多播后RDK profile 的 initial peer 只有远端 WSL `.151`。同一 RDK 上的多个 participant 没有本机单播 bootstrap peerSHM transport 本身不替代 participant discovery。
- 修正:
- RDK initial peer 同时包含本机 `.164` 和对端 `.151`
- WSL initial peer 同时包含本机 `.151` 和对端 `.164`,保证 WSL 现有软件由多个 participant 组成时也能本机发现。
- 范围:只在两个 Fast DDS XML 的 `<initialPeersList>` 中各增加一个本机 locator继续保持 `avoid_builtin_multicast=true` 和接口白名单。
- 必要复测Nav2 lifecycle 完成配置/激活WSL 可见 `/obstacles` 与 local/global costmap`.210` Domain 22 抓包仍为零。
### 实施偏差:扩大单播 initial peer 扫描范围
- 发现时间2026-07-23 增加本机 peer 后的 Nav2 复测。
- 现象:两个 RDK 测试 participant 能通过本机 `.164` peer 互相发现,但包含约 16 个 participant 的 Nav2 launch 仍无法让 lifecycle manager 找到 `controller_server/get_state`
- 根因initial peer locator 未显式指定端口时Fast DDS 只扫描有限数量的 participant ID默认范围足够两节点测试不足以覆盖 Nav2 多进程。
- 版本证据WSL Fast DDS `2.6.11` 与 RDKx5 Fast DDS `2.6.8` 的库均包含 `maxInitialPeersRange` 配置项。
- 修正:在双端自定义 UDPv4 transport descriptor 中加入 `<maxInitialPeersRange>64</maxInitialPeersRange>`
- 范围依据64 覆盖当前约 16 个 RDK participant 和 WSL 现有软件,并保留余量;不固定具体 UDP 端口,不引入 discovery server。
- 必要复测:本机多 participant 发现、Nav2 lifecycle 激活、WSL 关键话题可见、`.210` Domain 22 仍为零。
### peer 扫描范围修正与 Nav2 最终结果
- RDKx5 XML
- 最终 SHA-256`ecf275c084d4b8a1d2445a2613e079ab78182ac91dabd7ba53b48c10dde9c6d8`
- `maxInitialPeersRange` commit`e365bce`
- WSL XML
- 最终 SHA-256`d5de39799e4daa030025629fe5ee5eac1800f1c6def2c44971108ffe6ee6d54d`
- `maxInitialPeersRange` commit`441bf80`
- 两个 RDK participant 的本机单播测试通过:`SUB_RECEIVED ... local_ok``PUB_SENT ... local_ok`
- 实际启动命令:
```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 enable_motion:=false
```
- Nav2 lifecycle 完成配置与激活,日志包含 `Managed nodes are active`
- WSL 专用环境可见:
- `/obstacles`
- `/local_costmap/costmap`
- `/local_costmap/costmap_raw`
- `/global_costmap/costmap`
- `/global_costmap/costmap_raw`
- `/cmd_vel_hardware_disabled`
- 实际 Nav2 participant socket 抽查均绑定 `192.168.10.164`
- 验证脚本输出 `NAV2_VERIFY_OK`;验证结束后通过 `SIGINT` 停止 launch未发布运动目标。
RDKx5 最终 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>
<maxInitialPeersRange>64</maxInitialPeersRange>
<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>
<avoid_builtin_multicast>true</avoid_builtin_multicast>
<initialPeersList>
<locator>
<udpv4>
<address>192.168.10.164</address>
</udpv4>
</locator>
<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>
```
### 最终交付、校验与回滚记录
最终文件状态2026-07-23 复核):
- RDKx5 `/home/sunrise/yiliao_ws/config/dds/fastdds_rdk_164.xml`
- 权限/属主:`0644 sunrise:sunrise`
- SHA-256`ecf275c084d4b8a1d2445a2613e079ab78182ac91dabd7ba53b48c10dde9c6d8`
- RDKx5 `/home/sunrise/yiliao_ws/config/dds/use_rdk_dds_164.sh`
- 权限/属主:`0755 sunrise:sunrise`
- SHA-256`5b40b2d3c61bd9d7eedfdb11ef1bb43dd60b3cdbb67ddcb1e2da01ab79996059`
- WSL `/home/hikos/Yiliao2026/config/dds/fastdds_wsl_151.xml`
- 权限/属主:`0644 hikos:hikos`
- SHA-256`d5de39799e4daa030025629fe5ee5eac1800f1c6def2c44971108ffe6ee6d54d`
- WSL `/home/hikos/Yiliao2026/config/dds/use_wsl_dds_164_link.sh`
- 权限/属主:`0755 hikos:hikos`
- SHA-256`4dd272d34bbc480e7f5d112348fad7bb59532f155cdabbdc7e7b98dda7ff6155`
最终精简验证结果:
- 双向 `rclpy` 通信通过RDKx5 与 WSL 均能接收对端消息。
- RDKx5 抓包结果:`.164` 网卡捕获 `163 packets``.210` 网卡捕获 `0 packets``.210` SSH 管理链路正常。
- `ros2 launch obstacle_nav2 obstacle_nav2.launch.py enable_motion:=false` 通过lifecycle 日志包含 `Managed nodes are active`WSL 可见 `/obstacles`、local/global costmap 与 `/cmd_vel_hardware_disabled`,验证脚本输出 `NAV2_VERIFY_OK`
- 验证时未发布导航目标,速度输出被重映射到 `/cmd_vel_hardware_disabled`
- 验证 launch 已通过 `SIGINT` 正常退出最终进程复核时RDKx5 与 WSL 均无本任务 Nav2、DDS 验证脚本或 `tcpdump` 残留进程。
快速回滚(不删除文件):先停止从专用环境启动的 ROS 2 节点。最稳妥方式是关闭该终端并新开终端,只加载原 ROS 2 与工作空间环境。若必须复用当前终端,执行:
```bash
unset FASTRTPS_DEFAULT_PROFILES_FILE
unset FASTDDS_DEFAULT_PROFILES_FILE
unset RMW_IMPLEMENTATION
unset ROS_LOCALHOST_ONLY
export ROS_DOMAIN_ID=22
```
文件级逆向还原(本次验证成功,以下命令仅留档,未执行):
```bash
# RDKx5先解析并核对两个目标均位于批准目录再删除明确文件。
realpath /home/sunrise/yiliao_ws/config/dds/fastdds_rdk_164.xml
realpath /home/sunrise/yiliao_ws/config/dds/use_rdk_dds_164.sh
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
# WSL先解析并核对两个目标均位于批准目录再删除明确文件。
realpath /home/hikos/Yiliao2026/config/dds/fastdds_wsl_151.xml
realpath /home/hikos/Yiliao2026/config/dds/use_wsl_dds_164_link.sh
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
```
如需连同 Git 记录一起逆向还原,应在确认工作区无其他人的重叠修改后,按提交逆序使用 `git revert <commit>`;不得使用 `git reset --hard`,不得清理本节所列之外的 dirty files。相关提交
- RDKx5`edbe450``e7c3fe9``32a253a``e365bce`,以及对应实施记录提交;最近一次成功验证记录为 `985550a`
- WSL`b8840ec``9349f53``4b11f35``3195933``441bf80`
最终 Git 范围核对:
- RDKx5 当前分支为 `master`。除本 Markdown 的最终记录外,保留了任务开始前/用户已有的 `obstacle_nav2` 两个修改文件、三个 `nav2_params.yaml.bak.*``src/origincar_birdseye/`,未暂存、未清理、未纳入本任务提交。
- WSL 当前分支为 `zbw`。保留了 `.vscode/browse.vc.db*``.codex``resource/``src/navigation/``src/obstacle_scanner/``src/origincar_birdseye/``src/third_party/``tf_bag/` 等已有 dirty files未暂存、未清理、未纳入本任务提交。
- 未修改 `.bashrc`、路由表、防火墙、网卡 metric、Nav2 参数、ROS package、SSH 或 VS Code 配置;配置仅在终端中显式 `source` 后生效。
### 2026-07-23 18:51 后续卡顿诊断与恢复计划
#### 只读诊断证据
- 重启前 `ip route get 192.168.10.151 from 192.168.10.164` 返回 `dev wlx200db0c3fca5 table 164`;活动 Nav2 participant 的专用 UDP socket 绑定 `192.168.10.164`。因此已加载专用 profile 的 DDS 当时确实走 `.164`
- 同一启动周期累计计数显示:`.210``wlan0` 发送约 `11.58 GB / 3611 万包``.164` 网卡发送约 `64.5 MB / 22 万包`。该数量差异表明 `.210` 另有非专用 DDS 环境的流量。
- Windows 对 `.210` 的 20 次 ping 为平均 `4 ms`、最大 `55 ms``.164` 为平均 `2 ms`、最大 `5 ms`
- 18:52:55 启动的两个只读 `tcpdump` 均由 `timeout 8` 控制,并在 18:53:03 正常关闭 sudo session没有遗留 tcpdump。随后 RDK 网络失联并在 18:57:03 重新启动,上一启动日志末尾没有正常 shutdown 记录,因此只能确认发生了非正常重启,不能从现有日志证明触发源。
- 重启后 `wlx200db0c3fca5``NO-CARRIER`,没有 `.164` 地址、table 164 或 source rule`openwrt_5G` 当前扫描不可见。
- `.210` 管理网卡改连 `kskbl_2.4G`,协商 TX 约 `52 Mbit/s`。一个未设置 `FASTRTPS_DEFAULT_PROFILES_FILE` 的 ROS 2 daemon 绑定 `192.168.10.210`,说明未显式 source 专用脚本的 ROS CLI 会绕过 `.164` 配置。
#### 方案与实施顺序
采用回退连接方案:保留 `/etc/NetworkManager/dispatcher.d/90-wlx164-policy-route``.210` 管理连接和两个 Fast DDS XML 不变;克隆现有 `kskbl_2.4G` 凭据为只绑定 `wlx200db0c3fca5` 的回退 profile。原 `openwrt_5G 1` 保持为 `.164` 的 5G profile并将其自动连接优先级设为 `100`;回退 profile 优先级为 `50`
执行步骤:
1. RED 基线:确认 `.164` 不存在、`use_rdk_dds_164.sh` 返回失败、错误 ROS daemon 的环境中没有 Fast DDS profile 且 socket 位于 `.210`
2. 创建 `kskbl_2.4G-rdk164`,绑定 `wlx200db0c3fca5` 并试连接。只有 DHCP 返回 `192.168.10.164` 才继续;否则立即断开并删除该 profile。
3. 确认现有 dispatcher 自动恢复 `from 192.168.10.164/32 lookup 164`,且 `.164 -> .151` 走 USB 网卡不直接编辑路由表、dispatcher、网卡 metric 或防火墙。
4. 停止错误环境创建的 ROS 2 daemon从专用 DDS 环境启动新的 daemon检查其环境变量与 UDP socket。
5. 使用双向一次性 ROS 2 消息、短时只计数抓包和 ping 验证 `.164` 承载 DDS、`.210` 没有同一批 DDS 包且 SSH 保持可用。
6. 将实际 profile UUID、命令、结果、Git 状态和残留进程检查追加到本节,只提交本 Markdown。
精确回滚:
```bash
nmcli connection down 'kskbl_2.4G-rdk164' 2>/dev/null || true
nmcli connection delete 'kskbl_2.4G-rdk164'
nmcli connection modify 'openwrt_5G 1' connection.autoconnect-priority 0
```
上述回滚只删除本次新增的回退 profile并把既有 `openwrt_5G 1` 优先级恢复为实施前的 `0`;不得删除 `kskbl_2.4G``openwrt_5G 1`、策略路由脚本或 DDS 文件。
#### 后续恢复实施结果
- RDK 非正常重启后,`openwrt_5G` 扫描不可见,既有 `.164` profile 无法连接;`wlx200db0c3fca5` 没有地址,专用 DDS 脚本按设计返回失败。
- 新增 NetworkManager 回退连接:
- 名称:`kskbl_2.4G-rdk164`
- UUID`98eb5d04-3bf5-49a2-96e7-4ec44171154f`
- 绑定接口:`wlx200db0c3fca5`
- 自动连接优先级:`50`
- DHCP 实际地址:`192.168.10.164/24`
- 既有 `openwrt_5G 1` UUID `9e4f4ea7-f087-4369-8faf-fa3d0faa9839` 继续绑定 USB 网卡,自动连接优先级由 `0` 改为 `100`,保持 5G 为下次启动时的首选。
- 既有 `/etc/NetworkManager/dispatcher.d/90-wlx164-policy-route` 未修改;回退连接成功后自动恢复:
```text
1000: from 192.168.10.164 lookup 164
192.168.10.173 from 192.168.10.164 dev wlx200db0c3fca5 table 164
```
- WSL/Windows 有线 LAN 的 DHCP 地址在网络重启后变为 `192.168.10.173`。仅在 WSL 内临时添加 `.151`WSL 能发出但 RDK 无法反向 ARP该临时地址随后已删除。
- 尝试用 Windows `New-NetIPAddress` 添加持久 `.151` 辅助地址时系统返回 `Access is denied`,没有产生 Windows 地址或路由修改。
-`.173` 是当前真实可双向访问的 LAN 地址,最终将 WSL Fast DDS 本地地址和 RDK initial peer 从 `.151` 调整为 `.173`
- RDK `/home/sunrise/yiliao_ws/config/dds/fastdds_rdk_164.xml`:仅把远端 peer `192.168.10.151` 改为 `192.168.10.173`
- WSL XML 从 `fastdds_wsl_151.xml` 重命名为 `fastdds_wsl_173.xml`transport/profile ID 改为 `wsl_udp_173` / `wsl_dds_173`,本地白名单与本机 peer 改为 `.173`,对端仍为 `.164`
- WSL `use_wsl_dds_164_link.sh` 改为检查 `.173` 并加载 `fastdds_wsl_173.xml`
- 新文件校验:
- RDK XML`0644 sunrise:sunrise`SHA-256 `41c2fcac3c23218c40c3d4cf4273504f8233296e5db6ac44c3bc120c5d989dd1`
- RDK 脚本未变SHA-256 `5b40b2d3c61bd9d7eedfdb11ef1bb43dd60b3cdbb67ddcb1e2da01ab79996059`
- WSL XML`0644 hikos:hikos`SHA-256 `fa95118ced19bb0888789c8a0a59cbee1db2a01b00d3592a31b4bd9214ef7b4a`
- WSL 脚本:`0755 hikos:hikos`SHA-256 `85a1390cbda47fed4f42c01210067a575775b79c267def83d24abdde0f232543`
- Git 提交RDK XML `87f562d`WSL XML/脚本 `c383338`。两个提交均只包含上述明确路径。
#### daemon 与运行中节点恢复
- 重启后发现 Domain 22 的 ROS 2 daemon 没有 Fast DDS profileUDP socket 位于 `.210`。普通 `ros2 daemon stop``SIGTERM` 均未使该孤儿进程退出;在严格核对命令行后仅对该 daemon 使用 `SIGKILL`
- 新 RDK Domain 22 daemon 从专用环境启动,环境包含两个 Fast DDS profile 变量UDP socket 全部位于 `.164`
- WSL 旧 daemon 同样绑定已失效 `.151`,按相同方式清理后从 `.173` 环境重启UDP socket 全部位于 `.173`
- WSL 原有 `origincar_birdseye offline_validation.launch.py` 的父进程没有 DDS profile两个子节点仍绑定 `.151`。对明确 PID/命令行发送 `SIGINT` 正常停止后,用原命令在 `.173` 专用环境重启;`synthetic_camera_node``birdseye_node` 的 socket 均位于 `.173`
- `.210` 仍有一个 `ROS_DOMAIN_ID=23` 的独立 daemon它不属于本任务的 Domain 22未终止、未修改。
#### 最终数据路径与延迟证据
- 双向一次性 ROS 2 消息通过WSL 收到 `rdk_to_wsl_via_164`RDK 收到 `wsl_to_rdk_via_164`
- 在 RDK 从专用环境订阅 WSL `/image` 8 秒,第一次接口增量:
- `.164` RX `88,225,838` bytesTX `345,016` bytes
- `.210` RX `2,042` bytesTX `1,092` bytes
- 第二次同样负载:
- `.164` RX `90,334,970` bytesTX `346,092` bytes
- `.210` RX `1,194` bytesTX `1,092` bytes
- 结论:这两批约 8486 MiB 的图像 DDS 数据经过 `.164`,没有经过 `.210`
- 无负载时 `.210` 的 20 次 ping 为 `0%` 丢包、平均 `2 ms`、最大 `8 ms`。约 90 MB/8 秒图像负载期间15 次 ping 仍为 `0%` 丢包、平均 `5 ms`、最大 `52 ms`
- 剩余延迟尖峰不是 IP/DDS 泄漏:当前 `.164` 回退网卡与 `.210` 管理网卡都连接同一个 `kskbl_2.4G` AP共享 2.4 GHz 空口。只有 `openwrt_5G` 恢复可见并由优先级 `100` 的 profile 在启动时选中,或使用独立有线/5G 链路,才能进一步消除射频竞争。
#### 后续配置精确回滚
```bash
# RDK撤销 peer 地址提交,并删除本次新增回退连接。
cd /home/sunrise/yiliao_ws
git revert 87f562d
nmcli connection down 'kskbl_2.4G-rdk164' 2>/dev/null || true
nmcli connection delete 'kskbl_2.4G-rdk164'
nmcli connection modify 'openwrt_5G 1' connection.autoconnect-priority 0
```
```bash
# WSL恢复 .151 文件名、XML 与脚本。
cd /home/hikos/Yiliao2026
git revert c383338
```
回滚后应停止并重新启动 Domain 22 daemon/ROS 节点,使 participant 重新读取旧 XML。不要删除 `.210` 管理连接、现有策略路由脚本、Domain 23 daemon 或用户 dirty files。
WSL 最终 XML 完整内容(本节以下为最初 `.151` 版本的历史快照;当前生效版本和精确差异以上述后续实施结果为准):
```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>
<maxInitialPeersRange>64</maxInitialPeersRange>
<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>
<avoid_builtin_multicast>true</avoid_builtin_multicast>
<initialPeersList>
<locator>
<udpv4>
<address>192.168.10.151</address>
</udpv4>
</locator>
<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>
```