From 2a69d99c61c2e5dc68d44227f981afd794883204 Mon Sep 17 00:00:00 2001
From: Fabian Reister <fabian.reister@kit.edu>
Date: Mon, 25 Oct 2021 08:26:55 +0200
Subject: [PATCH] computing navigation cost map

---
 .../navigation/algorithms/CMakeLists.txt      |  6 ++
 .../algorithms/astar/NavigationCostMap.cpp    | 79 +++++++++++++------
 .../algorithms/astar/NavigationCostMap.h      | 21 +++--
 .../navigation/algorithms/astar/util.cpp      | 37 +++++++++
 .../armarx/navigation/algorithms/astar/util.h | 10 +++
 .../components/Navigator/Navigator.cpp        | 27 +++++++
 6 files changed, 148 insertions(+), 32 deletions(-)
 create mode 100644 source/armarx/navigation/algorithms/astar/util.cpp
 create mode 100644 source/armarx/navigation/algorithms/astar/util.h

diff --git a/source/armarx/navigation/algorithms/CMakeLists.txt b/source/armarx/navigation/algorithms/CMakeLists.txt
index 5507cdeb..295e35cf 100644
--- a/source/armarx/navigation/algorithms/CMakeLists.txt
+++ b/source/armarx/navigation/algorithms/CMakeLists.txt
@@ -1,9 +1,13 @@
+find_package(OpenCV REQUIRED )
+
 armarx_add_library(algorithms
     DEPENDENCIES
         ArmarXCoreInterfaces
         ArmarXCore
         armarx_navigation::core
         armarx_navigation::conversions
+    DEPENDENCIES_LEGACY
+        OpenCV
     SOURCES
         ./algorithms.cpp
         # A*
@@ -11,6 +15,7 @@ armarx_add_library(algorithms
         ./astar/NavigationCostMap.cpp
         ./astar/Node.cpp
         ./astar/Planner2D.cpp
+        ./astar/util.cpp
         # smoothing
         ./smoothing/ChainApproximation.cpp
         ./smoothing/CircularPathSmoothing.cpp
@@ -21,6 +26,7 @@ armarx_add_library(algorithms
         ./astar/NavigationCostMap.h
         ./astar/Node.h
         ./astar/Planner2D.h
+        ./astar/util.h
         # smoothing
         ./smoothing/ChainApproximation.h
         ./smoothing/CircularPathSmoothing.h
diff --git a/source/armarx/navigation/algorithms/astar/NavigationCostMap.cpp b/source/armarx/navigation/algorithms/astar/NavigationCostMap.cpp
index 08bfd27a..8900c799 100644
--- a/source/armarx/navigation/algorithms/astar/NavigationCostMap.cpp
+++ b/source/armarx/navigation/algorithms/astar/NavigationCostMap.cpp
@@ -14,6 +14,7 @@
 #include <VirtualRobot/BoundingBox.h>
 #include <VirtualRobot/CollisionDetection/CollisionChecker.h>
 #include <VirtualRobot/CollisionDetection/CollisionModel.h>
+#include <VirtualRobot/Visualization/CoinVisualization/CoinVisualizationFactory.h>
 #include <VirtualRobot/XML/ObjectIO.h>
 
 #include <ArmarXCore/core/exceptions/local/ExpressionException.h>
@@ -26,21 +27,6 @@ namespace bg = boost::geometry;
 namespace armarx::navigation::algorithm::astar
 {
 
-    bool
-    intersects(const VirtualRobot::BoundingBox& bb1, const VirtualRobot::BoundingBox& bb2)
-    {
-        using point_t = bg::model::point<double, 3, bg::cs::cartesian>;
-        using box_t = bg::model::box<point_t>;
-
-        const auto toPoint = [](const Eigen::Vector3f& pt)
-        { return point_t(pt.x(), pt.y(), pt.z()); };
-
-        box_t box1(toPoint(bb1.getMin()), toPoint(bb1.getMax()));
-        box_t box2(toPoint(bb2.getMin()), toPoint(bb2.getMax()));
-
-        return bg::intersects(box1, box2);
-    }
-
     NavigationCostMap::NavigationCostMap(VirtualRobot::RobotPtr robot,
                                          VirtualRobot::SceneObjectSetPtr obstacles,
                                          const Parameters& parameters) :
@@ -64,15 +50,32 @@ namespace armarx::navigation::algorithm::astar
     {
         ARMARX_TRACE;
 
-        ARMARX_DEBUG << "Scene bounds are " << sceneBoundsMin << " and " << sceneBoundsMax;
+        if (obstacles)
+        {
+            for (size_t i = 0; i < obstacles->getCollisionModels().size(); i++)
+            {
+                VirtualRobot::BoundingBox bb = obstacles->getCollisionModels()[i]->getBoundingBox();
+                sceneBoundsMin.x() = std::min(bb.getMin().x(), sceneBoundsMin.x());
+                sceneBoundsMin.y() = std::min(bb.getMin().y(), sceneBoundsMin.y());
+                sceneBoundsMax.x() = std::max(bb.getMax().x(), sceneBoundsMax.x());
+                sceneBoundsMax.y() = std::max(bb.getMax().y(), sceneBoundsMax.y());
+            }
+        }
+
+        ARMARX_INFO << "Scene bounds are " << sceneBoundsMin << " and " << sceneBoundsMax;
 
         //+1 for explicit rounding up
         c_x = (sceneBoundsMax.x() - sceneBoundsMin.x()) / parameters.cellSize + 1;
         c_y = (sceneBoundsMax.y() - sceneBoundsMin.y()) / parameters.cellSize + 1;
 
-        ARMARX_DEBUG << "Grid size: " << c_y << ", " << c_x;
+        ARMARX_INFO << "Grid size: " << c_y << ", " << c_x;
+
+        ARMARX_INFO << "Resetting grid";
+        grid = Eigen::MatrixXf(c_x, c_y); //.array();
+        // grid = Eigen::ArrayXf(); //(c_x, c_y);
+        // grid->resize(c_x, c_y);
 
-        grid = Eigen::ArrayXf(c_x, c_y);
+        ARMARX_INFO << "done.";
     }
 
 
@@ -87,6 +90,9 @@ namespace armarx::navigation::algorithm::astar
         const core::Pose globalPose = Eigen::Translation3f(conv::to3D(position)) *
                                       Eigen::AngleAxisf(M_PI_2f32, Eigen::Vector3f::UnitX());
 
+        // auto colModel = robotCollisionModel->clone();
+        // colModel->setGlobalPose(globalPose.matrix());
+
         robotCollisionModel->setGlobalPose(globalPose.matrix());
 
         VirtualRobot::BoundingBox robotBbox = robotCollisionModel->getBoundingBox(true);
@@ -119,7 +125,9 @@ namespace armarx::navigation::algorithm::astar
                     &id2);
 
             // check if objects collide
-            if (dist <= parameters.cellSize / 2)
+            if ((dist <= parameters.cellSize / 2) or
+                VirtualRobot::CollisionChecker::getGlobalCollisionChecker()->checkCollision(
+                    robotCollisionModel, obstacles->getSceneObject(i)->getCollisionModel()))
             {
                 minDistance = 0;
                 break;
@@ -154,7 +162,19 @@ namespace armarx::navigation::algorithm::astar
         ARMARX_TRACE;
         std::vector<Eigen::Vector2f> result;
 
-        ARMARX_CHECK_NOT_NULL(robot);
+        ARMARX_CHECK_NOT_NULL(robot) << "Robot must be set";
+
+
+        VirtualRobot::CoinVisualizationFactory factory;
+        const auto cylinder = factory.createCylinder(1500.F / 2, 2000.F);
+
+        VirtualRobot::CollisionModelPtr collisionModel(new VirtualRobot::CollisionModel(cylinder));
+
+
+        robotCollisionModel = collisionModel;
+
+
+        ARMARX_CHECK_NOT_NULL(robotCollisionModel) << "Collision model must be set!";
 
         // ARMARX_CHECK(robot->hasRobotNode(robotColModelName)) << "No robot node " << robotColModelName;
         // ARMARX_CHECK(robot->getRobotNode(robotColModelName)->getCollisionModel())
@@ -171,9 +191,13 @@ namespace armarx::navigation::algorithm::astar
 
         ARMARX_CHECK_NOT_NULL(robotCollisionModel);
 
+        ARMARX_INFO << "Creating grid";
         createUniformGrid();
 
+        ARMARX_INFO << "Filling grid";
         fillGridCosts();
+
+        ARMARX_INFO << "Filled grid";
     }
 
     void
@@ -182,16 +206,23 @@ namespace armarx::navigation::algorithm::astar
         robotCollisionModel = collisionModel;
     }
 
-    void NavigationCostMap::fillGridCosts()
+    void
+    NavigationCostMap::fillGridCosts()
     {
-        for (int x = 0; x < c_x; x++)
+        int i = 0;
+
+        for (unsigned int x = 0; x < c_x; x++)
         {
-            for (int y = 0; y < c_y; y++)
+            for (unsigned int y = 0; y < c_y; y++)
             {
                 const Index index{x, y};
                 const Position position = toPosition(index);
 
-                grid(x, y) = computeCost(position);
+                grid.value()(x, y) = computeCost(position);
+
+                i++;
+
+                ARMARX_INFO << i << "/" << c_x * c_y;
             }
         }
     }
diff --git a/source/armarx/navigation/algorithms/astar/NavigationCostMap.h b/source/armarx/navigation/algorithms/astar/NavigationCostMap.h
index d6bacdcf..d03750d5 100644
--- a/source/armarx/navigation/algorithms/astar/NavigationCostMap.h
+++ b/source/armarx/navigation/algorithms/astar/NavigationCostMap.h
@@ -24,7 +24,7 @@ namespace armarx::navigation::algorithm::astar
         struct Parameters
         {
             // if set to false, distance to obstacles will be computed and not only a binary collision check
-            bool binaryGrid{false}; 
+            bool binaryGrid{false};
 
             /// How big each cell is in the uniform grid.
             float cellSize = 100.f;
@@ -40,6 +40,7 @@ namespace armarx::navigation::algorithm::astar
 
         using Index = Eigen::Array2i;
         using Position = Eigen::Vector2f;
+        using Grid = Eigen::MatrixXf;
 
         struct Vertex
         {
@@ -47,6 +48,14 @@ namespace armarx::navigation::algorithm::astar
             Position position;
         };
 
+        Position toPosition(const Index& index) const;
+
+        const Grid&
+        getGrid() const
+        {
+            return grid.value();
+        }
+
     private:
         void createUniformGrid();
         float computeCost(const NavigationCostMap::Position& position);
@@ -55,11 +64,7 @@ namespace armarx::navigation::algorithm::astar
         void fillGridCosts();
 
     private:
-
-        Eigen::ArrayXf grid;
-
-        Position toPosition(const Index& index) const;
-
+        std::optional<Grid> grid;
 
 
         size_t c_x = 0;
@@ -71,8 +76,8 @@ namespace armarx::navigation::algorithm::astar
 
         VirtualRobot::CollisionModelPtr robotCollisionModel;
 
-        const Eigen::Vector2f sceneBoundsMin;
-        const Eigen::Vector2f sceneBoundsMax;
+        Eigen::Vector2f sceneBoundsMin;
+        Eigen::Vector2f sceneBoundsMax;
 
         const Parameters parameters;
     };
diff --git a/source/armarx/navigation/algorithms/astar/util.cpp b/source/armarx/navigation/algorithms/astar/util.cpp
new file mode 100644
index 00000000..abc91b03
--- /dev/null
+++ b/source/armarx/navigation/algorithms/astar/util.cpp
@@ -0,0 +1,37 @@
+#include "util.h"
+
+#include <cstddef>
+
+#include <Eigen/src/Core/util/Meta.h>
+
+#include <opencv2/core.hpp>
+#include <opencv2/core/mat.hpp>
+#include <opencv2/opencv.hpp>
+
+#include "ArmarXCore/core/logging/Logging.h"
+
+namespace armarx::navigation
+{
+    void
+    dumpToFile(const Eigen::MatrixXf& grid)
+    {
+
+        ARMARX_INFO << "Dumping to file.";
+
+        ARMARX_INFO << "Shape: " << grid.rows() << ", " << grid.cols();
+        cv::Size size(grid.rows(), grid.cols());
+
+        cv::Mat1f mat(size);
+
+        for (size_t r = 0; r < grid.rows(); r++)
+        {
+            for (size_t c = 0; c < grid.cols(); c++)
+            {
+                mat(cv::Point(r, c)) = grid(r, c);
+            }
+        }
+
+
+        cv::imwrite("/tmp/grid.exr", mat);
+    }
+} // namespace armarx::navigation
diff --git a/source/armarx/navigation/algorithms/astar/util.h b/source/armarx/navigation/algorithms/astar/util.h
new file mode 100644
index 00000000..335c9c6d
--- /dev/null
+++ b/source/armarx/navigation/algorithms/astar/util.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#include <Eigen/Core>
+
+namespace armarx::navigation
+{
+
+    void dumpToFile(const Eigen::MatrixXf& grid);
+
+}
diff --git a/source/armarx/navigation/components/Navigator/Navigator.cpp b/source/armarx/navigation/components/Navigator/Navigator.cpp
index 3ea06048..e61ad3ea 100644
--- a/source/armarx/navigation/components/Navigator/Navigator.cpp
+++ b/source/armarx/navigation/components/Navigator/Navigator.cpp
@@ -55,6 +55,8 @@
 #include "RobotAPI/libraries/armem_vision/client/occupancy_grid/Reader.h"
 #include <RobotAPI/libraries/core/remoterobot/RemoteRobot.h>
 
+#include "armarx/navigation/algorithms/astar/NavigationCostMap.h"
+#include <armarx/navigation/algorithms/astar/util.h>
 #include <armarx/navigation/client/NavigationStackConfig.h>
 #include <armarx/navigation/client/PathBuilder.h>
 #include <armarx/navigation/client/ice/NavigatorInterface.h>
@@ -424,6 +426,8 @@ namespace armarx::navigation::components
 
         if (result and result.occupancyGrid.has_value())
         {
+            ARMARX_INFO << "Occupancy grid available!";
+
             const auto occupancyGridSceneElements = util::asSceneObjects(
                 result.occupancyGrid.value(),
                 OccupancyGridHelper::Params{.freespaceThreshold = 0.45F,
@@ -447,8 +451,31 @@ namespace armarx::navigation::components
                               .color(viz::Color::orange()));
             }
 
+            ARMARX_INFO << "Creating costmap";
+
+            algorithm::astar::NavigationCostMap costmap(
+                getRobot(),
+                scene.objects,
+                algorithm::astar::NavigationCostMap::Parameters{.binaryGrid = false,
+                                                                .cellSize = 100});
+
+            costmap.createCostmap();
+
+            ARMARX_INFO << "Done";
+
+            ARMARX_TRACE;
+            const auto grid = costmap.getGrid();
+
+            ARMARX_TRACE;
+            ARMARX_INFO << "Dumping.";
+            dumpToFile(grid);
+
             arviz.commit({layer});
         }
+        else
+        {
+            ARMARX_INFO << "Occupancy grid not available";
+        }
 
         return scene;
     }
-- 
GitLab