persistence.cpp
Go to the documentation of this file.
1 /**
2  * This file is part of ArmarX.
3  *
4  * ArmarX is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * ArmarX is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * @author Fabian Reister ( fabian dot reister at kit dot edu )
17  * @date 2022
18  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
19  * GNU General Public License
20  */
21 
22 #include "persistence.h"
23 
24 #include <cmath>
25 #include <cstdint>
26 #include <filesystem>
27 #include <fstream>
28 #include <optional>
29 #include <string>
30 #include <vector>
31 
32 #include <opencv2/core.hpp>
33 #include <opencv2/core/eigen.hpp>
34 #include <opencv2/core/hal/interface.h>
35 #include <opencv2/core/mat.hpp>
36 #include <opencv2/imgcodecs.hpp>
37 #include <opencv2/imgproc.hpp>
38 
42 
45 
46 #include <nlohmann/json.hpp>
47 
49 {
50 
51  Costmap
52  load(const std::filesystem::path& directory)
53  {
54  // load
55  const auto filename = directory / "costmap.json";
56  std::ifstream ifs(filename);
57  ARMARX_VERBOSE << "Loading costmap info " << filename.string();
58  const nlohmann::json j = nlohmann::json::parse(ifs);
59 
60  // params
61  const auto& jParam = j.at("params");
62 
63  const Costmap::Parameters params{.binaryGrid = jParam.at("binary_grid"),
64  .cellSize = jParam.at("cell_size")};
65 
66  // scene bounds
67  const auto& jSceneBounds = j.at("scene_bounds");
68 
69  const std::vector<float> boundsMin = jSceneBounds.at("min");
70  const std::vector<float> boundsMax = jSceneBounds.at("max");
71 
72  ARMARX_CHECK_EQUAL(boundsMin.size(), 2);
73  ARMARX_CHECK_EQUAL(boundsMax.size(), 2);
74 
75  const SceneBounds sceneBounds{.min = {boundsMin.at(0), boundsMin.at(1)},
76  .max = {boundsMax.at(0), boundsMax.at(1)}};
77 
78 
79  // grid
80  const std::string gridFilename = j.at("grid_filename");
81  cv::Mat gridMat = cv::imread((directory / gridFilename).string(),
82  cv::IMREAD_ANYCOLOR | cv::IMREAD_ANYDEPTH);
83 
84  Eigen::MatrixXf grid;
85  cv::cv2eigen(gridMat, grid);
86 
87  // mask, if any
88  std::optional<Costmap::Mask> optMask;
89  if (not j.at("mask_filename").empty())
90  {
91  const std::string maskFilename = j.at("grid_filename");
92  cv::Mat maskMat = cv::imread((directory / maskFilename).string(),
93  cv::IMREAD_ANYCOLOR | cv::IMREAD_ANYDEPTH);
94 
96  cv::cv2eigen(maskMat, mask);
97 
98  optMask = mask.cast<bool>();
99  }
100 
101  return {grid, params, sceneBounds, optMask};
102  }
103 
104  bool
105  save(const Costmap& costmap, const std::filesystem::path& directory)
106  {
107  ARMARX_TRACE;
108 
109  ARMARX_INFO << "Storing costmap in directory `" << directory.string() << "`";
110 
111  if (not std::filesystem::exists(directory))
112  {
113  ARMARX_VERBOSE << "Creating directory `" << directory.string() << "`";
114  std::filesystem::create_directories(directory);
115  }
116 
117  nlohmann::json j = {{"params",
118  {{"binary_grid", costmap.params().binaryGrid},
119  {"cell_size", costmap.params().cellSize}}},
120  {"scene_bounds",
121  {{"min",
122  std::vector<float>{costmap.getLocalSceneBounds().min.x(),
123  costmap.getLocalSceneBounds().min.y()}},
124  {"max",
125  std::vector<float>{costmap.getLocalSceneBounds().max.x(),
126  costmap.getLocalSceneBounds().max.y()}}}}};
127 
128  std::optional<cv::Mat1b> mask;
129  if (costmap.getMask().has_value())
130  {
131  // mask, if any
133  costmap.getMask()->cast<std::uint8_t>();
134  cv::Mat1b m;
135  cv::eigen2cv(maskI, m);
136  mask = m;
137  }
138 
139  // grid
140  {
141  ARMARX_TRACE;
142 
143  cv::Mat1f grid;
144  cv::eigen2cv(costmap.getGrid(), grid);
145 
146  const std::string gridFilename = "grid.exr";
147  cv::imwrite((directory / gridFilename).string(), grid);
148 
149  j["grid_filename"] = gridFilename;
150 
151  // for debugging purpose, also save a png image
152  const std::string gridDebuggingFilename = "grid";
153 
154  double min;
155  double max;
156  if (mask)
157  {
158  cv::minMaxIdx(grid, &min, &max, 0, 0, mask.value());
159  }
160  else
161  {
162  cv::minMaxIdx(grid, &min, &max);
163  }
164  cv::Mat adjMap;
165  grid.convertTo(adjMap, CV_8UC1, 255 / (max - min), -255 * min / (max - min));
166 
167  cv::Mat colorsMap;
168  applyColorMap(adjMap, colorsMap, cv::COLORMAP_JET);
169  cv::Mat maskedColorsMap;
170  if (mask)
171  {
172  colorsMap.copyTo(maskedColorsMap, mask.value());
173  }
174  else
175  {
176  maskedColorsMap = colorsMap;
177  }
178  cv::imwrite((directory / (gridDebuggingFilename + ".png")).string(), maskedColorsMap);
179 
180  ARMARX_TRACE;
181 
182  // mask if any
183  if (mask)
184  {
185  const std::string maskFilename = "mask.ppm";
186  cv::imwrite((directory / maskFilename).string(), mask.value());
187 
188  j["mask_filename"] = maskFilename;
189  }
190  }
191 
192  // save
193  std::ofstream of(directory / "costmap.json");
194  of << j;
195 
196  return true;
197  }
198 
199 
200 } // namespace armarx::navigation::algorithms
armarx::navigation::algorithms::Costmap::getMask
const std::optional< Mask > & getMask() const noexcept
Definition: Costmap.cpp:399
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:187
armarx::navigation::algorithms::load
Costmap load(const std::filesystem::path &directory)
Definition: persistence.cpp:52
trace.h
armarx::max
std::vector< T > max(const std::vector< T > &v1, const std::vector< T > &v2)
Definition: VectorHelpers.h:297
armarx::navigation::algorithms
This file is part of ArmarX.
Definition: aron_conversions.cpp:25
persistence.h
armarx::navigation::algorithms::Costmap::getLocalSceneBounds
const SceneBounds & getLocalSceneBounds() const noexcept
Definition: Costmap.cpp:130
Costmap.h
armarx::navigation::algorithms::save
bool save(const Costmap &costmap, const std::filesystem::path &directory)
Definition: persistence.cpp:105
ARMARX_TRACE
#define ARMARX_TRACE
Definition: trace.h:77
armarx::navigation::algorithms::Costmap::Parameters::binaryGrid
bool binaryGrid
Definition: Costmap.h:27
armarx::navigation::algorithms::Costmap::params
const Parameters & params() const noexcept
Definition: Costmap.cpp:237
armarx::navigation::algorithms::Costmap::getGrid
const Grid & getGrid() const
Definition: Costmap.cpp:243
armarx::conversions::cv2eigen
Eigen::Vector2f cv2eigen(const cv::Point2f &pt)
Definition: opencv_eigen.h:54
filename
std::string filename
Definition: VisualizationRobot.cpp:86
armarx::navigation::algorithms::SceneBounds
Definition: types.h:29
ExpressionException.h
armarx::navigation::algorithms::SceneBounds::min
Eigen::Vector2f min
Definition: types.h:31
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
armarx::min
std::vector< T > min(const std::vector< T > &v1, const std::vector< T > &v2)
Definition: VectorHelpers.h:327
armarx::navigation::algorithms::Costmap::Parameters::cellSize
float cellSize
How big each cell is in the uniform grid.
Definition: Costmap.h:30
armarx::navigation::algorithms::Costmap::Parameters
Definition: Costmap.h:24
Eigen::Matrix
Definition: EigenForwardDeclarations.h:27
Logging.h
ARMARX_CHECK_EQUAL
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
Definition: ExpressionException.h:130
types.h
armarx::navigation::algorithms::SceneBounds::max
Eigen::Vector2f max
Definition: types.h:32
armarx::navigation::algorithms::Costmap
Definition: Costmap.h:16
armarx::conversions::eigen2cv
cv::Point2f eigen2cv(const Eigen::Vector2f &pt)
Definition: opencv_eigen.h:33