habitat-基础使用记录
一些有用的参考:
- Habitat-sim: https://github.com/facebookresearch/habitat-sim - Doc: https://aihabitat.org/docs/habitat-sim/index.html 
- Tutorial: https://aihabitat.org/tutorial/2020/ 
 
- Doc: 
- Habitat-lab: https://github.com/facebookresearch/habitat-lab - Doc:https://aihabitat.org/docs/habitat-lab/ 
 
- Doc:
- 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 |  |