testSignedDistance3d.cpp
Go to the documentation of this file.
1 /*
2  * testSignedDistance3d.cpp
3  *
4  * Created on: Aug 10, 2020
5  * Author: Ruben Grandia
6  * Institute: ETH Zurich
7  */
8 
9 #include <gtest/gtest.h>
10 
14 
15 #include "naiveSignedDistance.hpp"
16 
17 using namespace grid_map;
18 using namespace signed_distance_field;
19 
20 TEST(testSignedDistance3d, flatTerrain) {
21  const int n = 3;
22  const int m = 4;
23  const float resolution = 0.1;
24  const float terrainHeight = 0.5;
25  const Matrix map = Matrix::Constant(n, m, terrainHeight);
26  const float minHeight = map.minCoeff();
27  const float maxHeight = map.maxCoeff();
28 
29  const float testHeightAboveTerrain = 3.0;
30  const auto naiveSignedDistanceAbove = naiveSignedDistanceAtHeight(map, testHeightAboveTerrain, resolution);
31  const auto signedDistanceAbove = signedDistanceAtHeight(map, testHeightAboveTerrain, resolution, minHeight, maxHeight);
32  ASSERT_TRUE(isEqualSdf(signedDistanceAbove, naiveSignedDistanceAbove, 1e-4));
33 
34  const float testHeightBelowTerrain = -3.0;
35  const auto naiveSignedDistanceBelow = naiveSignedDistanceAtHeight(map, testHeightBelowTerrain, resolution);
36  const auto signedDistanceBelow = signedDistanceAtHeight(map, testHeightBelowTerrain, resolution, minHeight, maxHeight);
37  ASSERT_TRUE(isEqualSdf(signedDistanceBelow, naiveSignedDistanceBelow, 1e-4));
38 }
39 
40 TEST(testSignedDistance3d, randomTerrain) {
41  const int n = 20;
42  const int m = 30;
43  const float resolution = 0.1;
44  Matrix map = Matrix::Random(n, m); // random [-1.0, 1.0]
45  const float minHeight = map.minCoeff();
46  const float maxHeight = map.maxCoeff();
47 
48  // Check at different heights, resulting in different levels of sparsity.
49  float heightStep = 0.1;
50  for (float height = -1.0 - heightStep; height < 1.0 + heightStep; height += heightStep) {
51  const auto naiveSignedDistance = naiveSignedDistanceAtHeight(map, height, resolution);
52  const auto signedDistance = signedDistanceAtHeight(map, height, resolution, minHeight, maxHeight);
53 
54  ASSERT_TRUE(isEqualSdf(signedDistance, naiveSignedDistance, 1e-4)) << "height: " << height;
55  }
56 }
57 
58 TEST(testSignedDistance3d, randomTerrainInterpolation) {
59  const int n = 20;
60  const int m = 30;
61  const float resolution = 0.1;
62  GridMap map;
63  map.setGeometry({n * resolution, m * resolution}, resolution);
64  map.add("elevation");
65  map.get("elevation").setRandom(); // random [-1.0, 1.0]
66  const Matrix mapData = map.get("elevation");
67  const float minHeight = mapData.minCoeff();
68  const float maxHeight = mapData.maxCoeff();
69 
70  SignedDistanceField sdf(map, "elevation", minHeight, maxHeight);
71 
72  // Check at different heights/
73  for (float height = minHeight; height < maxHeight; height += resolution) {
74  const auto naiveSignedDistance = naiveSignedDistanceAtHeight(mapData, height, resolution);
75 
76  for (int i = 0; i < mapData.rows(); ++i) {
77  for (int j = 0; j < mapData.rows(); ++j) {
78  Position position2d;
79  map.getPosition({i, j}, position2d);
80 
81  const auto sdfValue = sdf.value({position2d.x(), position2d.y(), height});
82  const auto sdfCheck = naiveSignedDistance(i, j);
83  ASSERT_LT(std::abs(sdfValue - sdfCheck), 1e-4);
84  }
85  }
86  }
87 }
88 
89 TEST(testSignedDistance3d, randomTerrainDerivative) {
90  const int n = 10;
91  const int m = 20;
92  const float resolution = 0.1;
93  GridMap map;
94  map.setGeometry({n * resolution, m * resolution}, resolution);
95  map.add("elevation");
96  map.get("elevation").setRandom(); // random [-1.0, 1.0]
97  const Matrix mapData = map.get("elevation");
98  const float minHeight = mapData.minCoeff();
99  const float maxHeight = mapData.maxCoeff();
100 
101  SignedDistanceField sdf(map, "elevation", minHeight, maxHeight);
102 
103  // Check at different heights/
104  int numLayers = (maxHeight - minHeight) / resolution;
105  for (int k = 0; k <= numLayers; ++k) {
106  const float height = minHeight + k * resolution;
107  const auto naiveSignedDistance = naiveSignedDistanceAtHeight(mapData, height, resolution);
108  const auto naiveSignedDistanceNext = naiveSignedDistanceAtHeight(mapData, height + resolution, resolution);
109  const auto naiveSignedDistancePrevious = naiveSignedDistanceAtHeight(mapData, height - resolution, resolution);
110 
111  for (int i = 0; i < mapData.rows(); ++i) {
112  for (int j = 0; j < mapData.rows(); ++j) {
113  Position position2d;
114  map.getPosition({i, j}, position2d);
115  const auto sdfderivative = sdf.valueAndDerivative(Position3{position2d.x(), position2d.y(), height});
116  const auto sdfCheck = naiveSignedDistance(i, j);
117  ASSERT_LT(std::abs(sdfderivative.first - sdfCheck), 1e-4);
118 
119  // Check finite difference
120  float dx = 0.0;
121  if (i > 0) {
122  if (i + 1 < mapData.rows()) {
123  dx = (naiveSignedDistance(i + 1, j) - naiveSignedDistance(i - 1, j)) / (-2.0 * resolution);
124  } else {
125  dx = (naiveSignedDistance(i, j) - naiveSignedDistance(i - 1, j)) / (-resolution);
126  }
127  } else {
128  dx = (naiveSignedDistance(i + 1, j) - naiveSignedDistance(i, j)) / (-resolution);
129  }
130  ASSERT_LT(std::abs(dx - sdfderivative.second.x()), 1e-4);
131 
132  float dy = 0.0;
133  if (j > 0) {
134  if (j + 1 < mapData.cols()) {
135  dy = (naiveSignedDistance(i, j + 1) - naiveSignedDistance(i, j - 1)) / (-2.0 * resolution);
136  } else {
137  dy = (naiveSignedDistance(i, j) - naiveSignedDistance(i, j - 1)) / (-resolution);
138  }
139  } else {
140  dy = (naiveSignedDistance(i, j + 1) - naiveSignedDistance(i, j)) / (-resolution);
141  }
142  ASSERT_LT(std::abs(dy - sdfderivative.second.y()), 1e-4);
143 
144  float dz = 0.0;
145  if (k > 0) {
146  if (k < numLayers) {
147  dz = (naiveSignedDistanceNext(i, j) - naiveSignedDistancePrevious(i, j)) / (2.0 * resolution);
148  } else {
149  dz = (naiveSignedDistance(i, j) - naiveSignedDistancePrevious(i, j)) / (resolution);
150  }
151  } else {
152  dz = (naiveSignedDistanceNext(i, j) - naiveSignedDistance(i, j)) / (resolution);
153  }
154  ASSERT_LT(std::abs(dz - sdfderivative.second.z()), 1e-4);
155  }
156  }
157  }
158 }
159 
160 TEST(testSignedDistance3d, extrapolation) {
161  const int n = 20;
162  const int m = 30;
163  const float resolution = 0.1;
164  const float h = 0.5;
165  GridMap map;
166  map.setGeometry({n * resolution, m * resolution}, resolution);
167  map.add("elevation");
168  map.get("elevation").setConstant(h); // random [-1.0, 1.0]
169  const Matrix mapData = map.get("elevation");
170  const float minHeight = h - resolution;
171  const float maxHeight = h + resolution;
172 
173  SignedDistanceField sdf(map, "elevation", minHeight, maxHeight);
174 
175  // Check at different heights/
176  for (float height = h - 1.0; height < h + 1.0; height += resolution) {
177  const auto naiveSignedDistance = naiveSignedDistanceAtHeight(mapData, height, resolution);
178 
179  for (int i = 0; i < mapData.rows(); ++i) {
180  for (int j = 0; j < mapData.rows(); ++j) {
181  Position position2d;
182  map.getPosition({i, j}, position2d);
183 
184  const auto sdfValueAndDerivative = sdf.valueAndDerivative({position2d.x(), position2d.y(), height});
185  const auto sdfCheck = naiveSignedDistance(i, j);
186  ASSERT_LT(std::abs(sdfValueAndDerivative.first - sdfCheck), 1e-4);
187 
188  // Constant terrain, derivative should be up everywhere
189  ASSERT_LT((sdfValueAndDerivative.second - SignedDistanceField::Derivative3::UnitZ()).norm(), 1e-4);
190  }
191  }
192  }
193 }
void setGeometry(const Length &length, const double resolution, const Position &position=Position::Zero())
const Matrix & get(const std::string &layer) const
Matrix signedDistanceAtHeight(const Matrix &elevationMap, float height, float resolution, float minHeight, float maxHeight)
double value(const Position3 &position) const noexcept
Matrix naiveSignedDistanceAtHeight(const Matrix &elevationMap, float height, float resolution)
std::pair< double, Derivative3 > valueAndDerivative(const Position3 &position) const noexcept
Eigen::Vector2d Position
Eigen::MatrixXf Matrix
void add(const std::string &layer, const double value=NAN)
Eigen::Vector3d Position3
TEST(GridMap, CopyConstructor)
bool getPosition(const Index &index, Position &position) const
bool isEqualSdf(const Matrix &sdf0, const Matrix &sdf1, float tol)


grid_map_sdf
Author(s): Takahiro Miki , Péter Fankhauser
autogenerated on Wed Jul 5 2023 02:23:42