Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[breaking] - NavMeshSettings refactor #2111

Merged
merged 8 commits into from
May 31, 2023
2 changes: 1 addition & 1 deletion examples/motion_viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -584,10 +584,10 @@ def navmesh_config_and_recompute(self) -> None:
self.navmesh_settings = habitat_sim.NavMeshSettings()
self.navmesh_settings.set_defaults()
self.navmesh_settings.agent_radius = 0.30
self.navmesh_settings.include_static_objects = True
self.sim.recompute_navmesh(
self.sim.pathfinder,
self.navmesh_settings,
include_static_objects=True,
)

# Set all articulated objects back to original motion_type
Expand Down
5 changes: 2 additions & 3 deletions examples/tutorials/colabs/ECCV_2020_Interactivity.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -1063,9 +1063,8 @@
"# recompute the NavMesh with STATIC objects\n",
"navmesh_settings = habitat_sim.NavMeshSettings()\n",
"navmesh_settings.set_defaults()\n",
"navmesh_success = sim.recompute_navmesh(\n",
" sim.pathfinder, navmesh_settings, include_static_objects=True\n",
")\n",
"navmesh_settings.include_static_objects = True\n",
"navmesh_success = sim.recompute_navmesh(sim.pathfinder, navmesh_settings)\n",
"\n",
"# simulate and collect observations\n",
"example_type = \"clutter generation\"\n",
Expand Down
9 changes: 6 additions & 3 deletions examples/tutorials/colabs/ECCV_2020_Navigation.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -1011,9 +1011,12 @@
" # default = 1.0\n",
" # fmt: on\n",
"\n",
"navmesh_success = sim.recompute_navmesh(\n",
" sim.pathfinder, navmesh_settings, include_static_objects=False\n",
")\n",
" # @markdown **Include STATIC Objects**:\n",
" # @markdown Optionally include all instanced RigidObjects with STATIC MotionType as NavMesh constraints.\n",
" navmesh_settings.include_static_objects = True # @param {type:\"boolean\"}\n",
" # default = False\n",
"\n",
"navmesh_success = sim.recompute_navmesh(sim.pathfinder, navmesh_settings)\n",
"\n",
"if not navmesh_success:\n",
" print(\"Failed to build the navmesh! Try different parameters?\")\n",
Expand Down
5 changes: 2 additions & 3 deletions examples/tutorials/nb_python/ECCV_2020_Interactivity.py
Original file line number Diff line number Diff line change
Expand Up @@ -948,9 +948,8 @@ def build_widget_ui(obj_attr_mgr, prim_attr_mgr):
# recompute the NavMesh with STATIC objects
navmesh_settings = habitat_sim.NavMeshSettings()
navmesh_settings.set_defaults()
navmesh_success = sim.recompute_navmesh(
sim.pathfinder, navmesh_settings, include_static_objects=True
)
navmesh_settings.include_static_objects = True
navmesh_success = sim.recompute_navmesh(sim.pathfinder, navmesh_settings)

# simulate and collect observations
example_type = "clutter generation"
Expand Down
9 changes: 6 additions & 3 deletions examples/tutorials/nb_python/ECCV_2020_Navigation.py
Original file line number Diff line number Diff line change
Expand Up @@ -838,9 +838,12 @@ def display_map(topdown_map, key_points=None):
# default = 1.0
# fmt: on

navmesh_success = sim.recompute_navmesh(
sim.pathfinder, navmesh_settings, include_static_objects=False
)
# @markdown **Include STATIC Objects**:
# @markdown Optionally include all instanced RigidObjects with STATIC MotionType as NavMesh constraints.
navmesh_settings.include_static_objects = True # @param {type:"boolean"}
# default = False

navmesh_success = sim.recompute_navmesh(sim.pathfinder, navmesh_settings)

if not navmesh_success:
print("Failed to build the navmesh! Try different parameters?")
Expand Down
3 changes: 1 addition & 2 deletions examples/viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -882,11 +882,10 @@ def navmesh_config_and_recompute(self) -> None:
self.navmesh_settings.set_defaults()
self.navmesh_settings.agent_height = self.cfg.agents[self.agent_id].height
self.navmesh_settings.agent_radius = self.cfg.agents[self.agent_id].radius

self.navmesh_settings.include_static_objects = True
self.sim.recompute_navmesh(
self.sim.pathfinder,
self.navmesh_settings,
include_static_objects=True,
)

def exit_event(self, event: Application.ExitEvent):
Expand Down
5 changes: 4 additions & 1 deletion src/esp/bindings/ShortestPathBindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ void initShortestPathBindings(py::module& m) {
"filter_walkable_low_height_spans",
&NavMeshSettings::filterWalkableLowHeightSpans,
R"(Marks navigable spans as non-navigable if the clearence above the span is less than the specified height. Allows the formation of navigable regions that will flow over low lying objects such as curbs, and up structures such as stairways. Default True.)")
.def_readwrite(
"include_static_objects", &NavMeshSettings::includeStaticObjects,
R"(Whether or not to include STATIC RigidObjects as NavMesh constraints. Note: Used in Simulator recomputeNavMesh pre-process. Default False.)")
.def("set_defaults", &NavMeshSettings::setDefaults)
.def("read_from_json", &NavMeshSettings::readFromJSON,
R"(Overwrite these settings with values from a JSON file.)")
Expand Down Expand Up @@ -249,7 +252,7 @@ void initShortestPathBindings(py::module& m) {
"pt"_a, "max_y_delta"_a = 0.5)
.def_property_readonly("nav_mesh_settings",
&PathFinder::getNavMeshSettings,
R"(The settings for the current nav mesh)");
R"(The settings for the current NavMesh.)");

// this enum is used by GreedyGeodesicFollowerImpl so it needs to be defined
// before it
Expand Down
7 changes: 5 additions & 2 deletions src/esp/bindings/SimBindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ void initSimBindings(py::module& m) {
.def_readwrite(
"requires_textures", &SimulatorConfiguration::requiresTextures,
R"(Whether or not to load textures for the meshes. This MUST be true for RGB rendering.)")
.def_readwrite(
"navmesh_settings", &SimulatorConfiguration::navMeshSettings,
R"(Optionally provide a pre-configured NavMeshSettings. If provided, the NavMesh will be recomputed with the provided settings if: A. no NavMesh was loaded, or B. the loaded NavMesh's settings differ from the configured settings. If not provided, no NavMesh recompute will be done automatically.)")
.def_readwrite(
"PBR_image_based_lighting",
&SimulatorConfiguration::pbrImageBasedLighting,
Expand Down Expand Up @@ -269,8 +272,8 @@ void initSimBindings(py::module& m) {
R"(Enable or disable bounding box visualization for an object.)")
.def(
"recompute_navmesh", &Simulator::recomputeNavMesh, "pathfinder"_a,
"navmesh_settings"_a, "include_static_objects"_a = false,
R"(Recompute the NavMesh for a given PathFinder instance using configured NavMeshSettings. Optionally include all MotionType::STATIC objects in the navigability constraints.)")
"navmesh_settings"_a,
R"(Recompute the NavMesh for a given PathFinder instance using configured NavMeshSettings.)")
#ifdef ESP_BUILD_WITH_VHACD
.def(
"apply_convex_hull_decomposition",
Expand Down
2 changes: 1 addition & 1 deletion src/esp/nav/PathFinder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ bool operator==(const NavMeshSettings& a, const NavMeshSettings& b) {
CLOSE(edgeMaxError) && CLOSE(vertsPerPoly) &&
CLOSE(detailSampleDist) && CLOSE(detailSampleMaxError) &&
EQ(filterLowHangingObstacles) && EQ(filterLedgeSpans) &&
EQ(filterWalkableLowHeightSpans);
EQ(filterWalkableLowHeightSpans) && EQ(includeStaticObjects);

#undef CLOSE
#undef EQ
Expand Down
7 changes: 7 additions & 0 deletions src/esp/nav/PathFinder.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,12 @@ struct NavMeshSettings {
*/
bool filterWalkableLowHeightSpans{};

/**
* @brief Whether or not to include STATIC RigidObjects as NavMesh
* constraints. Note: Used in Simulator recomputeNavMesh pre-process.
*/
bool includeStaticObjects{};

void setDefaults() {
cellSize = 0.05f;
cellHeight = 0.2f;
Expand All @@ -274,6 +280,7 @@ struct NavMeshSettings {
filterLowHangingObstacles = true;
filterLedgeSpans = true;
filterWalkableLowHeightSpans = true;
includeStaticObjects = false;
}

//! Load the settings from a JSON file
Expand Down
31 changes: 22 additions & 9 deletions src/esp/sim/Simulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,14 +141,15 @@ void Simulator::reconfigure(const SimulatorConfiguration& cfg) {
sceneManager_ = scene::SceneManager::create_unique();
}

// This is a check to make sure that pathfinder_ is not null after
// a reconfigure. We check to see if it's null so that an existing
// one isn't overwritten.
if (!pathfinder_) {
pathfinder_ = nav::PathFinder::create();
}

// if configuration is unchanged, just reset and return
if (cfg == config_) {
// This is a check to make sure that pathfinder_ is not null after
// a reconfigure. We check to see if it's null so that an existing
// one isn't overwritten.
if (!pathfinder_) {
pathfinder_ = nav::PathFinder::create();
}
reset();
return;
}
Expand Down Expand Up @@ -209,6 +210,18 @@ void Simulator::reconfigure(const SimulatorConfiguration& cfg) {
<< "for active scene name :" << config_.activeSceneName
<< (config_.createRenderer ? " with" : " without") << "renderer.";

// Handle the NavMesh configuration
if (config_.navMeshSettings != nullptr &&
Cr::Utility::String::lowercase(config_.activeSceneName) != "none") {
// If the NavMesh is unloaded or does not match the requested configuration
// then recompute it.
if (!pathfinder_->isLoaded() ||
(pathfinder_->getNavMeshSettings() != *config_.navMeshSettings)) {
ESP_DEBUG() << "NavMesh recompute was necessary.";
recomputeNavMesh(*pathfinder_, *config_.navMeshSettings);
}
}

} // Simulator::reconfigure

bool Simulator::createSceneInstance(const std::string& activeSceneName) {
Expand Down Expand Up @@ -896,9 +909,9 @@ double Simulator::getPhysicsTimeStep() {
}

bool Simulator::recomputeNavMesh(nav::PathFinder& pathfinder,
const nav::NavMeshSettings& navMeshSettings,
const bool includeStaticObjects) {
assets::MeshData::ptr joinedMesh = getJoinedMesh(includeStaticObjects);
const nav::NavMeshSettings& navMeshSettings) {
assets::MeshData::ptr joinedMesh =
getJoinedMesh(navMeshSettings.includeStaticObjects);

if (!pathfinder.build(navMeshSettings, *joinedMesh)) {
ESP_ERROR() << "Failed to build navmesh";
Expand Down
3 changes: 1 addition & 2 deletions src/esp/sim/Simulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -590,8 +590,7 @@ class Simulator {
* @return Whether or not the navmesh recomputation succeeded.
*/
bool recomputeNavMesh(nav::PathFinder& pathfinder,
const nav::NavMeshSettings& navMeshSettings,
bool includeStaticObjects = false);
const nav::NavMeshSettings& navMeshSettings);

/**
* @brief Get the joined mesh data for all objects in the scene
Expand Down
3 changes: 2 additions & 1 deletion src/esp/sim/SimulatorConfiguration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ bool operator==(const SimulatorConfiguration& a,
a.sceneDatasetConfigFile == b.sceneDatasetConfigFile &&
a.physicsConfigFile == b.physicsConfigFile &&
a.overrideSceneLightDefaults == b.overrideSceneLightDefaults &&
a.sceneLightSetupKey == b.sceneLightSetupKey;
a.sceneLightSetupKey == b.sceneLightSetupKey &&
a.navMeshSettings == b.navMeshSettings;
}

bool operator!=(const SimulatorConfiguration& a,
Expand Down
12 changes: 12 additions & 0 deletions src/esp/sim/SimulatorConfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@
#ifndef ESP_SIM_SIMULATORCONFIGURATION_H_
#define ESP_SIM_SIMULATORCONFIGURATION_H_

#include <Corrade/Containers/Optional.h>
aclegg3 marked this conversation as resolved.
Show resolved Hide resolved
#include <string>

#include "esp/core/Esp.h"
#include "esp/nav/PathFinder.h"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be forward-declared as this class is widely used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I thought so too. However, the compiler does not like the forward declaration here, so I needed the full the include.

#include "esp/physics/configure.h"

namespace Cr = Corrade;

namespace esp {

namespace sim {
Expand Down Expand Up @@ -92,6 +96,14 @@ struct SimulatorConfiguration {
*/
bool useSemanticTexturesIfFound = true;

/**
* @brief Optionally provide a pre-configured NavMeshSettings. If provided,
* the NavMesh will be recomputed with the provided settings if A. no NavMesh
* was loaded, or B. the loaded NavMesh's settings differ from the configured
* settings. If not provided, no NavMesh recompute will be done automatically.
*/
nav::NavMeshSettings::ptr navMeshSettings = nullptr;

ESP_SMART_POINTERS(SimulatorConfiguration)
};
bool operator==(const SimulatorConfiguration& a,
Expand Down
9 changes: 6 additions & 3 deletions src/tests/SimTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -474,13 +474,15 @@ void SimTest::recomputeNavmeshWithStaticObjects() {
simulator->getPathFinder()->isNavigable({randomNavPoint}, 0.1));

// recompute with object
navMeshSettings.includeStaticObjects = true;
simulator->recomputeNavMesh(*simulator->getPathFinder().get(),
navMeshSettings, true);
navMeshSettings);
CORRADE_VERIFY(!simulator->getPathFinder()->isNavigable(randomNavPoint, 0.1));

// recompute without again
navMeshSettings.includeStaticObjects = false;
simulator->recomputeNavMesh(*simulator->getPathFinder().get(),
navMeshSettings, false);
navMeshSettings);
CORRADE_VERIFY(simulator->getPathFinder()->isNavigable(randomNavPoint, 0.1));

rigidObjMgr->removePhysObjectByHandle(obj->getHandle());
Expand All @@ -499,8 +501,9 @@ void SimTest::recomputeNavmeshWithStaticObjects() {
CORRADE_VERIFY(
simulator->getPathFinder()->isNavigable(randomNavPoint + offset, 0.2));
// recompute with object
navMeshSettings.includeStaticObjects = true;
simulator->recomputeNavMesh(*simulator->getPathFinder().get(),
navMeshSettings, true);
navMeshSettings);
CORRADE_VERIFY(!simulator->getPathFinder()->isNavigable(randomNavPoint, 0.1));
CORRADE_VERIFY(
simulator->getPathFinder()->isNavigable(randomNavPoint + offset, 0.2));
Expand Down
3 changes: 2 additions & 1 deletion src/utils/viewer/viewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1126,8 +1126,9 @@ void Viewer::initSimPostReconfigure() {
esp::nav::NavMeshSettings navMeshSettings;
navMeshSettings.agentHeight = agentConfig_.height;
navMeshSettings.agentRadius = agentConfig_.radius;
navMeshSettings.includeStaticObjects = true;
simulator_->recomputeNavMesh(*simulator_->getPathFinder().get(),
navMeshSettings, true);
navMeshSettings);
} else if (!navmeshFilename_.empty()) {
std::string navmeshFile = Cr::Utility::Path::join(
*Corrade::Utility::Path::currentDirectory(), navmeshFilename_);
Expand Down
48 changes: 3 additions & 45 deletions src_python/habitat_sim/simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import time
from collections import OrderedDict
from collections.abc import MutableMapping
from os import path as osp
from typing import Any, Dict, List
from typing import MutableMapping as MutableMapping_T
from typing import Optional, Union, cast, overload
Expand All @@ -31,7 +30,7 @@
from habitat_sim.bindings import cuda_enabled
from habitat_sim.logging import LoggingContext, logger
from habitat_sim.metadata import MetadataMediator
from habitat_sim.nav import GreedyGeodesicFollower, NavMeshSettings
from habitat_sim.nav import GreedyGeodesicFollower
from habitat_sim.sensor import SensorSpec, SensorType
from habitat_sim.sensors.noise_models import make_sensor_noise_model
from habitat_sim.sim import SimulatorBackend, SimulatorConfiguration
Expand Down Expand Up @@ -210,52 +209,11 @@ def _config_agents(self, config: Configuration) -> None:
]

def _config_pathfinder(self, config: Configuration) -> None:
scene_basename = osp.basename(config.sim_cfg.scene_id)
# "mesh.ply" is identified as a replica model, whose navmesh
# is named as "mesh_semantic.navmesh" and is placed in the
# subfolder called "habitat" (a level deeper than the "mesh.ply")
if scene_basename == "mesh.ply":
scene_dir = osp.dirname(config.sim_cfg.scene_id)
navmesh_filename = osp.join(scene_dir, "habitat", "mesh_semantic.navmesh")
else:
navmesh_filename = osp.splitext(config.sim_cfg.scene_id)[0] + ".navmesh"

if osp.exists(navmesh_filename) and not self.pathfinder.is_loaded:
self.pathfinder.load_nav_mesh(navmesh_filename)
logger.info(f"Loaded navmesh {navmesh_filename}")

# NOTE: this recomputed NavMesh does not include STATIC objects.
needed_settings = NavMeshSettings()
default_agent_config = config.agents[config.sim_cfg.default_agent_id]
needed_settings.agent_radius = default_agent_config.radius
needed_settings.agent_height = default_agent_config.height
if (
# If we loaded a navmesh and we need one with different settings,
# always try and recompute
(
self.pathfinder.is_loaded
and self.pathfinder.nav_mesh_settings != needed_settings
)
# If we didn't load a navmesh, only try to recompute one if we can.
# This allows for use cases where we just want to view a single
# object or similar.
or (
not self.pathfinder.is_loaded
and config.sim_cfg.scene_id.lower() != "none"
)
):
logger.info(
f"Recomputing navmesh for agent's height {default_agent_config.height} and radius"
f" {default_agent_config.radius}."
)
self.recompute_navmesh(self.pathfinder, needed_settings)

self.pathfinder.seed(config.sim_cfg.random_seed)

if not self.pathfinder.is_loaded:
if self.pathfinder is None or not self.pathfinder.is_loaded:
logger.warning(
"Could not find a navmesh nor could one be computed, "
"no collision checking will be done"
"Navmesh not loaded or computed, no collision checking will be done."
)

def reconfigure(self, config: Configuration) -> None:
Expand Down
Loading