diff --git a/.circleci/config.yml b/.circleci/config.yml index 76112c33096db389f4b85096ba22cf629422e27f..206edb0163b0f73d84cf78c253999a4e98a6320e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -25,8 +25,8 @@ jobs: - run: name: run isort command: | - isort . -rc --multi-line 3 --trailing-comma --force-grid-wrap 0 --line-width 79 --combine-as -o torch -o pytest -o torchvision -o matplotlib --diff - isort . -rc --multi-line 3 --trailing-comma --force-grid-wrap 0 --line-width 79 --combine-as -o torch -o pytest -o torchvision -o matplotlib --check-only + isort . -rc --multi-line 3 --trailing-comma --force-grid-wrap 0 --line-width 79 --combine-as -o torch -o pytest -o torchvision -o matplotlib -p habitat_sim --diff + isort . -rc --multi-line 3 --trailing-comma --force-grid-wrap 0 --line-width 79 --combine-as -o torch -o pytest -o torchvision -o matplotlib -p habitat_sim --check-only install_and_test_ubuntu: <<: *gpu diff --git a/configs/README.md b/configs/README.md new file mode 100644 index 0000000000000000000000000000000000000000..c564d4d9ff2b9cca16b784a8c4b5890bc2973bf1 --- /dev/null +++ b/configs/README.md @@ -0,0 +1,103 @@ +Habitat-API Configuration +============================== + +Habitat-API uses [Yacs configuration system](https://github.com/rbgirshick/yacs) +with the paradigm of `your code + a YACS config for experiment E (+ +external dependencies + hardware + other nuisance terms ...) = +reproducible experiment E`. Yacs advantages: +- Checks for type consistency. +- All parameters and default values are searchable in the code. +- A parameter doesn't need to be set always as each parameter has a + default value. +- Ability to freeze config to prevent unintended changes. + +## Config usage +An example of how to merge default config with 2 others configs and overwrite +one parameter that could come from the command line: +``` + merged_config = get_config( + config_paths=["configs/tasks/pointnav.yaml", + "configs/dataset/val.yaml"], + opts=["ENVIRONMENT.MAX_EPISODE_STEPS", steps_limit] + ) + +``` + +## Config structure +Below is the structure of config used for Habitat: +- Environment +- Task + - Sensors + - Measurements +- Simulator + - Agent + - Sensors +- Dataset + +We use node names (e.g. `SENSORS: ['RGB_SENSOR', 'DEPTH_SENSOR']`) instead of list +of config nodes (e.g. `SENSORS: [{TYPE = "HabitatSimDepthSensor", +MIN_DEPTH = 0}, ...]`) to declare the Sensors attached to an Agent or Measures +enabled for the Task . With this approach, it's still easy to overwrite a +particular sensor parameter in yaml file without redefining the whole sensor +config. + +## Extending the config +Example of how to extend a config outside of `habtiat-api` repository. +First, we create a config extending the default config in the code and re-use +`habitat.get_config()`: +``` +import habitat +import argparse +from typing import List, Optional, Union + +_C = habitat.get_config() +_C.defrost() +# Add new parameters to the config +_C.TASK.EPISODE_INFO = habitat.Config() +_C.TASK.EPISODE_INFO.TYPE = "EpisodeInfo" +_C.TASK.EPISODE_INFO.VALUE = 5 +_C.TASK.MEASUREMENTS.append("EPISODE_INFO") + +# New function returning extended Habitat config that should be used instead +# of habitat.get_config() +def my_get_config( + config_paths: Optional[Union[List[str], str]] = None, + opts: Optional[list] = None, +) -> habitat.Config: + CONFIG_FILE_SEPARATOR = "," + config = _C.clone() + if config_paths: + if isinstance(config_paths, str): + if CONFIG_FILE_SEPARATOR in config_paths: + config_paths = config_paths.split(CONFIG_FILE_SEPARATOR) + else: + config_paths = [config_paths] + + for config_path in config_paths: + config.merge_from_file(config_path) + + if opts: + config.merge_from_list(opts) + + config.freeze() + return config + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--task-config", + type=str, + default="configs/tasks/pointnav.yaml," + "configs/datasets/pointnav/habitat_test.yaml", + ) + parser.add_argument( + "opts", + default=None, + nargs=argparse.REMAINDER, + help="Modify config options from command line", + ) + args = parser.parse_args() + config = my_get_config(config_paths=args.task_config, opts=args.opts) + env = habitat.Env(config) + +``` \ No newline at end of file diff --git a/docs/source/conf.py b/docs/source/conf.py index 44327f530754e438e206238ff0c01ee5b84af9c7..317c59a6fe84f7a7bdb6998214d26cdb5b02b567 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -1,4 +1,9 @@ #!/usr/bin/env python3 + +# Copyright (c) Facebook, Inc. and its affiliates. +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + # -*- coding: utf-8 -*- # # habitat-api documentation build configuration file, created by diff --git a/examples/register_new_sensors_and_measures.py b/examples/register_new_sensors_and_measures.py index a7bb634cc4b7f1ce18ea0320c9c1314eef13ec10..a857f18662c2912fd144dc2f992404ca9f0575d1 100644 --- a/examples/register_new_sensors_and_measures.py +++ b/examples/register_new_sensors_and_measures.py @@ -1,17 +1,22 @@ +#!/usr/bin/env python3 + +# Copyright (c) Facebook, Inc. and its affiliates. +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + from typing import Any import numpy as np from gym import spaces import habitat -from habitat.config import Config as CN # Define the measure and register it with habitat # By default, the things are registered with the class name @habitat.registry.register_measure class EpisodeInfo(habitat.Measure): - def __init__(self, sim, config): + def __init__(self, sim, config, **kwargs: Any): # This measure only needs the config self._config = config @@ -38,7 +43,7 @@ class EpisodeInfo(habitat.Measure): # For the sensor, we will register it with a custom name @habitat.registry.register_sensor(name="my_supercool_sensor") class AgentPositionSensor(habitat.Sensor): - def __init__(self, sim, config): + def __init__(self, sim, config, **kwargs: Any): super().__init__(config=config) self._sim = sim @@ -73,7 +78,7 @@ def main(): config.defrost() # Add things to the config to for the measure - config.TASK.EPISODE_INFO = CN() + config.TASK.EPISODE_INFO = habitat.Config() # The type field is used to look-up the measure in the registry. # By default, the things are registered with the class name config.TASK.EPISODE_INFO.TYPE = "EpisodeInfo" @@ -82,7 +87,7 @@ def main(): config.TASK.MEASUREMENTS.append("EPISODE_INFO") # Now define the config for the sensor - config.TASK.AGENT_POSITION_SENSOR = CN() + config.TASK.AGENT_POSITION_SENSOR = habitat.Config() # Use the custom name config.TASK.AGENT_POSITION_SENSOR.TYPE = "my_supercool_sensor" config.TASK.AGENT_POSITION_SENSOR.ANSWER_TO_LIFE = 42 diff --git a/habitat/datasets/pointnav/pointnav_generator.py b/habitat/datasets/pointnav/pointnav_generator.py index 8b08174be56e7e277b8456c443a63d828c8190bd..047876adf5c3723e1f54f4185620128b8d44ade6 100644 --- a/habitat/datasets/pointnav/pointnav_generator.py +++ b/habitat/datasets/pointnav/pointnav_generator.py @@ -1,3 +1,9 @@ +#!/usr/bin/env python3 + +# Copyright (c) Facebook, Inc. and its affiliates. +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + from typing import Optional import numpy as np diff --git a/habitat/datasets/utils.py b/habitat/datasets/utils.py index 918096a53588c8c1c0a128b4614b3f0f974a72e8..67395525c90072e9505a3575e7a238c1d8dd51e3 100644 --- a/habitat/datasets/utils.py +++ b/habitat/datasets/utils.py @@ -1,3 +1,9 @@ +#!/usr/bin/env python3 + +# Copyright (c) Facebook, Inc. and its affiliates. +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + from typing import List from habitat.core.logging import logger diff --git a/habitat_baselines/README.md b/habitat_baselines/README.md index 242d07e09fcff5e962aab6bc2b29afd770249d20..f3150a210a034a5fb4e48116cb10cd287bc8430c 100644 --- a/habitat_baselines/README.md +++ b/habitat_baselines/README.md @@ -76,4 +76,5 @@ Set argument `--task-config` to `tasks/pointnav_mp3d.yaml` for training on [Matt **SLAM based** -- [Handcrafted agent baseline adopted from the paper "Benchmarking Classic and Learned Navigation in Complex 3D Environments"](habitat_baselines/slambased/README.md) +- [Handcrafted agent baseline](slambased/README.md) adopted from the paper +"Benchmarking Classic and Learned Navigation in Complex 3D Environments". diff --git a/habitat_baselines/agents/slam_agents.py b/habitat_baselines/agents/slam_agents.py index b7694e826f5d42bd9134c598ac20e5c64b679880..846584062e01a202fd8e36c8ef27937e66796f88 100644 --- a/habitat_baselines/agents/slam_agents.py +++ b/habitat_baselines/agents/slam_agents.py @@ -1,3 +1,9 @@ +#!/usr/bin/env python3 + +# Copyright (c) Facebook, Inc. and its affiliates. +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + import argparse import os import random diff --git a/test/test_demo_notebook.py b/test/test_demo_notebook.py index fe756c436fb77f3aec764948ec920b192e1f1732..ca4e5ad23927aa2a04ce73f0ca6867f031101e56 100644 --- a/test/test_demo_notebook.py +++ b/test/test_demo_notebook.py @@ -1,4 +1,8 @@ -import os +#!/usr/bin/env python3 + +# Copyright (c) Facebook, Inc. and its affiliates. +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. import pytest diff --git a/test/test_relative_camera.py b/test/test_relative_camera.py index c85b1cbdb04525aabe2e36afde2f0b2b9ab21e63..fd87dff85d4fa9effa736349c0776fa41fdd77af 100644 --- a/test/test_relative_camera.py +++ b/test/test_relative_camera.py @@ -1,4 +1,8 @@ -import os +#!/usr/bin/env python3 + +# Copyright (c) Facebook, Inc. and its affiliates. +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. import pytest