habitat-基础使用记录
一些有用的参考:
- Habitat-sim: https://github.com/facebookresearch/habitat-sim
- Doc: https://aihabitat.org/docs/habitat-sim/index.html
- Tutorial: https://aihabitat.org/tutorial/2020/
- Habitat-lab: https://github.com/facebookresearch/habitat-lab
- Doc:https://aihabitat.org/docs/habitat-lab/
- Resource Index: https://aihabitat.org/docs/resource_index/
Habitat-Sim Usage
首先介绍一些核心的概念,这些概念会贯穿整个使用流程。
Agent
:在场景中的Agent,能够观察场景以及与场景进行交互Sensor
:装配在Agent上的各种传感器,能够对环境进行感知,包括视觉信息、深度信息等Scene
:场景的模拟3D环境Simulator
:模拟器,融合上面的概念,进行模拟
Habitat-Sim的基础运行流程可以总结为:配置并启动simulator(habitat_sim.simulator.Simulator),加载scene,配置带有sensor的agent(habitat_sim.agent.Agent),执行action,获取sensor观察结果(rgb、semantic、depth等)
1 |
|
创建Simulator,需要利用config(habitat_sim.simulator.Configuration)来指定相关配置,主要包括:
For simulator backend:指定要加载的场景,是否加载语义mesh、是否启用物理等
For agent:给定Agent的初始化参数,包括高度、质量、Agent相关的Sensor、每次移动的物理量等
根据官方给的入门教程,我们同样列举如下的一些概念:
NavMesh:用于指定场景中的可导航区域。habitat中提供pathfinder可以用来加载或者构建NavMash,然后在上面进行点采样、路径查找、碰撞等查询
1 |
|
island_radius
:最小包含圆是指能够包含所有属于该导航岛屿的点的最小圆。island_radius 是这个圆的半径。导航岛屿中的点的质心(中心点)是这个圆的圆心。island_radius 参数表示的是一个点所属的连通组件(connected component)的大小。island_radius 可以用来验证一个点是否在一个有意义的导航表面上,例如地板。如果一个点的island_radius值很小,这意味着该点可能位于一个小的、孤立的表面上,比如桌面或椅子,而不是一个大的、连续的表面如地板。这有助于过滤掉那些不适合导航的点,确保AI代理只在合理的、可导航的表面上移动。Snap Point
:在导航和路径规划领域,特别是在模拟和机器人研究中,“snap point” 通常指的是将一个查询点调整(或“吸附”)到最接近的有效导航点的过程。这个概念用于确保AI代理或机器人在导航时始终位于可导航的表面上,而不是在无效的或无法导航的区域。- 重新计算NavMesh参考:Digesting Duck: Recast Settings Uncovered)
Sliding:Agent的滑动操作。这是一个配置选项,表示Agent是否能够沿着障碍进行滑动sim.config.sim_cfg.allow_sliding
。需要注意的是,滑动和连续动作空间并不是同一个概念。允许滑动可以使训练更加容易,产生更高的模拟性能,但是会损害训练策略的sim2real性能。
入门教程中还提供了如下参考资料:
Navigation:Habitat Lab for Navigation|YouTube
Interactivity 物理/交互性:Habitat-Sim Interactivity|YouTube
强化学习任务训练:
Advanced Topic:Habitat-Sim Advanced Topics|YouTube
- Tracking object motion with a camera:跟踪某个对象的运动
- Projecting 3D points into 2D:将3D空间的点投影到2D平面
- Configuring semantic ids for objects:为物体配置语义ID
- Object/Asset configuration via template libraries
- Object attributes:修改对象的属性模版,然后以此重新实例化得到新的对象object
- Asset attributes:3d相关的特征,例如mesh数量等,是否是实体,几何形状等信息
Habitat-Lab Usage
Habitat-Lab是一个模块化的高级库,它在Habitat-sim的基础上构建,可以完成相关操作,包括定义具身AI任务(例如导航、指令跟随、问答)、配置具身Agent、训练Agent、在定义任务上进行基准测试。下面是一个Quick Start,允许我们通过键盘操作完成一个PointNav任务(完整实现可以参考quick-start,这里只保留了一些关键代码便于说明):
1 |
|
完整quick-start中的可视化功能是通过cv2提供的,与habitat-sim是否使用headless没有关系
habitcat.Env:其中抽象了利用simulator处理emnodied task所需的所有信息,包括dataset(episodes),simulator(sim)和EmbodiedTask(task)
- Env通过config来完成初始化,config中配置sensor和agent等信息
- config可以是一个文件,其中指定默认值,然后通过habitat.get_config来获取。配置管理系统使用hydra。配置系统可以参考README、config key
- 所有的config基本配置都在
habitat-lab/habitat/config
中 - 也可以通过read_write来更新默认值:
1 |
|
simulator.Simulator:Abstract Simulator,要添加到habitat中的新Simulator都需要继承该类并实现抽象方法
embodied_task.EmbodiedTask:Abstract Embodied Task,包括任务定义相关的action space、observation space、measures、simulator usage

上图是Habitat的架构说明,包含如下关键概念:
- habitat.sims.habitat_simulator.HabitatSim:habitat_sim的轻量级封装,提供与实验框架的无缝集成
- habitat.core.env.Env:智能体、任务和模拟器的抽象。你训练和评估的智能体在这个环境中运行
- habitat.core.env.RLEnv:通过定义奖励和其他必需组件,扩展Env类以用于强化学习
- habitat.core.embodied_task.EmbodiedTask:定义智能体需要解决的任务。这个类包含观察空间、动作空间、度量、模拟器使用的定义。例如:PointNav, ObjectNav
- habitat.core.dataset.Dataset:包含具身任务数据集所需信息的封装,包含episode的定义和交互
- habitat.core.embodied_task.Measure:定义具身任务的度量标准,例如:SPL
- habitat_baselines:不同具身任务的强化学习、SLAM、启发式基线实现
Habitat-Baseline Usage
Habitat-Baseline是Habitat官方提供的一套用于训练和评估 AI 智能体的强化学习基线算法集合,构建于Habitat-Lab之上,提供了可直接使用的训练框架和模型实现。它是用于在 Habitat 环境中快速训练智能体的“开箱即用”工具,广泛用于导航、探索、任务完成等研究。
一个典型的运行流程如下:
- 通过
habitat-baselines.run.execute_exp
来启动整个流程 - 通过Trainer来进行训练和评估,类似Pytorch-Lightning的管理方式
- 通过config中的trainer name来初始化Trainer,默认实现是PPO Trainer
- 需要通过
@baseline_registry.register_trainer
来将其他Trainer实现注册到系统中 - 根据配置中的
cfg.habitat_baselines.evaluate
来选择走Trainer.train()还是Trainer.eval()
- Trainer中包括重要属性,Agent和Envs
- 通过_init_envs()来初始化VectorEnv
- VectorEnv就是多个envs组成的,可以同时运行多个Envs来加速训练。VectorEnv维护多个进程Process,每个进程会有一个worker_env,对应config.habitat.env_task.GymHabitatEnv
- 这个Env同样是可以注册的
@habitat.registry.register_env(*name*="GymHabitatEnv")
- 这个Env同样是可以注册的
- 而这个Env中又包含一个成员是RLTaskEnv -> habitat.RLEnv -> Env,最终和Habitat-sim中的Env联系在一起
- VectorEnv就是多个envs组成的,可以同时运行多个Envs来加速训练。VectorEnv维护多个进程Process,每个进程会有一个worker_env,对应config.habitat.env_task.GymHabitatEnv
- 通过Trainer中的env.step()来驱动所有的Env和Agent等。这个也是Habitat-Lab Trainer和Habitat-sim Env之间的核心桥梁
在Habitat-sim和Habitat-lab中包含多种Env的定义,它们可能是相互嵌套的关系,实际使用过程中需要明确每个Env究竟是什么Class
- 核心步骤的源码追踪如下:
1 |
|
- 对应的实现在RLEnv
1 |
|
使用记录
坐标系约定
关于坐标系的教程可以参考坐标系教程。核心概念包括:
- 世界坐标系:高度轴为y,并且遵循右手系
- 物体坐标系:高度轴为y,并且遵循右手系,同时物体中心为原点
- 相机坐标系:-z(blue)指向前方,y(green)指向上方,x(red)轴指向右方「opengl」

Dataset加载-以Replica为例
在Habitat中,支持的Dataset需要满足一定的组织格式,可以参考文档
顶层描述文件xxx.scene_dataset_config.json
- 子属性包括:
- stage:构成场景背景的mesh组件,对于室内场景来说就是一个空房间的mesh
- objects: 物体
- articulated_objects:铰链物体
- lights_setup:光照设置
- scene_instances:场景描述
- semantic_scene_descriptor_instances:语义场景
- navmesh_instances: NavMesh描述
- 每个子属性都可以用一个json来描述「json路径或者JSON Object」
- stage:一个场景只能有一个stage_instance
- 在json文件中配置的路径为相对路径
- user_defined:可以在任意json文件中叠加。并且 Habitat-sim 功能既不依赖于也不处理此标签下的任何特定元数据。您可以使用此标签缓存特定使用案例的对象信息,或在用户代码中跟踪一段时间内的模拟属性。
这里我们记录了一些相关Issue:
- Replica数据加载,参考issue1782
- 指定xxx.scene_dataset_config.json, scene_id
- 可以像参考程序一样直接加载glb,也可以像Replica一样加载ply,参考issue63
- scene_dataset_config.json内容说明,围绕此来构造集成自己的数据集,参考issue2353
[habitat-sim]获取Agent和Sensor的state
以下代码可以获取Agent的state:
1 |
|
agent的position是当前所在地面位置的全局坐标「注意agent必须贴地行走」
agent的旋转与sensor的旋转相同
以下代码可以获取sensor的state:
1 |
|
分别返回position和rotation「一共六个数字」,相当于相机的外参
注意sensor的状态和agent的状态并不存在绝对的联系
sensor参数的获取:尤其是内参的获取
[habitat-sim]获取observation
在Habitat-sim中可以通过以下两种方式来获取observation:
1 |
|
[habitat-sim]获取场景语义信息
- 参考:https://github.com/facebookresearch/habitat-sim/issues/2364
[habitat-sim]使用ShortestFollower
在Habitat-sim中使用ShortedFollower,可以参考样例Notebook
[habitat-lab]获取state
在Habitat-lab中获取Agent的state:
1 |
|
Sensor的state则包含在agent的state中。
[habitat-lab]构造new sensor
这里说明如何构造simulator.sim_sensor
在Config系统中注册相关配置。config系统可以参考文档
如果需要额外的配置信息,也需要在config中指定增加配置
实现相关的类型,进行register
- 在Habitat中,如果不给@registry.register_sensor装饰器指定名字参数,它会使用类名作为默认的注册名。
目前可用的config key,可以参考文档
注意simluator.sim_sensor在最终配置系统中Package的变化:
- ```Bash /gsim/simulator/sensors@habitat.simulator.agents.main_agent:
gs_rgb_sensor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
## [habitat-lab]构造基于ReplicaCAD的PointNav
引入ReplicaCAD的关键在于Env中的Sim配置需要对齐,包括scene_dataset_config_json的指定,以及scene_id的指定。这里列出了一些需要解决的问题
- sim使用的是封装了habitat_sim的[HabtatSim](https://github.com/facebookresearch/habitat-lab/blob/main/habitat-lab/habitat/sims/habitat_simulator/habitat_simulator.py#L269)
- habitat_sim的config和habitat_lab的config之间关键参数的对应「[reference](https://github.com/facebookresearch/habitat-lab/blob/main/habitat-lab/habitat/sims/habitat_simulator/habitat_simulator.py#L324-L327)」
- habitat_sim.config.scene_dataset_config.file <=> habitat_lab.config.simulator.scene_datset
- habitat_sim.config.scene_id <=> habitat_lab.config.scene
- habitat_lab.config.simulator.scene=habitat_lab.config.simulator.scene_dir + episode.scene_id「in train.json」
- 我们不能够直接在habitat-lab yaml中指定habitat.simulator.scene_dataset,因为它会被episode中的scene_dataset_config覆盖「[reference](https://github.com/facebookresearch/habitat-lab/blob/main/habitat-lab/habitat/core/env.py#L104-L108)」
因此最终的解决方案是:
- 在yaml中如下指定,其中scene_dir设置为空字符串:
```yaml
# @package _global_
defaults:
- pointnav_base
- _self_
habitat:
environment:
max_episode_steps: 500
simulator:
agents:
main_agent:
sim_sensors:
rgb_sensor:
width: 256
height: 256
depth_sensor:
width: 256
height: 256
dataset:
type: PointNav-v1
split: train
data_path: data/datasets/pointnav/replica_cad_test/v1/{split}/{split}.json.gz
scenes_dir: ""
- ```Bash /gsim/simulator/sensors@habitat.simulator.agents.main_agent:
gs_rgb_sensor
在train.json中如下指定,其中通过scene_dataset_config指定为对应的json路径
1 |
|
- 这里还需要注意rotation的指定,在train.json中指定的start_rotation的顺序是
(x, y, z, w)
「reference」,但是在agent中获得的rotation输出的顺序是(w, x, y, z)
「该rotation的类型是quaternion.quaternion,这个类对应的顺序是wxyz」
[habitat-lab]获取habitat-sim相关的配置内容
在habitat-lab中,可以通过某种方式获取到scene_dataset_config.json
里面的内容。关于Config属性可以参考说明文档。要获取对应的Config属性,需要获取template_manager,然后获取其中的key。
- 相关manager:reference
- MetadataMediator:管理dataset层级的config,可以获取scene的list
- StageAttributesManager:管理stage层级的config
- ObjectAttributesManager:管理object层级的config
- Attributes对应的C++实现位置
- stage和object的缩放和平移在两个配置文件中有定义
- stage:「stage的缩放好像没有生效?」
- stage_config.json中
- up: y
- front: -z
- origin: xyz
- scale: 缩放
- scene_instance.json中的stage_instance:
- translation xyz
- rotation wxyz
- uniform_scale
- non_uniform_scale
- stage_config.json中
- object:
- object_config.json中
- up:y
- front:-z
- COM:xyz
- scale:缩放
- scene_instance.json中的object_instances:
- translation xyz
- rotation wxyz
- uniform_scale
- non_uniform_scale
- object_config.json中
- stage:「stage的缩放好像没有生效?」
[habitat-lab]episode切换的流程
以下主要介绍在habitat-lab中切换episode实际上经过的操作:
- 首先在初始化Env的时候,会依次初始化dataset「List of Episode」,sim「simulator」和task 「EmbodiedTask」
- 通过env.reset()进行episode的切换
- 获取next episode
- Reconfigure
- task.overwrite_sim_config
- sim.reconfigure(simulator_config+current_episode)
- 在task中进行reset
- task.mesurements.rest_measures():重置相关指标
- 但是需要注意的是next epsiode的处理逻辑,它并不是完全按照顺序一个个给出指定的env.episodes中的值,而是会构造一个迭代器,这个迭代器中顺序会尽可能减少场景的切换,参考habitat-lab中的EpisodeIterator
[habitat-lab]实现过程中场景物体的控制
在habitat-lab中,我们可以在过程中控制场景中的物体,包括物体的种类、位置等。一种实现思路是:在episode的描述文件中添加需要在该episode中加入的物体,然后在切换episode的时候,将对应的物体加载到场景中。其中的核心类是habitat_sim中的RigidObjectManager「动态管理的API参考」
1 |
|