NUE-NeRF-nav 实验复现流程说明文档

论文: “Enhancing Exploratory Capability of Visual Navigation Using Uncertainty of Implicit Scene Representation” (IROS 2024)

复现日期: 2026年3月

有问题可以关于咸鱼用户:代码跑通pytorch。一个金鱼图像


目录

  1. 项目概述
  2. 环境配置
  3. 数据集准备
  4. 模型训练
  5. 模型测试
  6. 结果分析
  7. 项目文件结构
  8. 常用命令速查
  9. 已知问题与修复

1. 项目概述

NUE (Navigation with Uncertainty-driven Exploration) 是一种基于 NeRF 隐式场景表示的视觉导航方法。
核心思想:

  • 使用 NeRF 作为在线认知结构,实时构建场景的隐式表示
  • 通过 NeRF 的不确定性估计来增强探索能力
  • 从 NeRF 中提取记忆信息来辅助目标定位推理
  • 将探索(exploration)和利用(exploitation)无缝结合,生成导航动作

任务类型:Image-Goal Navigation(给定目标图像,导航到对应位置)


2. 环境配置

2.1 实际运行环境

组件 版本
Python 3.8.10
CUDA 11.3
PyTorch 1.10.0+cu113
iGibson 2.2.2
NumPy 1.22.x
TensorBoard 2.14.0
操作系统 Linux (AutoDL 云服务器)
GPU 双卡(cuda:0 + cuda:1)

2.2 安装步骤

# 1. 创建 conda 环境
conda create -n nue python=3.8
conda activate nue

# 2. 安装 PyTorch (CUDA 11.3)
pip install torch==1.10.0+cu113 torchvision==0.11.0+cu113 \
    -f https://download.pytorch.org/whl/cu113/torch_stable.html

# 3. 安装 iGibson
#    参考: https://github.com/StanfordVL/iGibson
pip install igibson

# 4. 安装其他依赖
pip install numpy==1.22.2 tensorboard==2.14.0 pyyaml opencv-python matplotlib tqdm

2.3 iGibson 数据集配置

iGibson 的场景数据需按如下结构放置:

iGibson/igibson/data/
├── assets/          # iGibson 基础资源
├── ig_dataset/      # iGibson 场景数据
├── g_dataset/       # Gibson 场景数据 (本项目使用)
│   ├── Adrian/
│   ├── Avonia/
│   ├── Kerrtown/
│   └── ...
└── igibson.key      # 许可证密钥

注意: 下载 Gibson 数据集需要通过 Stanford 官方申请,获取 igibson.key 后才能下载。


3. 数据集准备

3.1 Waypoints 数据集(用于生成专家数据)

下载 waypoints 数据集后放置在项目根目录:

NUE-NeRF-nav/navigation_scenarios/waypoints/
├── tiny/      # 最小规模
├── medium/    # 中等规模
├── full/      # 完整规模
└── full+/     # 增强规模

3.2 生成训练数据(专家数据集)

# 通过模仿学习的方式采集专家轨迹
python sample.py

生成的训练数据结构:

NUE-NeRF-nav/dataset/
├── Kerrtown/       # 训练场景1
│   ├── 0000/
│   │   ├── observation.npy    # 观测数据
│   │   ├── action.npy         # 专家动作标签
│   │   └── info.txt           # episode 信息
│   ├── 0001/
│   └── ...
├── Oyens/          # 训练场景2
├── Ribera/         # 训练场景3(注意:也出现在测试集中)
├── Rosenberg/      # 训练场景4
├── Roxboro/        # 训练场景5
└── Superior/       # 训练场景6

3.3 测试数据集

测试用的 episode 配置文件:

NUE-NeRF-nav/test_dataset/
├── Avonia.json         # 测试场景配置(含起点、目标等信息)
├── Lathrup.json
├── Mosinee.json
├── Rabbit.json
├── Sawpit.json
├── Ribera.json
└── ...(共 14 个场景可用)

实际测试使用了 6 个场景:Avonia, Lathrup, Mosinee, Rabbit, Sawpit, Ribera


4. 模型训练

4.1 关键配置参数

main_imitate_navig.py 中的主要参数:

# 训练模式
training = 1                    # 1 = 训练模式

# 训练超参数
episodeLimit = 24000            # 最大训练 episode 数
batchSize = 4                   # 批次大小(实际采样用 256)
initialLearningRate = 5e-4      # 初始学习率(模型训练实际用 1e-3)
save_model_every_n_step = 10000 # 每隔多少步保存模型(实际每1000步保存一次)

# 设备配置
device_0 = "cuda:0"             # 主模型所在 GPU
device_1 = "cuda:1"             # NeRF 训练所在 GPU

# 模型加载(接续训练时使用)
model_load = './model/9000.pkl' # 预训练模型路径

4.2 仿真环境配置

turtlebot_nav.yaml 关键配置:

# 机器人
robot: Turtlebot              # 使用 Turtlebot 机器人
action_type: continuous        # 连续动作空间

# 图像传感器
image_width: 240               # 图像宽度
image_height: 180              # 图像高度
vertical_fov: 75               # 垂直视场角

# 深度传感器
depth_low: 0.8                 # 最小深度范围
depth_high: 10.0               # 最大深度范围

# 终止条件(设置极大值,由代码控制)
max_step: 99999999
dist_tol: 0.36                 # 成功判定距离(机器人体宽)

4.3 相机内参

cameras.txt 中记录了相机内参矩阵参数:

fx=117.56  fy=117.56  cx=120.43  cy=89.90  H=180  W=240

4.4 训练架构

训练采用多进程架构:

  • 主进程: 运行 iGibson 仿真环境,收集轨迹数据
  • Process-1: 模型训练进程(模仿学习 + 策略优化)
  • Process-2: NeRF 在线训练进程(实时更新场景表示)

进程间通过 multiprocessing.QueueManager().list()Pipe 通信。

4.5 运行训练

# 前台运行
python main_imitate_navig.py

# 后台运行(推荐,因为训练时间很长)
nohup python main_imitate_navig.py > nohup_main_imitate.log 2>&1 &

4.6 训练输出

NUE-NeRF-nav/
├── model/2026-03-11/          # 模型 checkpoint
│   ├── 6000.pkl
│   ├── 7000.pkl
│   ├── ...
│   └── 57000.pkl              # 共 53 个 checkpoint,每 1000 步保存
├── summary/2026-03-11/        # TensorBoard 日志
│   └── events.out.tfevents.*
└── nohup_main_imitate.log     # 训练过程日志

查看训练曲线:

tensorboard --logdir summary/2026-03-11/ --port 6006

5. 模型测试

5.1 测试配置

test.py 中的关键参数:

max_step_num = 500          # 每个 episode 最大步数
device_0 = "cuda:0"         # 主模型 GPU
device_1 = "cuda:1"         # NeRF GPU

# 使用的模型 checkpoint
model_index = '57000'
model_load = 'model/2026-03-11/57000.pkl'

# 测试场景(共 6 个)
test_scenes = [
    'Avonia.json',
    'Lathrup.json',
    'Mosinee.json',
    'Rabbit.json',
    'Sawpit.json',
    'Ribera.json'
]

5.2 测试架构

测试同样采用多进程:

  • 主进程: 运行仿真环境,逐 episode 执行导航
  • Process-2: NeRF 在线训练进程(nerf_train_for_test),每个 episode 重置

每个 episode 的流程:

  1. 加载起点和目标图像
  2. 初始化 NeRF
  3. 每步:观测 -> Cognition Extraction (~3ms) -> Policy Generation (~2ms) -> 执行动作
  4. NeRF 在后台持续用观测数据训练(~73ms/步)
  5. 达到目标(距离 < 0.8m)或超过 500 步后结束

5.3 运行测试

# 前台运行
python test.py

# 后台运行(推荐,测试约需 4 小时)
nohup python test.py > test_output.log 2>&1 &

# 查看实时进度
tail -f test_output.log

5.4 测试输出

NUE-NeRF-nav/
├── test_result/57000/              # 测试结果目录
│   ├── Avonia.json                 # 各场景的逐 episode 结果
│   ├── Lathrup.json
│   ├── Mosinee.json
│   ├── Rabbit.json
│   ├── Ribera.json
│   ├── Sawpit.json
│   └── events.out.tfevents.*       # TensorBoard 日志
└── test_output.log                 # 测试过程日志

每个 JSON 结果文件的单条记录格式:

{
    "if success": true,
    "path dist": 9.80,
    "closed_dist": 0.93,
    "optimal dist": 5.16,
    "dist": 5.16,
    "label": ["straight", "hard"],
    "border": 0.8,
    "endDist": 0.93
}

字段说明:

  • if success: 是否导航成功
  • path dist: 实际行走路径长度(米)
  • closed_dist: 过程中最近距离目标的距离
  • optimal dist: 最优路径长度(米)
  • dist: 目标距离
  • label: [路径类型(straight/curved), 难度级别(easy/medium/hard)]
  • border: 成功判定阈值(米)
  • endDist: 终止时距目标的距离

6. 结果分析

6.1 查看结果命令

# 使用项目自带脚本查看完整指标
python compute_metrics.py 57000

6.2 评估指标说明

指标 全称 含义 方向
SR Success Rate 成功率 = 成功数 / 总数 x 100% 越高越好
SPL Success weighted by Path Length 路径效率 = (1/N) x sum(S_i x l_i / max(p_i, l_i)) 越高越好
DTS Distance To Success/goal 终止时距目标的平均距离 越低越好

其中:

  • S_i = 1 如果成功,0 如果失败
  • l_i = 最优路径长度 (optimal dist)
  • p_i = 实际行走路径长度 (path dist)

6.3 按难度分类的结果

难度由目标距离和路径复杂度决定(标签在 test_dataset 的 JSON 中预定义):

难度 数量 SR (复现) SR (论文) SPL (复现) SPL (论文) DTS (复现) DTS (论文)
Easy 159 61.64% 66.00% 0.407 0.458 2.030 1.289
Medium 187 52.94% 59.50% 0.373 0.388 2.658 1.511
Hard 131 52.67% 54.75% 0.406 0.388 3.039 2.684
Total 477 55.77% 59.65% 0.393 0.385 2.553 2.053

6.4 按场景的结果

场景 数量 SR SPL DTS
Avonia 76 55.26% 0.306 2.191
Lathrup 77 55.84% 0.415 2.513
Mosinee 79 60.76% 0.397 2.182
Rabbit 73 65.75% 0.497 2.199
Ribera 89 39.33% 0.279 3.057
Sawpit 83 60.24% 0.480 3.049
  • 最好:Rabbit(SR=65.75%, SPL=0.497)
  • 最差:Ribera(SR=39.33%, SPL=0.279)

6.5 复现差距分析

  • SR 整体低约 3.9 个百分点,Easy 和 Medium 差距较大
  • SPL Total 和 Hard 实际上略优于论文值
  • DTS 整体偏高约 0.5m

可能的差距原因:

  1. 随机种子不同
  2. 训练 episode 数可能不同(本次训练约 57000 步)
  3. iGibson 版本差异(论文使用 2.0.6,复现使用 2.2.2)
  4. 场景渲染的微小差异

6.6 推理速度

模块 平均耗时
Cognition Extraction ~3.0 ms
Policy Generation ~1.9 ms
单步总时间 ~60 ms
NeRF 训练(每步) ~73 ms

7. 项目文件结构

NUE-NeRF-nav/
│
├── main_imitate_navig.py   # 【训练入口】模仿学习训练主脚本
├── test.py                 # 【测试入口】模型测试主脚本
├── compute_metrics.py      # 【结果分析】计算 SR/SPL/DTS 指标
├── sample.py               # 【数据采集】从 waypoints 生成专家数据
│
├── model.py                # 模型定义(E2E_model, NeRF, 训练/测试进程)
├── model_qkv.py            # QKV 注意力变体模型
├── trainer.py              # 训练器、仿真交互逻辑
├── dataset.py              # 数据集加载器
├── util.py                 # 工具函数(渲染热力图等)
│
├── turtlebot_nav.yaml      # iGibson 仿真环境配置
├── cameras.txt             # 相机内参
├── scenes_for_training.txt # 训练场景列表(6个场景)
│
├── dataset/                # 训练数据(专家轨迹)
│   ├── Kerrtown/
│   ├── Oyens/
│   ├── Ribera/
│   ├── Rosenberg/
│   ├── Roxboro/
│   └── Superior/
│
├── test_dataset/           # 测试 episode 配置
│   ├── Avonia.json ~ Ribera.json  (共14个场景可用)
│
├── navigation_scenarios/   # waypoints 原始数据
│   └── waypoints/
│       ├── tiny/  medium/  full/  full+/
│
├── model/                  # 训练保存的模型 checkpoint
│   └── 2026-03-11/
│       ├── 6000.pkl ~ 57000.pkl  (共53个)
│
├── summary/                # TensorBoard 训练日志
│   └── 2026-03-11/
│
├── test_result/            # 测试结果
│   ├── 4000/               # 早期测试(仅 Avonia, SR=23.1%)
│   └── 57000/              # 最终测试(6场景, SR=55.8%)
│
├── test_output.log         # 测试过程日志
├── nohup_main_imitate.log  # 训练过程日志
├── model.py.bak            # model.py 修复前的备份
│
└── doc/                    # 文档和图片
    ├── network.png         # 网络结构图
    └── result.png          # 论文结果表

8. 常用命令速查

# ===== 训练 =====
# 启动训练(后台)
nohup python main_imitate_navig.py > nohup_main_imitate.log 2>&1 &

# 查看训练进度
tail -f nohup_main_imitate.log

# 查看训练曲线
tensorboard --logdir summary/2026-03-11/ --port 6006


# ===== 测试 =====
# 启动测试(后台,约需 4 小时)
nohup python test.py > test_output.log 2>&1 &

# 查看测试进度
tail -f test_output.log


# ===== 结果分析 =====
# 查看 checkpoint 57000 的完整指标
python compute_metrics.py 57000

# 查看 checkpoint 4000 的指标
python compute_metrics.py 4000


# ===== 环境 =====
# 激活环境
conda activate base

# 查看 GPU 使用情况
nvidia-smi

9. 已知问题与修复

9.1 BrokenPipeError(已修复)

问题: 测试完成后,nerf_train_for_test 子进程访问已销毁的 Manager 共享列表时抛出 BrokenPipeError。

位置: model.py 第 785 行

修复: 将 reset_list[-1] 的直接访问包裹在 try/except 中:

# 修复前:
if reset_list[-1]:

# 修复后:
try:
    should_reset = reset_list[-1]
except (BrokenPipeError, EOFError, ConnectionResetError, OSError):
    break
if should_reset:

影响: 此错误仅在测试全部完成后的清理阶段发生,不影响测试结果的正确性

备份: 修复前的文件已备份为 model.py.bak

9.2 Gym 废弃警告

运行时会出现 Gym 过期警告,这是因为 iGibson 2.x 依赖旧版 Gym。该警告不影响功能,可以忽略。


最后更新: 2026-03-12

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐