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

Recompute NavMesh with STATIC RigidObjects #538

Merged
merged 16 commits into from
Mar 27, 2020
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions habitat_sim/simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,12 @@ def contact_test(self, object_id, scene_id=0):
def get_world_time(self, scene_id=0):
return self._sim.get_world_time()

def recompute_navmesh(self, pathfinder, navmesh_settings):
return self._sim.recompute_navmesh(pathfinder, navmesh_settings)
def recompute_navmesh(
self, pathfinder, navmesh_settings, include_static_objects=False
):
return self._sim.recompute_navmesh(
pathfinder, navmesh_settings, include_static_objects
)

# --- lighting functions ---
def get_light_setup(self, key=DEFAULT_LIGHTING_KEY):
Expand Down
8 changes: 7 additions & 1 deletion src/esp/assets/ResourceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -758,14 +758,20 @@ int ResourceManager::getObjectID(const std::string& configFile) {
std::find(physicsObjectConfigList_.begin(),
physicsObjectConfigList_.end(), configFile);
if (itr == physicsObjectConfigList_.cend()) {
return -1;
return ID_UNDEFINED;
} else {
int objectID = std::distance(physicsObjectConfigList_.begin(), itr);
return objectID;
}
}

std::string ResourceManager::getObjectConfig(const int objectID) {
if (physicsObjectConfigList_.size() <= objectID) {
aclegg3 marked this conversation as resolved.
Show resolved Hide resolved
Corrade::Utility::Debug() << "ResourceManager::getObjectConfig - Aborting. "
"No template with index "
<< objectID;
return "";
}
return physicsObjectConfigList_[objectID];
}

Expand Down
2 changes: 1 addition & 1 deletion src/esp/bindings/SimBindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ void initSimBindings(py::module& m) {
.def("contact_test", &Simulator::contactTest, "object_id"_a,
"sceneID"_a = 0)
.def("recompute_navmesh", &Simulator::recomputeNavMesh, "pathfinder"_a,
"navmesh_settings"_a)
"navmesh_settings"_a, "include_static_objects"_a)
.def("get_light_setup", &Simulator::getLightSetup,
"key"_a = assets::ResourceManager::DEFAULT_LIGHTING_KEY)
.def("set_light_setup", &Simulator::setLightSetup, "light_setup"_a,
Expand Down
12 changes: 12 additions & 0 deletions src/esp/physics/PhysicsManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -517,5 +517,17 @@ scene::SceneNode& PhysicsManager::getObjectSceneNode(int physObjectID) {
physObjectID));
}

const scene::SceneNode& PhysicsManager::getObjectVisualSceneNode(
int physObjectID) const {
assertIDValidity(physObjectID);
return *existingObjects_.at(physObjectID)->visualNode_;
}

const assets::PhysicsObjectAttributes&
PhysicsManager::getInitializationAttributes(const int physObjectID) const {
assertIDValidity(physObjectID);
return existingObjects_.at(physObjectID)->getInitializationAttributes();
}

} // namespace physics
} // namespace esp
19 changes: 19 additions & 0 deletions src/esp/physics/PhysicsManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,15 @@ class PhysicsManager {
/** @overload */
scene::SceneNode& getObjectSceneNode(int physObjectID);

/**
* @brief Get a const reference to the specified object's visual SceneNode for
* info query purposes.
* @param physObjectID The object ID and key identifying the object in @ref
* PhysicsManager::existingObjects_.
* @return Const reference to the object's visual scene node.
*/
const scene::SceneNode& getObjectVisualSceneNode(int physObjectID) const;

/** @brief Render any debugging visualizations provided by the underlying
* physics simulator implementation. By default does nothing. See @ref
* BulletPhysicsManager::debugDraw.
Expand Down Expand Up @@ -795,6 +804,16 @@ class PhysicsManager {
return activePhysSimLib_;
};

/**
* @brief Get the template used to initialize an object.
*
* PhysicsObjectAttributes templates are expected to be changed between
* instances of objects.
* @return The initialization settings of the specified object instance.
*/
const assets::PhysicsObjectAttributes& getInitializationAttributes(
const int physObjectID) const;

protected:
/** @brief Check that a given object ID is valid (i.e. it refers to an
* existing object). Terminate the program and report an error if not. This
Expand Down
4 changes: 3 additions & 1 deletion src/esp/physics/RigidObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ bool RigidObject::initializeScene(
}

bool RigidObject::initializeObject(
const assets::PhysicsObjectAttributes&,
const assets::PhysicsObjectAttributes& physicsObjectAttributes,
const std::vector<assets::CollisionMeshData>&) {
// TODO (JH): Handling static/kinematic object type
if (rigidObjectType_ != RigidObjectType::NONE) {
Expand All @@ -41,6 +41,8 @@ bool RigidObject::initializeObject(
// default kineamtic unless a simulator is initialized...
objectMotionType_ = MotionType::KINEMATIC;

initializationAttributes_ = physicsObjectAttributes;

return true;
}

Expand Down
20 changes: 20 additions & 0 deletions src/esp/physics/RigidObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
#include "esp/scene/SceneNode.h"

namespace esp {

namespace assets {
class PhysicsObjectAttributes;
}
namespace physics {

/**
Expand Down Expand Up @@ -545,6 +549,17 @@ class RigidObject : public Magnum::SceneGraph::AbstractFeature3D {
*/
virtual void setAngularDamping(CORRADE_UNUSED const double angDamping){};

/**
* @brief Get the template used to initialize this object.
*
* PhysicsObjectAttributes templates are expected to be changed between
* instances of objects.
* @return The initialization settings of this object instance.
*/
const assets::PhysicsObjectAttributes& getInitializationAttributes() const {
return initializationAttributes_;
};

/** @brief public @ref esp::assets::Attributes object for user convenience.
* Store whatever object attributes you want here! */
assets::Attributes attributes_;
Expand Down Expand Up @@ -574,6 +589,11 @@ class RigidObject : public Magnum::SceneGraph::AbstractFeature3D {
* identifies the object as uninitialized.*/
RigidObjectType rigidObjectType_ = RigidObjectType::NONE;

/**
* @brief Saved attributes when the object was initialized.
*/
assets::PhysicsObjectAttributes initializationAttributes_;

/** @brief Used to synchronize other simulator's notion of the object state
* after it was changed kinematically. Called automatically on kinematic
* updates.*/
Expand Down
2 changes: 2 additions & 0 deletions src/esp/physics/bullet/BulletRigidObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ bool BulletRigidObject::initializeObject(
return false;
}

initializationAttributes_ = physicsObjectAttributes;

//! Turn on scene flag
rigidObjectType_ = RigidObjectType::OBJECT;
objectMotionType_ = MotionType::DYNAMIC;
Expand Down
51 changes: 50 additions & 1 deletion src/esp/sim/Simulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@

#include <Corrade/Utility/Directory.h>
#include <Corrade/Utility/String.h>
#include <Magnum/EigenIntegration/GeometryIntegration.h>

#include "esp/assets/Attributes.h"
#include "esp/core/esp.h"
#include "esp/gfx/Drawable.h"
#include "esp/gfx/RenderCamera.h"
Expand Down Expand Up @@ -275,6 +277,17 @@ int Simulator::getPhysicsObjectLibrarySize() {
return resourceManager_.getNumLibraryObjects();
}

assets::PhysicsObjectAttributes& Simulator::getPhysicsObjectAttributes(
int templateIndex) {
return resourceManager_.getPhysicsObjectAttributes(
resourceManager_.getObjectConfig(templateIndex));
}

assets::PhysicsObjectAttributes& Simulator::getPhysicsObjectAttributes(
const std::string& templateHandle) {
return resourceManager_.getPhysicsObjectAttributes(templateHandle);
}

// return a list of existing objected IDs in a physical scene
std::vector<int> Simulator::getExistingObjectIDs(const int sceneID) {
if (sceneHasPhysics(sceneID)) {
Expand Down Expand Up @@ -404,7 +417,8 @@ double Simulator::getWorldTime() {
}

bool Simulator::recomputeNavMesh(nav::PathFinder& pathfinder,
const nav::NavMeshSettings& navMeshSettings) {
const nav::NavMeshSettings& navMeshSettings,
bool includeStaticObjects) {
CORRADE_ASSERT(
config_.createRenderer,
"Simulator::recomputeNavMesh: SimulatorConfiguration::createRenderer is "
Expand All @@ -415,6 +429,41 @@ bool Simulator::recomputeNavMesh(nav::PathFinder& pathfinder,
assets::MeshData::uptr joinedMesh =
resourceManager_.createJoinedCollisionMesh(config_.scene.id);

// add STATIC collision objects
if (includeStaticObjects) {
for (auto objectID : physicsManager_->getExistingObjectIDs()) {
if (physicsManager_->getObjectMotionType(objectID) ==
physics::MotionType::STATIC) {
auto objectTransform = Magnum::EigenIntegration::cast<
Eigen::Transform<float, 3, Eigen::Affine> >(
physicsManager_->getObjectVisualSceneNode(objectID)
.absoluteTransformationMatrix());
const assets::PhysicsObjectAttributes& initializationTemplate =
physicsManager_->getInitializationAttributes(objectID);
objectTransform.scale(Magnum::EigenIntegration::cast<vec3f>(
initializationTemplate.getMagnumVec3("scale")));
std::string meshHandle =
initializationTemplate.getString("collisionMeshHandle");
if (meshHandle.empty()) {
meshHandle = initializationTemplate.getString("renderMeshHandle");
}
assets::MeshData::uptr joinedObjectMesh =
resourceManager_.createJoinedCollisionMesh(meshHandle);
int prevNumIndices = joinedMesh->ibo.size();
int prevNumVerts = joinedMesh->vbo.size();
joinedMesh->ibo.resize(prevNumIndices + joinedObjectMesh->ibo.size());
for (size_t ix = 0; ix < joinedObjectMesh->ibo.size(); ++ix) {
joinedMesh->ibo[ix + prevNumIndices] =
joinedObjectMesh->ibo[ix] + prevNumVerts;
}
joinedMesh->vbo.reserve(joinedObjectMesh->vbo.size() + prevNumVerts);
for (auto& vert : joinedObjectMesh->vbo) {
joinedMesh->vbo.push_back(objectTransform * vert);
}
}
}
}

if (!pathfinder.build(navMeshSettings, *joinedMesh)) {
LOG(ERROR) << "Failed to build navmesh";
return false;
Expand Down
23 changes: 19 additions & 4 deletions src/esp/sim/Simulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,16 @@ class Simulator {
* esp::physics::PhysicsManager::addObject().
* @param objectLibIndex The index of the object's template in @ref
* esp::assets::ResourceManager::physicsObjectLibrary_.
* @param attachmentNode If provided, attach the RigidObject Feature to this
* node instead of creating a new one.
* @param lightSetupKey The string key for the LightSetup to be used by this
* object.
* @param sceneID !! Not used currently !! Specifies which physical scene to
* add an object to.
* @return The ID assigned to new object which identifies it in @ref
* esp::physics::PhysicsManager::existingObjects_ or @ref esp::ID_UNDEFINED if
* instancing fails.
*/
// int addObject(int objectLibIndex, int sceneID = 0);

/** @overload */
int addObject(int objectLibIndex,
scene::SceneNode* attachmentNode = nullptr,
const std::string& lightSetupKey =
Expand All @@ -120,6 +121,19 @@ class Simulator {
*/
int getPhysicsObjectLibrarySize();

/**
* @brief Get an editable reference to a physics object template by index.
*/
assets::PhysicsObjectAttributes& getPhysicsObjectAttributes(
int templateIndex);

/**
* @brief Get an editable reference to a physics object template by string
* key.
*/
assets::PhysicsObjectAttributes& getPhysicsObjectAttributes(
const std::string& templateHandle);

/**
* @brief Remove an instanced object by ID. See @ref
* esp::physics::PhysicsManager::removeObject().
Expand Down Expand Up @@ -315,7 +329,8 @@ class Simulator {
* @return Whether or not the navmesh recomputation succeeded.
*/
bool recomputeNavMesh(nav::PathFinder& pathfinder,
const nav::NavMeshSettings& navMeshSettings);
const nav::NavMeshSettings& navMeshSettings,
bool includeStaticObjects = false);

agent::Agent::ptr getAgent(int agentId);

Expand Down
64 changes: 63 additions & 1 deletion src/tests/SimTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
#include <Corrade/TestSuite/Tester.h>
#include <Corrade/Utility/Directory.h>
#include <Magnum/DebugTools/CompareImage.h>
#include <Magnum/EigenIntegration/Integration.h>
#include <Magnum/ImageView.h>
#include <Magnum/Magnum.h>
#include <Magnum/PixelFormat.h>
#include <string>

#include "esp/assets/ResourceManager.h"
#include "esp/physics/RigidObject.h"
#include "esp/sim/Simulator.h"

#include "configure.h"
Expand Down Expand Up @@ -88,6 +90,7 @@ struct SimTest : Cr::TestSuite::Tester {
void updateLightSetupRGBAObservation();
void updateObjectLightSetupRGBAObservation();
void multipleLightingSetupsRGBAObservation();
void recomputeNavmeshWithStaticObjects();

// TODO: remove outlier pixels from image and lower maxThreshold
const Magnum::Float maxThreshold = 255.f;
Expand All @@ -109,7 +112,8 @@ SimTest::SimTest() {
&SimTest::getCustomLightingRGBAObservation,
&SimTest::updateLightSetupRGBAObservation,
&SimTest::updateObjectLightSetupRGBAObservation,
&SimTest::multipleLightingSetupsRGBAObservation});
&SimTest::multipleLightingSetupsRGBAObservation,
&SimTest::recomputeNavmeshWithStaticObjects});
// clang-format on
}

Expand Down Expand Up @@ -315,6 +319,64 @@ void SimTest::multipleLightingSetupsRGBAObservation() {
*simulator, "SimTestExpectedDifferentLighting.png", maxThreshold, 0.01f);
}

void SimTest::recomputeNavmeshWithStaticObjects() {
auto simulator = getSimulator(skokloster);

// compute the initial navmesh
esp::nav::NavMeshSettings navMeshSettings;
navMeshSettings.setDefaults();
simulator->recomputeNavMesh(*simulator->getPathFinder().get(),
navMeshSettings);

esp::vec3f randomNavPoint =
simulator->getPathFinder()->getRandomNavigablePoint();
while (simulator->getPathFinder()->distanceToClosestObstacle(randomNavPoint) <
1.0 ||
randomNavPoint[1] > 1.0) {
randomNavPoint = simulator->getPathFinder()->getRandomNavigablePoint();
}

// add static object at a known navigable point
int objectID = simulator->addObject(0);
simulator->setTranslation(Magnum::Vector3{randomNavPoint}, objectID);
simulator->setObjectMotionType(esp::physics::MotionType::STATIC, objectID);
CORRADE_VERIFY(
simulator->getPathFinder()->isNavigable({randomNavPoint}, 0.1));

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

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

simulator->removeObject(objectID);

// test scaling
esp::assets::PhysicsObjectAttributes& objectTemplate =
simulator->getPhysicsObjectAttributes(0);
objectTemplate.setMagnumVec3("scale", {0.5, 0.5, 0.5});
objectID = simulator->addObject(0);
simulator->setTranslation(Magnum::Vector3{randomNavPoint}, objectID);
simulator->setTranslation(
simulator->getTranslation(objectID) + Magnum::Vector3{0, 0.5, 0},
objectID);
simulator->setObjectMotionType(esp::physics::MotionType::STATIC, objectID);
esp::vec3f offset(0.75, 0, 0);
CORRADE_VERIFY(simulator->getPathFinder()->isNavigable(randomNavPoint, 0.1));
CORRADE_VERIFY(
simulator->getPathFinder()->isNavigable(randomNavPoint + offset, 0.2));
// recompute with object
simulator->recomputeNavMesh(*simulator->getPathFinder().get(),
navMeshSettings, true);
CORRADE_VERIFY(!simulator->getPathFinder()->isNavigable(randomNavPoint, 0.1));
CORRADE_VERIFY(
simulator->getPathFinder()->isNavigable(randomNavPoint + offset, 0.2));
}

} // namespace

CORRADE_TEST_MAIN(SimTest)