habitat_lab环境搭建及配置
Habitat-lab仿真基础
Habitat-Lab 是基于 Habitat-Sim 的算法层,封装了标准化的任务、评估指标和 API,让研究者无需关注底层仿真细节,专注于具身智能算法的设计、训练与评估。
一、Habitat-lab特性介绍
1. 预定义具身任务
•
导航类:PointGoalNav(点目标导航)、ObjectNav(物体目标导航)、VLN(视觉语言导航)。
•
交互类:Rearrange(物体重排)、PickPlace(拾取放置)、OpenDoor(开门)。
•
支持自定义任务(如多智能体协作、长程规划)。
2.标准化评估体系
•
内置核心指标(成功率 SR、路径长度效率 SPL、DTW 对齐分数等),可直接对比算法性能。
•
支持与公开基准(如 Habitat Challenge)对齐,便于论文复现和成果对比。
3.模块化智能体架构
•
解耦 “传感器 → 编码器 → 策略 → 控制器”,可快速替换组件(如用 CNN 或者 Transformer 做视觉编码,用 RL/IL 做决策);
•
深度集成 PyTorch,支持强化学习(RL)、模仿学习(IL)、端到端深度学习等主流算法。
4.易用的 API
•
提供简洁的 Python 接口,一键加载场景、初始化智能体、运行仿真循环。
二、Habitat-lab环境搭建
这里可以直接使用habitat-sim创建的conda环境
代码块
Python
conda create -n habitat python=3.9 cmake=3.14.0
conda activate habitat
在下载habitat-lab的时候注意需要与安装的habitat-sim版本一致,例如本教程使用的habitat-sim版本是0.2.5,则需要下载0.2.5版本的habitat-lab,复现其他论文的时候也要注意habitat-sim和habitat-lab版本一致。
代码块
Python
git clone --branch v0.2.5 https://github.com/facebookresearch/habitat-lab.git
cd habitat-lab
pip install -e habitat-lab
同时安装habitat-baselines
代码块
Python
pip install -e habitat-baselines
下载3D场景数据和点导航数据
代码块
Python
python -m habitat_sim.utils.datasets_download --uids habitat_test_scenes --data-path data/
代码块
Python
python -m habitat_sim.utils.datasets_download --uids habitat_test_pointnav_dataset --data-path data/
三、Habitat-lab初探与yaml配置基础讲解
本节将以habitat-lab的项目中提供的交互式导航代码habitatlab_test.py为核心,详细讲解 Habitat-Lab 中 yaml 配置文件的编写逻辑与加载流程,对于后续更加复杂的 yaml 文件的阅读提供基本的思路。
1. habitatlab_test.py的yaml配置基础及实现
habitatlab_test.py的运行流程:
1) 加载 YAML 配置
2) 初始化环境
3) 重置环境获取观测
4) 按键交互控制智能体
5) 依据配置的最大步数终止循环。
可以看出与Habitat-sim最不同的部分就是YAML的加载和配置,在导入yaml配置后,初始化其实还是用habitat-sim来运行的,下面将对pointnav_habitat_test.yaml文件做详细的讲解。
代码块
Python
# @package _global_
defaults:
- pointnav_base
- /habitat/dataset/pointnav: habitat_test
- _self_
habitat:
environment:
yaml配置输入:
加载pointnav_base.yaml(基础 PointNav 配置)
覆盖 /habitat/dataset/pointnav 为 habitat_test
用当前文件的habitat.environment.max_episode_steps:500、simulator.agents.main_agent.sim_sensors覆盖基础配置
刚开始使用habitat-lab的初学者可能会很疑惑,那这些就全部配置结束了?其实不是,在代码中,有很多的默认配置,最终通过habitat-lab解析,传入habitat-sim完成环境和智能体的创建,下面将给大家进行详细的讲解,来疏通大家的困惑
具体的yaml可配置项可以参考:https://github.com/facebookresearch/habitat-lab/blob/main/habitat-lab/habitat/config/CONFIG_KEYS.md
以下关于yaml配置的代码均参考habitat-lab中的default_structured_configs.py文件中的函数,可去源文件中进行察看。
yaml配置详解:
1) yaml中的数据集配置详解
代码块
Python
class DatasetConfig(HabitatBaseConfig):
type: str = "PointNav-v1"
split: str = "train"
scenes_dir: str = "data/scene_datasets"
content_scenes: List[str] = field(default_factory=lambda: ["*"])
data_path: str = (
"data/datasets/pointnav/"
关键配置项的默认值说明:
•
habitat.dataset.type:默认值为PointNav-v1,表示点导航任务数据集
•
habitat.dataset.split:默认值为train,表示训练集分割
•
habitat.dataset.scene_dir:默认值为data/scene_datasets,表示场景数据集的根目录
•
habitat.dataset.data_path:默认值为data/datasets/pointnav/habitat-test-scenes/v1/{split}/{split}.json.gz,表示数据集文件路径,其中{split}会被实际的 split 值替换。
•
数据集配置还支持通过content_scenes字段指定要加载的具体场景列表,默认情况下会加载所有可用场景。
2) yaml中的任务配置详解
代码块
Python
关键配置项的默认值说明:
•
habitat.task.type:默认值为Nav-v0,表示导航任务
•
habitat.task.physics_target_sps:默认值为60.0,表示物理引擎的更新频率为每秒 60 次
•
habitat.task.reward_measure:默认值为None,需要在具体配置中指定奖励测量指标
•
habitat.task.success_measure:默认值为None,需要在具体配置中指定成功测量指标
•
habitat.task.success_reward:默认值为2.5,表示成功完成任务的奖励
•
habitat.task.slack_reward:默认值为-0.01,表示每步的基础奖励(惩罚)
•
habitat.task.end_on_success:默认值为False,表示成功后不会自动结束 episode
•
任务配置还包含了大量与重排任务相关的默认值,如settle_steps(默认 5 步)、constraint_violation_ends_episode(默认 True)等。
3) yaml中的环境配置详解
代码块
Python
class EnvironmentConfig(HabitatBaseConfig):
max_episode_steps: int = 1000
max_episode_seconds: int = 10000000
iterator_options: IteratorOptionsConfig = IteratorOptionsConfig()
关键配置项的默认值说明:
•
habitat.environment.max_episode_steps:默认值为1000,表示 episode 的最大步数限制
•
habitat.environment.max_episode_seconds:默认值为10000000,表示 episode 的最大时间限制
•
habitat.environment.iterator_options:包含多个迭代器选项的默认配置,如循环模式(cycle)默认为 True、随机洗牌(shuffle)默认为 True 等
4) yaml中的模拟器配置详解
代码块
Python
关键配置项的默认值说明:
•
habitat.simulator.type:默认值为Sim-v0
•
habitat.simulator.forward_step_size:默认值为0.25米,控制前进动作的步长
•
habitat.simulator.turn_angle:默认值为10度,控制旋转动作的角度
•
habitat.simulator.create_renderer:默认值为False
•
habitat.simulator.requires_textures:默认值为True
•
habitat.simulator.lag_observations:默认值为0
•
habitat.simulator.auto_sleep:默认值为False
•
habitat.simulator.step_physics:默认值为True
5) yaml中的Agent配置详解
代码块
Python
class AgentConfig(HabitatBaseConfig):
height: float = 1.5
radius: float = 0.1
max_climb: float = 0.2
max_slope: float = 45.0
grasp_managers: int = 1
sim_sensors: Dict[str, Any] = field(default_factory=dict)
is_set_start_state: bool = False
start_position: List[float] = field(default_factory=lambda: [0, 0, 0])
start_rotation: List[float] = field(default_factory=lambda: [0, 0, 0, 1])
joint_start_noise: float = 0.1
joint_that_can_control: Optional[List[int]] = None
# Hard-code the robot joint start. `joint_start_noise` still applies.
joint_start_override: Optional[List[float]] = None
articulated_agent_urdf: Optional[str] = None
articulated_agent_type: Optional[str] = None
•
habitat.simulator.agents.main_agent.height:默认值为1.5米,定义智能体的基础高度,直接影响传感器(如RGB、深度相机)的观测视角,默认贴合人类视角高度。
•
habitat.simulator.agents.main_agent.radius:默认值为0.1米,设置智能体的碰撞半径,用于模拟器中碰撞检测,避免智能体穿透场景物体。
•
habitat.simulator.agents.main_agent.auto_update_sensor_transform:默认值为True,每帧自动更新传感器相对于智能体的位姿;关闭后需手动更新,适用于自定义传感器布局场景。
结合以上的默认配置和pointnav_habitat_test.yaml以及pointnav_base.yaml,可以得到一个示意的yaml完整文件如下。(具体代码运行的时候不会生成这个yaml文件,只是一个示意的yaml供参考使用)
代码块
Python
成功运行habitatlab_test.py并了解了基本的yaml配置原理后,可以跳过后面的部分,想要了解yaml文件配置导入代码的运行流程的可以参考后续内容,学习yaml文件导入代码的基本思路。
2. yaml文件配置运行流程详解
1) 获取配置文件并合并基础配置
配置对象的构建通过get_config函数完成,该函数位于habitat-lab/habitat/config/default.py文件中。构建过程如下:
代码块
Python
def get_config(
config_path: str,
overrides: Optional[List[str]] = None,
configs_dir: str = _HABITAT_CFG_DIR,
) -> DictConfig:
r"""Returns habitat config object composed of configs from yaml file (config_path) and overrides.
:param config_path: path to the yaml config file.
路径解析:首先使用get_full_config_path函数解析配置文件的绝对路径,该函数检查配置路径是否存在,如果不存在则在配置目录中查找。
配置组合:使用compose函数组合配置,compose函数的参数包括配置名称(配置文件的基本名称)和覆盖项列表。
配置修补:返回配置对象前,调用patch_config方法对配置进行内部修补,推断缺失的键并确保某些键存在且相互兼容。
2)config传入Env类进行初始化
在get_config函数后,在habitat-lab/habitat/core/env.py文件中,完成模拟器、任务和传感器的实例化。habitat.Env类是 Habitat Lab 环境的核心类,它集成了三个主要组件:数据集、模拟器和任务。
Env 类初始化流程详细步骤:
构造函数参数处理:
代码块
Python
def __init__(self, config: "DictConfig", dataset: Optional[Dataset[Episode]] = None) -> None:
•
config参数:环境配置,应包含模拟器 ID 和任务名称,这些将传递给make_sim和make_task函数
•
dataset参数:任务实例级信息的数据集引用,可以为None
配置预处理:
代码块
Python
if "habitat" in config:
config = config.habitat
self._config = config
如果配置中包含habitat键,则提取habitat子配置作为实际使用的配置。
数据集初始化:
代码块
Python
self._dataset = dataset
if self._dataset is None and config.dataset.type:
self._dataset = make_dataset(
id_dataset=config.dataset.type,
config=config.dataset
如果未提供数据集且配置中指定了数据集类型,则使用make_dataset创建数据集。
当前 episode 和 episode 迭代器初始化:
代码块
Python
self._current_episode = None
self._episode_iterator = None
self._episode_from_iter_on_reset = True
self._episode_force_changed = False
episode 迭代器设置(如果有数据集):
代码块
Python
if self._dataset:
assert (
len(self._dataset.episodes) > 0
), "dataset should have non-empty episodes list"
•
调用_setup_episode_iterator方法设置 episode 迭代器
•
获取第一个 episode 并设置为当前 episode
•
更新配置中的场景数据集和场景 ID
•
设置 episode 总数
模拟器初始化:
代码块
Python
使用配置中的模拟器类型和配置初始化模拟器。
任务初始化:
代码块
Python
self._task = make_task(
self._config.task.type,
config=self._config.task,
sim=self._sim,
dataset=self._dataset,
)
使用配置中的任务类型、任务配置、模拟器实例和数据集初始化任务。
观察空间和动作空间设置:
代码块
Python
self.observation_space = spaces.Dict({
**self._sim.sensor_suite.observation_spaces.spaces,
**self._task.sensor_suite.observation_spaces.spaces,
})
self.action_space = self._task.action_space
观察空间由模拟器传感器套件和任务传感器套件的观察空间合并而成,动作空间来自任务。
最大步数和时间限制设置:
代码块
Python
self._max_episode_seconds = self._config.environment.max_episode_seconds
self._max_episode_steps = self._config.environment.max_episode_steps
self._elapsed_steps = 0
self._episode_start_time: Optional[float] = None
从配置中读取最大 episode 步数和时间限制,并初始化相关状态变量。
在上述过程中,配置驱动的组件实例化是 Habitat Lab 的核心机制,通过配置文件可以灵活地创建不同类型的环境。
上述代码中的模拟器实例化make_sim,任务实例化make_task,以及传感器实例化的代码和路径如下:
•
模拟器实例化
(habitat-lab/habitat/sims/registration.py)
代码块
Python
def make_sim(id_sim, **kwargs):
logger.info("initializing sim {}".format(id_sim))
_sim = registry.get_simulator(id_sim)
assert _sim is not None, "Could not find simulator with name {}".format(id_sim)
return _sim(**kwargs)
•
任务实例化
(habitat-lab/habitat/tasks/registration.py)
代码块
Python
def make_task(id_task, **kwargs):
logger.info("Initializing task {}".format(id_task))
_task = registry.get_task(id_task)
assert _task is not None, "Could not find task with name {}".format(id_task)
return _task(**kwargs)
•
传感器实例化
(habitat-lab/habitat/sims/habitat_simulator/habitat_simulator.py)
传感器实例化没有函数,直接在habitat_simulator.py中定义,并设置habitat-sim环境。
代码块
Python
sim_sensors = []
for agent_config in self.habitat_config.agents.values():
从配置中读取每个智能体的传感器配置,然后使用registry.get_sensor获取传感器类,最后使用传感器配置创建传感器实例。
3) 依据配置设置habitat-sim环境
在前面对于yaml文件的处理后,将最终得到的配置用来设置habitat-sim环境。
Simulator 配置结构
代码块
Python
habitat.simulator
├── type: "Sim-v0" # 模拟器类型
├── scene_dataset: "data/scene_datasets/habitat-test-scenes" # 场景数据集路径
├── scene: "van-gogh-room.glb" # 当前场景
├── agents: # 智能体配置
│ └── rgbd_agent:
在HabitatSim类(habitat-lab/habitat/sims/habitat_simulator/habitat_simulator.py)的create_sim_config方法中,配置被转换为 Habitat-Sim 的内部配置格式。
代码块
Python
def create_sim_config(self, _sensor_suite: SensorSuite) -> habitat_sim.Configuration:
sim_config = habitat_sim.SimulatorConfiguration()
# 从Habitat Lab配置复制到Habitat-Sim配置
overwrite_config(
config_from=self.habitat_config.habitat_sim_v0,
config_to=sim_config,
Task 配置结构(PointNav 任务)
代码块
Python
在NavigationTask类(habitat-lab/habitat/tasks/nav/nav.py)的初始化过程中,配置被用于设置任务的各种属性:
代码块
Python
@registry.register_task(name="Nav-v0")
class NavigationTask(EmbodiedTask):
def __init__(
Agent 配置结构
代码块
Python
habitat.simulator.agents.rgbd_agent
├── height: 1.5 # 智能体高度
├── radius: 0.1 # 智能体半径
├── sim_sensors: # 传感器配置
│ ├── rgb_sensor:
│ │ ├── type: "HabitatSimRGBSensor"
│ │ ├── width: 256
│ │ └── height: 256
│ └── depth_sensor:
│ ├── type: "HabitatSimDepthSensor"
│ ├── width: 256
│ └── height: 256
├── start_position: [0.0, 0.0, 0.0] # 初始位置
在HabitatSim类(habitat-lab/habitat/sims/habitat_simulator/habitat_simulator.py)的create_sim_config方法中,智能体配置被转换为 Habitat-Sim 的内部格式:
代码块
Python
Sensor 配置结构
代码块
Python
habitat.simulator.agents.rgbd_agent.sim_sensors.rgb_sensor
├── type: "HabitatSimRGBSensor" # 传感器类型
├── width: 256 # 图像宽度
├── height: 256 # 图像高度
├── position: [0.0, 1.25, 0.0] # 传感器位置
├── orientation: [0.0, 0.0, 0.0] # 传感器方向
在传感器类的实现中(habitat-lab/habitat/sims/habitat_simulator/habitat_simulator.py),配置被用于设置传感器的属性:
代码块
Python
在HabitatSim类(habitat-lab/habitat/sims/habitat_simulator/habitat_simulator.py)的传感器初始化过程中,传感器配置被转换为 Habitat-Sim 的传感器规范:
代码块
Python
for sensor in _sensor_suite.sensors.values():
sim_sensor_cfg = sensor._get_default_spec()
# 从Habitat Lab配置复制到Habitat-Sim传感器配置
overwrite_config(
config_from=sensor.config,
config_to=sim_sensor_cfg,
ignore_keys=sensor._config_ignore_keys,
trans_dict={
"sensor_model_type": lambda v: getattr(habitat_sim.FisheyeSensorModelType, v),
"sensor_subtype": lambda v: getattr(habitat_sim.SensorSubType, v),
},
)
sim_sensor_cfg.uuid = sensor.uuid
sim_sensor_cfg.resolution = [sensor.observation_space.shape[1], sensor.observation_space.shape[0]]
sim_sensor_cfg.sensor_type = sensor.sim_sensor_type
sensor_specifications.append(sim_sensor_cfg)
habitat-lab的基础配置及其在代码中的运行过程介绍完毕,可以看出,habitat-lab的配置系统使得开发者可以灵活地创建各种复杂的具身 AI 环境,实现从简单导航到复杂操作任务的多样化应用。
参考资料: