From 4ac37d433aed7a3c3098bb83e345f900de161257 Mon Sep 17 00:00:00 2001 From: Jan Wehrmann Date: Thu, 30 Apr 2020 17:07:04 +0200 Subject: [PATCH] Updated MPL to support slam::maps by converting to envire. Adds support to hand a slam/maps/TraversabilityGrid to the MotionPlanningLibraries by converting it to an envire::TraversabilityGrid. --- manifest.xml | 1 + src/CMakeLists.txt | 4 +- src/MotionPlanningLibraries.cpp | 82 +++++++++++++++++++ src/MotionPlanningLibraries.hpp | 33 +++++++- test/test_MotionPlanning.cpp | 59 +++++++++++++ ...anningLibrariesSbplSplineVisualization.cpp | 2 +- 6 files changed, 178 insertions(+), 3 deletions(-) diff --git a/manifest.xml b/manifest.xml index faa91ad..07679fe 100644 --- a/manifest.xml +++ b/manifest.xml @@ -10,6 +10,7 @@ + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 85a4dea..6811e18 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -36,7 +36,9 @@ rock_library(motion_planning_libraries ompl/validators/TravMapValidator.hpp ompl/objectives/TravGridObjective.hpp ompl/spaces/SherpaStateSpace.hpp - DEPS_PKGCONFIG envire + DEPS_PKGCONFIG + envire + maps ompl sbpl base-types diff --git a/src/MotionPlanningLibraries.cpp b/src/MotionPlanningLibraries.cpp index adcc6e3..d3fa798 100644 --- a/src/MotionPlanningLibraries.cpp +++ b/src/MotionPlanningLibraries.cpp @@ -12,9 +12,12 @@ namespace motion_planning_libraries { +Eigen::Affine3d MotionPlanningLibraries::mWorld2Local = Eigen::Affine3d::Identity(); + // PUBLIC MotionPlanningLibraries::MotionPlanningLibraries(Config config) : mConfig(config), + mpEnv(nullptr), mpTravGrid(NULL), mpTravData(), mpLastTravGrid(NULL), @@ -197,6 +200,39 @@ bool MotionPlanningLibraries::setTravGrid(envire::Environment* env, std::string return true; } +bool MotionPlanningLibraries::setTravGrid(const maps::grid::TraversabilityGrid& trav) +{ + boost::intrusive_ptr envireTrav = convertToEnvire(trav); + std::string uuid = "/trav_map"; + envireTrav->setUniqueId(uuid); + + if (!mpEnv) + mpEnv = boost::shared_ptr(new envire::Environment); + + // Detach item if there is already a map in the environment. + // Not storing the returned intrusive_ptr causes the item to self delete. + boost::intrusive_ptr trav_ptr = mpEnv->getItem(uuid); + if (trav_ptr) + mpEnv->detachItem(trav_ptr.get()); + + // Check for a frame node to reuse. + std::list frameNodes = mpEnv->getRootNode()->getChildren(); + envire::FrameNode* travFrameNode; + if (frameNodes.empty()) + travFrameNode = new envire::FrameNode(); + else + travFrameNode = frameNodes.front(); + + mpEnv->attachItem(envireTrav.get()); + mpEnv->getRootNode()->addChild(travFrameNode); + envireTrav->setFrameNode(travFrameNode); + + // Set transform in case it was updated or hasn't been set yet. + travFrameNode->setTransform(mWorld2Local); + + return setTravGrid(mpEnv.get(), uuid); +} + bool MotionPlanningLibraries::setStartState(struct State new_state) { if(mpPlanningLib == NULL) { LOG_WARN("Planning library has not been allocated yet"); @@ -746,6 +782,16 @@ bool MotionPlanningLibraries::getSbplMotionPrimitives(struct SbplMotionPrimitive } } +void MotionPlanningLibraries::setWorld2Local(Eigen::Affine3d world2local) +{ + mWorld2Local = world2local; +} + +Eigen::Affine3d MotionPlanningLibraries::getWorld2Local() +{ + return mWorld2Local; +} + bool MotionPlanningLibraries::world2grid(envire::TraversabilityGrid const* trav, base::samples::RigidBodyState const& world_pose, base::samples::RigidBodyState& grid_pose, @@ -929,4 +975,40 @@ void MotionPlanningLibraries::collectCellUpdates( envire::TraversabilityGrid* ol LOG_INFO("Number of unchanged cells %d", cell_counter_same); } +boost::intrusive_ptr MotionPlanningLibraries::convertToEnvire(const maps::grid::TraversabilityGrid& traversabilityGrid) const +{ + maps::grid::Vector2ui numCells = traversabilityGrid.getNumCells(); + maps::grid::Vector2d resolution = traversabilityGrid.getResolution(); + maps::grid::Vector3d localFrame = traversabilityGrid.translation(); + + boost::intrusive_ptr envTravGrid(new envire::TraversabilityGrid(numCells.x(), numCells.y(), + resolution.x(), resolution.y(), + localFrame.x(), localFrame.y())); + + std::vector travClasses = traversabilityGrid.getTraversabilityClasses(); + envire::TraversabilityClass travClass; + + for (size_t travClassId = 0; travClassId < travClasses.size(); ++travClassId) + { + travClass = envire::TraversabilityClass(travClasses.at(travClassId).getDrivability()); + envTravGrid->setTraversabilityClass(travClassId, travClass); + } + + uint8_t travClassId; + double probability; + + uint8_t* trav_ptr = envTravGrid->getGridData(envTravGrid->TRAVERSABILITY).origin(); + uint8_t* prob_ptr = envTravGrid->getGridData(envTravGrid->PROBABILITY).origin(); + maps::grid::TraversabilityGrid::const_iterator it = traversabilityGrid.begin(); + for (; it < traversabilityGrid.end(); ++it, ++trav_ptr, ++prob_ptr) + { + travClassId = it->getTraversabilityClassId(); + probability = it->getProbability(); + *trav_ptr = travClassId; + *prob_ptr = probability; + } + + return envTravGrid; +} + } // namespace motion_planning_libraries diff --git a/src/MotionPlanningLibraries.hpp b/src/MotionPlanningLibraries.hpp index 23dd2f1..6aab6d0 100644 --- a/src/MotionPlanningLibraries.hpp +++ b/src/MotionPlanningLibraries.hpp @@ -6,6 +6,7 @@ #include #include +#include #include "Config.hpp" #include "State.hpp" @@ -141,6 +142,7 @@ class MotionPlanningLibraries boost::shared_ptr mpPlanningLib; + boost::shared_ptr mpEnv; envire::TraversabilityGrid* mpTravGrid; boost::shared_ptr mpTravData; // Receives a copy of each trav grid, which is used for partial update testing. @@ -152,6 +154,7 @@ class MotionPlanningLibraries bool mNewGoalReceived; double mLostX; // Used to trac discretization error. double mLostY; + static Eigen::Affine3d mWorld2Local; public: enum MplErrors mError; @@ -167,6 +170,13 @@ class MotionPlanningLibraries * \todo "If possible cell updates should be used." */ bool setTravGrid(envire::Environment* env, std::string trav_map_id); + + /** + * @overload allows to directly pass a maps::grid:TraversabilityGrid. + * @param trav : Traversability grid to be set. + * @returns true if the traversability grid was successfully set. + */ + bool setTravGrid(const maps::grid::TraversabilityGrid& trav); inline bool travGridAvailable() { return mpTravGrid != NULL; @@ -285,6 +295,19 @@ class MotionPlanningLibraries } bool getSbplMotionPrimitives(struct SbplMotionPrimitives& prims); + + /** + * Set the transformation between world and local coordinates. + * @param world2local : transformation between the world frame and the local frame. + * Will be set to identity by default. + */ + static void setWorld2Local(Eigen::Affine3d world2local); + + /** + * Get the transformation between world and local coordinates. + * @returns : the transformation between the world frame and the local frame. + */ + static Eigen::Affine3d getWorld2Local(); /** * Converts the world pose to grid coordinates including the transformed orientation. @@ -310,7 +333,15 @@ class MotionPlanningLibraries bool gridlocal2world(envire::TraversabilityGrid const* trav, base::samples::RigidBodyState const& grid_local_pose, base::samples::RigidBodyState& world_pose); - + + /** + * Converts a maps::grid::TraversabilityGrid to an envire::TraversabilityGrid as an + * intrusive_ptr so it can be passed to the motion planner. + * @param traversabilityGrid : traversabilityGrid to be converted. + * @returns an intrusive_ptr to the converted traversavility grid. + */ + boost::intrusive_ptr convertToEnvire(const maps::grid::TraversabilityGrid& traversabilityGrid) const; + private: /** * Extracts the traversability map \a trav_map_id from the passed environment. diff --git a/test/test_MotionPlanning.cpp b/test/test_MotionPlanning.cpp index bc7a85d..8264835 100644 --- a/test/test_MotionPlanning.cpp +++ b/test/test_MotionPlanning.cpp @@ -71,6 +71,65 @@ BOOST_AUTO_TEST_CASE(sbpl_mprims) mprims.createPrimitives(); mprims.storeToFile("test.mprim"); } + +BOOST_AUTO_TEST_CASE(test_convertToEnvire) +{ + maps::grid::TraversabilityCell defaultCell = maps::grid::TraversabilityCell(); + maps::grid::Vector2ui numCells(1000, 1500); + maps::grid::Vector2d resolution(0.1, 0.2); + maps::grid::TraversabilityGrid travGrid = maps::grid::TraversabilityGrid(numCells, resolution, defaultCell); + travGrid.translate(Eigen::Vector3d(1, 1, 0)); + + for (size_t i = 0; i < 10; ++i) + { + uint8_t retID; + travGrid.registerNewTraversabilityClass(retID, maps::grid::TraversabilityClass(0.1 * i)); + BOOST_CHECK_EQUAL(retID, i); + } + + travGrid.setTraversabilityAndProbability(0, 0.0, 0, 0); + travGrid.setTraversabilityAndProbability(1, 0.1, 0, 14); + travGrid.setTraversabilityAndProbability(2, 0.2, 9, 0); + travGrid.setTraversabilityAndProbability(3, 0.3, 9, 14); + travGrid.setTraversabilityAndProbability(4, 0.4, 4, 4); + travGrid.setTraversabilityAndProbability(5, 0.5, 7, 3); + + motion_planning_libraries::MotionPlanningLibraries mpl = motion_planning_libraries::MotionPlanningLibraries(); + boost::intrusive_ptr envireTravGrid = mpl.convertToEnvire(travGrid); + + // Check number of cells. + BOOST_CHECK_EQUAL(envireTravGrid->getCellSizeX(), travGrid.getNumCells().x()); + BOOST_CHECK_EQUAL(envireTravGrid->getCellSizeY(), travGrid.getNumCells().y()); + + // Check cell sizes. + BOOST_CHECK_EQUAL(envireTravGrid->getScaleX(), travGrid.getResolution().x()); + BOOST_CHECK_EQUAL(envireTravGrid->getScaleY(), travGrid.getResolution().y()); + + // Check size (redundant but why not). + BOOST_CHECK_EQUAL(envireTravGrid->getSizeX(), travGrid.getSize().x()); + BOOST_CHECK_EQUAL(envireTravGrid->getSizeY(), travGrid.getSize().y()); + + // Check offset. + BOOST_CHECK_EQUAL(envireTravGrid->getOffsetX(), travGrid.translation().x()); + BOOST_CHECK_EQUAL(envireTravGrid->getOffsetY(), travGrid.translation().y()); + + // Check classes. + BOOST_CHECK_EQUAL(envireTravGrid->getTraversabilityClasses().size(), travGrid.getTraversabilityClasses().size()); + for (size_t i = 0; i < envireTravGrid->getTraversabilityClasses().size(); ++i) + { + BOOST_CHECK_EQUAL(envireTravGrid->getTraversabilityClass(i).getDrivability(), travGrid.getTraversabilityClass(i).getDrivability()); + } + + // Check traversability and probability. + for (size_t x = 0; x < envireTravGrid->getCellSizeX(); ++x) + { + for (size_t y = 0; y < envireTravGrid->getCellSizeY(); ++y) + { + BOOST_CHECK_EQUAL(envireTravGrid->getTraversability(x, y).getDrivability(), travGrid.getTraversability(x, y).getDrivability()); + BOOST_CHECK_CLOSE(envireTravGrid->getProbability(x, y), travGrid.getProbability(x, y), 0.001); + } + } +} #if 0 diff --git a/viz/MotionPlanningLibrariesSbplSplineVisualization.cpp b/viz/MotionPlanningLibrariesSbplSplineVisualization.cpp index 8adbf8a..d55a6df 100644 --- a/viz/MotionPlanningLibrariesSbplSplineVisualization.cpp +++ b/viz/MotionPlanningLibrariesSbplSplineVisualization.cpp @@ -121,7 +121,7 @@ void MotionPlanningLibrariesSbplSplineVisualization::addPrimitives(osg::Group* g const std::vector& prims = primitives.getPrimitiveForAngle(mAngleNum); for(const SplinePrimitive& prim : prims) { - if(prim.endAngle != mEndAngle) + if(static_cast(prim.endAngle) != mEndAngle) continue; if(const_cast(prim).spline.getCurvatureMax() > maxCurvature)