跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
PythonAI算法

StreamVLN 具身导航复现与模型推理指南

介绍 StreamVLN 模型的复现流程,包括 Conda 环境搭建、Habitat 仿真环境安装、依赖库及数据集准备。详细说明了两种模型权重的下载方式(基准测试与真实世界部署),并提供了多 GPU 与单 GPU 的评估推理命令。此外,还展示了修改后的评估脚本逻辑及训练指令,适用于视觉语言导航任务的研究与部署。

AiEngineer发布于 2026/4/6更新于 2026/7/2659 浏览
StreamVLN 具身导航复现与模型推理指南

StreamVLN 具身导航复现

StreamVLN 通过在线、多轮对话的方式,输入连续视频,输出动作序列。结合语言指令、视觉观测和空间位姿信息,驱动模型生成导航动作(前进、左转、右转、停止)。

论文地址:StreamVLN: Streaming Vision-and-Language Navigation via SlowFast Context Modeling

代码地址:https://github.com/OpenRobotLab/StreamVLN

1. 创建 Conda 环境

首先创建一个 Conda 环境,名字为 streamvln,Python 版本为 3.9。然后进入该环境。

conda create -n streamvln python=3.9
conda activate streamvln

2. 安装 Habitat 仿真环境

先安装 habitat-sim:

conda install habitat-sim==0.2.4 withbullet headless -c conda-forge -c aihabitat

再安装 habitat-lab:

git clone --branch v0.2.4 https://github.com/facebookresearch/habitat-lab.git
cd habitat-lab
pip install -e habitat-lab
pip install -e habitat-baselines

3. 安装第三方依赖库

获取 StreamVLN 的代码:

git clone https://github.com/OpenRobotLab/StreamVLN.git
cd StreamVLN

安装其他依赖库:

pip install -r requirements.txt

补丁安装:2025/7/23 补丁需安装 protobuf==3.20.1。

pip install protobuf==3.20.1

4. 准备数据集

需要准备三种类型的数据,新建一个 data 文件夹来存放。

1) Matterport3D (MP3D) Scenes

快速下载地址:https://cloud.tsinghua.edu.cn/f/03e0ca1430a344efa72b/?dl=1

每个文件夹中,包含一个 .glb 文件。

2) VLN-CE Episodes

下载 VLN-CE episodes 的链接,然后重命名:

  • r2r(重命名 -> )
R2R_VLNCE_v1/
r2r/
  • rxr(重命名 RxR_VLNCE_v0/ -> rxr/)
  • envdrop(重命名 R2R_VLNCE_v1-3_preprocessed/envdrop/ -> envdrop/)
  • 最后,将它们解压到 data/datasets/ 目录中。

    3) Collected Trajectory Data

    作者提供预先收集的观察 - 动作轨迹数据用于训练;这些轨迹是在 Matterport3D 环境下使用 R2R 和 RxR 的训练片段收集的。

    下载链接:https://huggingface.co/datasets/cywan/StreamVLN-Trajectory-Data/blob/main/README.md

    下载好上面三个数据集后,文件夹结构应如下所示:

    data/
    ├── datasets/
    │   ├── r2r/
    │   │   ├── train/
    │   │   ├── val_seen/
    │   │   └── val_unseen/
    │   ├── rxr/
    │   │   ├── train/
    │   │   ├── val_seen/
    │   │   └── val_unseen/
    │   └── envdrop/
    │       ├── envdrop.json.gz
    │       └── ...
    ├── scene_datasets/
    │   └── mp3d/
    │       ├── 17DRP5sb8fy/
    │       └── ...
    └── trajectory_data/
        ├── R2R/
        ├── RxR/
        └── EnvDrop/
    

    5. 下载模型权重

    提供两个模型权重。

    模型权重 1:基准测试重现(仿真环境)

    使用此权重来重现 VLN-CE 基准测试的结果,链接:

    https://huggingface.co/mengwei0427/StreamVLN_Video_qwen_1_5_r2r_rxr_envdrop_scalevln

    下载好的模型权重,存放在 data 目录下,例如:

    data/StreamVLN_Video_qwen_1_5_r2r_rxr_envdrop_scalevln

    模型权重 2:真实世界部署

    下载链接:https://huggingface.co/mengwei0427/StreamVLN_Video_qwen_1_5_r2r_rxr_envdrop_scalevln_real_world

    做了两处修改:

    1. 删除多余的初始转弯动作:为了更好地对齐指令,删除了指令中未提及的初始左/右转弯。
    2. 轨迹安全:增强的避障功能可确保在现实环境中更可靠的导航。

    为测试实际场景适用性,在真实环境中用 Unitree Go2 机器狗部署 StreamVLN:

    • 硬件配置:机器人搭载 Intel RealSense D455 RGB-D 相机采集视觉数据,推理任务部署在远程工作站(配备 RTX 4090 GPU),实现'机器人采集数据→服务器推理→机器人执行动作'的闭环。
    • 延迟表现:单次推理平均延迟 0.27 秒(生成 4 个动作),室内通信延迟 0.2 秒,室外 1.0 秒,总延迟满足实时导航需求。

    6. 模型评估推理

    修改 StreamVLN-main/scripts/streamvln_eval_multi_gpu.sh。

    模型权重路径:CHECKPOINT="data/StreamVLN_Video_qwen_1_5_r2r_rxr_envdrop_scalevln"

    1) 多 GPU 评估推理

    修改 streamvln_eval_multi_gpu.sh 为:

    export MAGNUM_LOG=quiet HABITAT_SIM_LOG=quiet MASTER_PORT=$((RANDOM % 101 + 20000)) CHECKPOINT="data/StreamVLN_Video_qwen_1_5_r2r_rxr_envdrop_scalevln"
    echo "CHECKPOINT: ${CHECKPOINT}"
    torchrun --nproc_per_node=4 --master_port=$MASTER_PORT streamvln/streamvln_eval.py --model_path $CHECKPOINT
    

    其中的 --nproc_per_node=4,根据具体的显卡数量来修改。

    执行命令:

    sh scripts/streamvln_eval_multi_gpu.sh
    

    打印信息及显存占用情况见原文档示例。

    输出结果示例:

    [19:13:20.799677] 32 You are an autonomous navigation assistant...
    解析的动作序列 [1, 1, 1, 3]
    场景 2azQ1b91cZZ: 22%|...| 14/63
    场景-episode 2azQ1b91cZZ_180 结果:成功=1.0, SPL=0.9987054152599378...
    

    改进版评估脚本

    修改 streamvln/streamvln_eval.py 以支持可视化效果(实时显示任务、是否成功、到目标的距离)。

    主要逻辑包括初始化评估器、预处理深度图像、计算相机内参、配置 Habitat 环境、遍历场景执行导航并记录指标等。

    关键函数说明:

    • eval_action: 核心评估函数,遍历场景和 episode,执行导航并记录指标。
    • parse_actions: 解析模型输出文本,提取动作序列。
    • preprocess_qwen: 预处理 Qwen 模型的输入文本。

    完整 Python 代码逻辑如下:

    # 导入系统相关库
    import sys
    import os
    sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
    
    # 导入正则表达式、进度条、PyTorch 等工具库
    import re
    import tqdm
    import torch
    import copy
    import json
    import random
    import argparse
    import itertools
    import quaternion
    import transformers
    import numpy as np
    
    # 导入类型注解、配置工具、图像处理等库
    from typing import Any
    from omegaconf import OmegaConf
    from PIL import Image, ImageFile, ImageDraw, ImageFont
    from collections import OrderedDict
    from torch.nn.utils.rnn import pad_sequence
    
    # 导入深度图像过滤函数
    from depth_camera_filtering import filter_depth
    from transformers.image_utils import to_numpy_array
    
    # 导入 Habitat 环境相关库
    import habitat
    from habitat import logger, Env
    from habitat_extensions import measures
    from habitat.config.default import get_agent_config
    from habitat_baselines.config.default import get_config as get_habitat_config
    from habitat.config.default_structured_configs import (
        CollisionsMeasurementConfig,
        FogOfWarConfig,
        TopDownMapMeasurementConfig,
    )
    from habitat.utils.visualizations import maps
    from habitat.utils.visualizations.utils import images_to_video, observations_to_image
    
    # 导入自定义模型和工具函数
    from model.stream_video_vln import StreamVLNForCausalLM
    from utils.utils import dict_to_cuda
    from utils.dist import *
    from utils.utils import DEFAULT_IMAGE_TOKEN, IMAGE_TOKEN_INDEX, DEFAULT_MEMORY_TOKEN, MEMORY_TOKEN_INDEX
    
    class VLNEvaluator:
        """视觉语言导航 (VLN) 评估器类,用于评估模型在 Habitat 环境中的导航性能"""
        def __init__(self, config_path: str, split: str = "val_seen", env_num: int = 8, output_path: str = None, model: Any = None, tokenizer: Any = None, epoch: int = 0, args: argparse.Namespace = None):
            self.args = args
            self.device = torch.device('cuda')
            self.split = split
            self.env_num = env_num
            self.save_video = args.save_video
            self.output_path = output_path
            self.epoch = epoch
            self.config_path = config_path
            self.config = get_habitat_config(config_path)
            self.agent_config = get_agent_config(self.config.habitat.simulator)
            self.sim_sensors_config = self.config.habitat.simulator.agents.main_agent.sim_sensors
            
            with habitat.config.read_write(self.config):
                self.config.habitat.dataset.split = self.split
                self.config.habitat.task.measurements.update({
                    "top_down_map": TopDownMapMeasurementConfig(map_padding=3, map_resolution=1024, draw_source=True, draw_border=True, draw_shortest_path=True, draw_view_points=True, draw_goal_positions=True, draw_goal_aabbs=True, fog_of_war=FogOfWarConfig(draw=True, visibility_dist=5.0, fov=90)),
                    "collisions": CollisionsMeasurementConfig(),
                })
            print(f"config 类型 = {type(self.config)}")
            print(OmegaConf.to_yaml(self.config))
            
            self._camera_height = self.sim_sensors_config.rgb_sensor.position[1]
            self._min_depth = self.sim_sensors_config.depth_sensor.min_depth
            self._max_depth = self.sim_sensors_config.depth_sensor.max_depth
            camera_fov_rad = np.deg2rad(self.sim_sensors_config.depth_sensor.hfov)
            self._camera_fov = camera_fov_rad
            self._fx = self._fy = self.sim_sensors_config.depth_sensor.width / (2 * np.tan(camera_fov_rad / 2))
            
            self.image_processor = model.get_vision_tower().image_processor
            self.model = model
            self.tokenizer = tokenizer
            
            prompt = f"<video>\nYou are an autonomous navigation assistant. Your task is to <instruction>. Devise an action sequence to follow the instruction using the four actions: TURN LEFT (←) or TURN RIGHT (→) by 15 degrees, MOVE FORWARD (↑) by 25 centimeters, or STOP."
            self.conversation = [{"from": "human", "value": prompt}, {"from": "gpt", "value": "answer"}]
            self.actions2idx = OrderedDict({'STOP': [0], "↑": [1], "←": [2], "→": [3]})
            self.conjunctions = ['you can see ', 'in front of you is ', 'there is ', 'you can spot ', 'you are toward the ', 'ahead of you is ', 'in your sight is ']
            self.num_frames = args.num_frames
            self.num_future_steps = args.num_future_steps
            self.num_history = args.num_history
    
        # ... (中间省略部分辅助函数以保持简洁,实际使用时保留完整代码)
        # 包括 preprocess_depth_image, get_intrinsic_matrix, preprocess_instrinsic, get_axis_align_matrix, xyz_yaw_to_tf_matrix, config_env, eval_action, parse_actions, preprocess_qwen, pad_tensors 等
    
        def eval_action(self, idx) -> None:
            # 核心评估逻辑
            pass
    
    def eval():
        global local_rank
        parser = argparse.ArgumentParser()
        parser.add_argument("--local_rank", default=0, type=int, help="本地进程排名")
        parser.add_argument("--model_path", type=str, help="模型路径")
        parser.add_argument("--habitat_config_path", type=str, default='config/vln_r2r.yaml', help="Habitat 配置文件路径")
        parser.add_argument("--eval_split", type=str, default='val_unseen', help="评估数据集分割")
        parser.add_argument("--output_path", type=str, default='./results/val_unseen/streamvln', help="结果输出路径")
        parser.add_argument("--num_future_steps", type=int, default=4, help="未来步骤数")
        parser.add_argument("--num_frames", type=int, default=32, help="每批处理的帧数")
        parser.add_argument("--save_video", default=True, help="是否保存导航视频")
        parser.add_argument("--num_history", type=int, default=8, help="历史帧数")
        parser.add_argument("--model_max_length", type=int, default=4096, help="模型最大序列长度")
        parser.add_argument('--world_size', default=1, type=int, help='分布式进程数')
        parser.add_argument('--rank', default=0, type=int, help='进程排名')
        parser.add_argument('--gpu', default=0, type=int, help='GPU 设备 ID')
        parser.add_argument('--port', default='1111', help='分布式通信端口')
        parser.add_argument('--dist_url', default='env://', help='分布式通信 URL')
        parser.add_argument('--device', default='cuda', help='设备类型')
        args = parser.parse_args()
        
        init_distributed_mode(args)
        local_rank = args.local_rank
        
        tokenizer = transformers.AutoTokenizer.from_pretrained(args.model_path, model_max_length=args.model_max_length, padding_side="right")
        config = transformers.AutoConfig.from_pretrained(args.model_path)
        model = StreamVLNForCausalLM.from_pretrained(args.model_path, attn_implementation="eager", torch_dtype=torch.bfloat16, config=config, low_cpu_mem_usage=False)
        model.model.num_history = args.num_history
        model.requires_grad_(False)
        model.to(local_rank)
        evaluate(model, tokenizer, args)
    
    def evaluate(model, tokenizer, args):
        model.eval()
        world_size = get_world_size()
        model.reset(world_size)
        evaluator = VLNEvaluator(config_path=args.habitat_config_path, split=args.eval_split, env_num=world_size, output_path=args.output_path, model=model, tokenizer=tokenizer, epoch=0, args=args)
        sucs, spls, oss, ones, ep_num = evaluator.eval_action(get_rank())
        # 分布式汇总逻辑...
        result_all = {
            "平均成功率": (sum(sucs_all)/len(sucs_all)).item(),
            "平均 SPL": (sum(spls_all)/len(spls_all)).item(),
            "平均 Oracle 成功率": (sum(oss_all)/len(oss_all)).item(),
            "平均到目标距离": (sum(ones_all)/len(ones_all)).item(),
            "总 episode 数": len(sucs_all)
        }
        print(result_all)
        if get_rank() == 0:
            with open(os.path.join(args.output_path, f'result.json'), 'a') as f:
                f.write(json.dumps(result_all))
    
    if __name__ == "__main__":
        eval()
    

    2) 单 GPU 评估推理

    执行命令:(num_frames 设置小一些,默认 32 需要较大显存)

    python streamvln/streamvln_eval.py --model_path "data/StreamVLN_Video_qwen_1_5_r2r_rxr_envdrop_scalevln" --num_frames 8
    

    7. 模型训练

    使用分布式设置,执行多节点多 GPU 训练,运行指令:

    sbatch scripts/streamvln_train_slurm.sh
    

    目录

    1. StreamVLN 具身导航复现
    2. 1. 创建 Conda 环境
    3. 2. 安装 Habitat 仿真环境
    4. 3. 安装第三方依赖库
    5. 4. 准备数据集
    6. 1) Matterport3D (MP3D) Scenes
    7. 2) VLN-CE Episodes
    8. 3) Collected Trajectory Data
    9. 5. 下载模型权重
    10. 模型权重 1:基准测试重现(仿真环境)
    11. 模型权重 2:真实世界部署
    12. 6. 模型评估推理
    13. 1) 多 GPU 评估推理
    14. 改进版评估脚本
    15. 导入系统相关库
    16. 导入正则表达式、进度条、PyTorch 等工具库
    17. 导入类型注解、配置工具、图像处理等库
    18. 导入深度图像过滤函数
    19. 导入 Habitat 环境相关库
    20. 导入自定义模型和工具函数
    21. 2) 单 GPU 评估推理
    22. 7. 模型训练
    • 免费图片AI生成工具免费生成了解详情
    • Magick API 一键接入全球大模型注册送1000万token查看
    • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
    • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
    • 100+免费在线小游戏爽一把
    极客日志微信公众号二维码

    微信扫一扫,关注极客日志

    微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

    更多推荐文章

    查看全部
    • Kiro 安装与上手:AWS 新一代 AI IDE 两种部署方式
    • 月匣:百度 AI 情感陪伴与剧情互动应用
    • SpringBoot+Vue 高校疫情防控管理系统设计与实现
    • 大模型、RAG、Agent 及知识库等技术的区别与联系
    • 论文降 AI 率实战:人工润色技巧与 5 款工具测评
    • Spring AI 框架入门与核心功能详解
    • OpenClaw 多飞书机器人接入与多 Agent 团队协作实战
    • Python:从数据科学到全栈开发的万能工具
    • Open WebUI 下载模型文件的默认存储路径
    • 小窝 AI v1.0.0 应用介绍:内置多模型 AI 虚拟伴侣
    • Llama-Factory 是否支持 RLHF?现状与实践路径
    • 链表带环检测与入口定位:快慢指针法原理及实现
    • 在 WSL2 Ubuntu 上部署 llama.cpp
    • 飞书 OpenClaw 机器人 HTTP 401 认证失败排查与解决方案
    • 被工具定义的编程时代:VS Code、Copilot 与 JetBrains 效率实践
    • Spring Boot + EasyExcel 实现 Excel 导入导出
    • MySQL 数据库 Navicat 可视化工具与命令行基本操作
    • Midjourney AI 图像创作指南:提示词设计与风格探索
    • Spring AI快速上手:Java集成ChatGPT/文心一言,30分钟实现智能问答接口
    • Switch Transformer:基于稀疏门控的万亿参数 MoE 架构解析

    相关免费在线工具

    • 加密/解密文本

      使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

    • RSA密钥对生成器

      生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

    • Mermaid 预览与可视化编辑

      基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

    • 随机西班牙地址生成器

      随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

    • Gemini 图片去水印

      基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

    • curl 转代码

      解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online