grid_conversion.cpp
Go to the documentation of this file.
1 #include "grid_conversion.h"
2 
3 #include <algorithm>
4 #include <cstdint>
5 
6 #include <Eigen/Geometry>
7 
8 #include <opencv2/core.hpp>
9 #include <opencv2/core/mat.hpp>
10 #include <opencv2/opencv.hpp>
11 
14 
15 #include <cartographer/mapping/2d/grid_2d.h>
16 #include <cartographer/mapping/2d/probability_grid.h>
17 #include <cartographer/mapping/2d/submap_2d.h>
18 #include <cartographer/mapping/2d/xy_index.h>
19 #include <cartographer/mapping/internal/2d/tsdf_2d.h>
20 
22 {
23  ColoredMeshGrid::ColoredMeshGrid(Eigen::Array2i numCells) :
24  num_cells(numCells),
25  vertices(numCells.x(), std::vector<Position>(numCells.y(), Position::Zero())),
26  colors(numCells.x(), std::vector<Color>(numCells.y(), Color::Zero()))
27  {
28  }
29 
30  void
31  ColoredMeshGrid::setColoredVertex(const Eigen::Array2i& idx,
32  const Position& position,
33  const Color& color)
34  {
35  vertices.at(idx.x()).at(idx.y()) = position;
36  colors.at(idx.x()).at(idx.y()) = color;
37  }
38 
40  toMeshGrid(const ::cartographer::mapping::ProbabilityGrid& grid)
41  {
42  const auto resolution = static_cast<float>(grid.limits().resolution());
43 
44  Eigen::Array2i offset;
45  ::cartographer::mapping::CellLimits mapLimits;
46  grid.ComputeCroppedLimits(&offset, &mapLimits);
47 
48  ::cartographer::mapping::XYIndexRangeIterator iter(mapLimits);
49 
50  ColoredMeshGrid meshGrid({mapLimits.num_x_cells, mapLimits.num_y_cells});
51 
52  constexpr uint8_t transparency{255}; // non transparent
53  const ColoredMeshGrid::Color colorCellUnknown =
54  ColoredMeshGrid::Color::Zero(); // fully transparent
55 
56  std::for_each(iter.begin(),
57  iter.end(),
58  [&](const Eigen::Array2i& cellIndexCropped)
59  {
60  const auto cellIndex = cellIndexCropped + offset;
61 
62  const float probability = grid.GetProbability(cellIndex);
63  const bool isKnown = grid.IsKnown(cellIndex);
64 
65  const ColoredMeshGrid::Color color = [&]() -> ColoredMeshGrid::Color
66  {
67  if (isKnown)
68  {
69  const auto c = static_cast<uint8_t>((1 - probability) * 255);
70  return {c, c, c, transparency};
71  }
72 
73  return colorCellUnknown;
74  }();
75 
76  ColoredMeshGrid::Position position = ColoredMeshGrid::Position::Zero();
77 
78  // x and y are swapped on purpose.
79  position.y() = -cellIndex.x() * resolution;
80  position.x() = -cellIndex.y() * resolution;
81 
82  meshGrid.setColoredVertex(cellIndexCropped, position, color);
83  });
84 
85  // x and y are swapped on purpose.
86  // see cartographer/mapping/2d/probability_grid.cc
87  const double maxX = grid.limits().max().x();
88  const double maxY = grid.limits().max().y();
89 
90  meshGrid.innerSlicePosition = Eigen::Vector3f(maxX, maxY, 0.);
91 
92  return meshGrid;
93  }
94 
96  toOccupancyGrid(const ::cartographer::mapping::ProbabilityGrid& grid)
97  {
98  const auto resolution = static_cast<float>(grid.limits().resolution());
99 
100  Eigen::Array2i offset = Eigen::Array2i::Zero();
101  ::cartographer::mapping::CellLimits mapLimits = grid.limits().cell_limits();
102  grid.ComputeCroppedLimits(&offset, &mapLimits);
103 
104  armem::vision::OccupancyGrid::Grid occGrid(mapLimits.num_y_cells, mapLimits.num_x_cells);
105 
106  ::cartographer::mapping::XYIndexRangeIterator iter(mapLimits);
107 
108  std::for_each(iter.begin(),
109  iter.end(),
110  [&](const Eigen::Array2i& cellIndexCropped)
111  {
112  const auto cellIndex = cellIndexCropped + offset;
113 
114  const float probability = grid.GetProbability(cellIndex);
115  const bool isKnown = grid.IsKnown(cellIndex);
116 
117  // x and y are mirrored
118  occGrid(mapLimits.num_y_cells - 1 - cellIndexCropped.y(),
119  mapLimits.num_x_cells - 1 - cellIndexCropped.x()) =
120  isKnown ? probability : 0.F;
121  });
122 
123  // x and y are swapped on purpose.
124  // see cartographer/mapping/2d/probability_grid.cc
125 
126  const int inner_shift_x =
127  grid.limits().cell_limits().num_x_cells - (offset.x() + mapLimits.num_x_cells);
128  const int inner_shift_y =
129  grid.limits().cell_limits().num_y_cells - (offset.y() + mapLimits.num_y_cells);
130 
131  const float maxY = resolution - grid.limits().max().y() + resolution * inner_shift_y;
132  const float maxX = resolution - grid.limits().max().x() + resolution * inner_shift_x;
133 
135  .resolution = resolution,
136  .frame = MapFrame,
137  // Intentionally, we swap x and y. See comment above.
138  .pose = Eigen::Isometry3f(Eigen::Translation3f(maxY, maxX, 0.F)),
139  .grid = occGrid};
140  }
141 
143  toOccupancyGrid(const ::cartographer::mapping::Grid2D& grid)
144  {
145  const auto* probGrid = dynamic_cast<const ::cartographer::mapping::ProbabilityGrid*>(&grid);
146  if (probGrid != nullptr)
147  {
148  auto occ = toOccupancyGrid(*probGrid);
149  return occ;
150  }
151 
152  throw InvalidArgumentException();
153  }
154 
155  ColoredMeshGrid
156  toMeshGrid(const ::cartographer::mapping::Grid2D& grid)
157  {
158  const auto* probGrid = dynamic_cast<const ::cartographer::mapping::ProbabilityGrid*>(&grid);
159 
160  if (probGrid != nullptr)
161  {
162  return toMeshGrid(*probGrid);
163  }
164 
165  // const auto* tsdf = dynamic_cast<const cartographer::mapping::TSDF2D*>(&grid);
166  // if (tsdf)
167  // {
168  // ARMARX_INFO << "Processing tsdf grid";
169  // return toMeshGrid(*tsdf, resolution);
170  // }
171 
172  throw InvalidArgumentException();
173  }
174 
175  cv::Mat2b
176  toImage(const ::cartographer::mapping::ProbabilityGrid& grid)
177  {
178  Eigen::Array2i offset;
179  ::cartographer::mapping::CellLimits mapLimits;
180  grid.ComputeCroppedLimits(&offset, &mapLimits);
181 
182  ::cartographer::mapping::XYIndexRangeIterator iter(mapLimits);
183 
184  cv::Mat1f outputMap(mapLimits.num_x_cells, mapLimits.num_y_cells);
185  cv::Mat1b outputMapMask(mapLimits.num_x_cells, mapLimits.num_y_cells);
186 
187  std::for_each(iter.begin(),
188  iter.end(),
189  [&](const ::Eigen::Array2i& cellIndexCropped)
190  {
191  const auto cellIndex = cellIndexCropped + offset;
192  const cv::Point idx{cellIndexCropped[1], cellIndexCropped[0]};
193 
194  outputMap.at<float>(idx) = grid.GetProbability(cellIndex);
195  outputMapMask.at<uint8_t>(idx) =
196  static_cast<uint8_t>(grid.IsKnown(cellIndex));
197  });
198 
199  outputMap *= std::numeric_limits<uint8_t>::max(); // Scale [0..1] -> [0..255]
200  outputMapMask *= std::numeric_limits<uint8_t>::max(); // Scale [0..1] -> [0..255]
201 
202  cv::Mat1b out;
203  outputMap.convertTo(out, CV_8UC1);
204 
205  cv::Mat1b outMask;
206  outputMapMask.convertTo(outMask, CV_8UC1);
207  outputMapMask *= std::numeric_limits<uint8_t>::max(); // Scale {0,1} -> {0,255}
208 
209  cv::Mat2b outWithMask;
210  cv::merge(std::vector({out, outMask}), outWithMask);
211 
212  return outWithMask;
213  }
214 
215  cv::Mat2b
216  toImage(const ::cartographer::mapping::TSDF2D& tsdf)
217  {
218  const ::cartographer::mapping::CellLimits& mapLimits = tsdf.limits().cell_limits();
219 
220  ::cartographer::mapping::XYIndexRangeIterator iter(mapLimits);
221 
222  cv::Mat1f outputMap(mapLimits.num_x_cells, mapLimits.num_y_cells);
223  cv::Mat1f outputMapMask(mapLimits.num_x_cells, mapLimits.num_y_cells);
224 
225  std::for_each(iter.begin(),
226  iter.end(),
227  [&](const ::Eigen::Array2i& cellIndex)
228  {
229  const cv::Point idx{cellIndex[1], cellIndex[0]};
230 
231  outputMap.at<float>(idx) = tsdf.GetTSD(cellIndex);
232  outputMapMask.at<bool>(idx) = tsdf.IsKnown(cellIndex);
233  });
234 
235  outputMap *= std::numeric_limits<uint8_t>::max(); // Scale [0..1] -> [0..255]
236 
237  cv::Mat1b out;
238  outputMap.convertTo(out, CV_8UC1);
239 
240  cv::Mat1b outMask;
241  outputMapMask.convertTo(outMask, CV_8UC1);
242  outputMapMask *= std::numeric_limits<uint8_t>::max(); // Scale {0,1} -> {0,255}
243 
244  cv::Mat2b outWithMask;
245  cv::merge(std::vector({out, outMask}), outWithMask);
246 
247  return outWithMask;
248  }
249 
250  cv::Mat2b
251  toImage(const ::cartographer::mapping::Grid2D& grid)
252  {
253  const auto* probGrid = dynamic_cast<const ::cartographer::mapping::ProbabilityGrid*>(&grid);
254 
255  if (probGrid != nullptr)
256  {
257  return toImage(*probGrid);
258  }
259 
260  const auto* tsdf = dynamic_cast<const ::cartographer::mapping::TSDF2D*>(&grid);
261  if (tsdf != nullptr)
262  {
263  return toImage(*tsdf);
264  }
265 
266  return {};
267  }
268 
269 } // namespace armarx::localization_and_mapping::cartographer_adapter
armarx::localization_and_mapping::cartographer_adapter::ColoredMeshGrid
Definition: types.h:74
armarx::armem::vision::OccupancyGrid::Grid
Eigen::Array< CellType, Eigen::Dynamic, Eigen::Dynamic > Grid
Definition: types.h:45
armarx::localization_and_mapping::cartographer_adapter::ColoredMeshGrid::Color
Eigen::Vector4i Color
Definition: types.h:78
armarx::armem::vision::OccupancyGrid
Definition: types.h:36
merge
Use of this software is granted under one of the following two to be chosen freely by the user Boost Software License Version Marcin Kalicinski Permission is hereby free of to any person or organization obtaining a copy of the software and accompanying documentation covered by this and transmit the and to prepare derivative works of the and to permit third parties to whom the Software is furnished to do all subject to the including the above license this restriction and the following must be included in all copies of the in whole or in and all derivative works of the unless such copies or derivative works are solely in the form of machine executable object code generated by a source language processor THE SOFTWARE IS PROVIDED AS WITHOUT WARRANTY OF ANY EXPRESS OR INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF FITNESS FOR A PARTICULAR TITLE AND NON INFRINGEMENT IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER WHETHER IN TORT OR ARISING OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE The MIT Marcin Kalicinski Permission is hereby free of to any person obtaining a copy of this software and associated documentation to deal in the Software without including without limitation the rights to merge
Definition: license.txt:39
armarx::MapFrame
const std::string MapFrame
Definition: FramedPose.h:67
FramedPose.h
armarx::localization_and_mapping::cartographer_adapter::toMeshGrid
ColoredMeshGrid toMeshGrid(const ::cartographer::mapping::Grid2D &grid)
Definition: grid_conversion.cpp:156
armarx::localization_and_mapping::cartographer_adapter::toOccupancyGrid
armem::vision::OccupancyGrid toOccupancyGrid(const ::cartographer::mapping::Grid2D &grid)
Definition: grid_conversion.cpp:143
armarx::localization_and_mapping::cartographer_adapter::ColoredMeshGrid::vertices
VertexGrid vertices
Definition: types.h:84
max
T max(T t1, T t2)
Definition: gdiam.h:51
armarx::localization_and_mapping::cartographer_adapter
This file is part of ArmarX.
Definition: ApproximateTimeQueue.cpp:15
armarx::localization_and_mapping::cartographer_adapter::toMeshGrid
ColoredMeshGrid toMeshGrid(const ::cartographer::mapping::ProbabilityGrid &grid)
Definition: grid_conversion.cpp:40
armarx::armem::vision::OccupancyGrid::resolution
float resolution
Definition: types.h:38
armarx::localization_and_mapping::cartographer_adapter::toImage
cv::Mat2b toImage(const ::cartographer::mapping::Grid2D &grid)
Definition: grid_conversion.cpp:251
grid_conversion.h
armarx::localization_and_mapping::cartographer_adapter::ColoredMeshGrid::colors
ColorGrid colors
Definition: types.h:85
std
Definition: Application.h:66
types.h
armarx::localization_and_mapping::cartographer_adapter::ColoredMeshGrid::ColoredMeshGrid
ColoredMeshGrid()=default
armarx::localization_and_mapping::cartographer_adapter::ColoredMeshGrid::Position
Eigen::Vector3f Position
Definition: types.h:79
armarx::localization_and_mapping::cartographer_adapter::ColoredMeshGrid::setColoredVertex
void setColoredVertex(const Eigen::Array2i &idx, const Position &position, const Color &color)
Definition: grid_conversion.cpp:31
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27