OccGridMapUtil.h
Go to the documentation of this file.
1 //=================================================================================================
2 // Copyright (c) 2011, Stefan Kohlbrecher, TU Darmstadt
3 // All rights reserved.
4 
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above copyright
10 // notice, this list of conditions and the following disclaimer in the
11 // documentation and/or other materials provided with the distribution.
12 // * Neither the name of the Simulation, Systems Optimization and Robotics
13 // group, TU Darmstadt nor the names of its contributors may be used to
14 // endorse or promote products derived from this software without
15 // specific prior written permission.
16 
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
21 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //=================================================================================================
28 
29 #ifndef __OccGridMapUtil_h_
30 #define __OccGridMapUtil_h_
31 
32 #include <cmath>
33 
34 #include "../scan/DataPointContainer.h"
35 #include "../util/UtilFunctions.h"
36 
37 namespace hectorslam {
38 
39 template<typename ConcreteOccGridMap, typename ConcreteCacheMethod>
41 {
42 public:
43 
44  OccGridMapUtil(const ConcreteOccGridMap* gridMap)
45  : concreteGridMap(gridMap)
46  , size(0)
47  {
48  mapObstacleThreshold = gridMap->getObstacleThreshold();
49  cacheMethod.setMapSize(gridMap->getMapDimensions());
50  }
51 
53  {}
54 
55 public:
56 
57  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
58 
59  inline Eigen::Vector3f getWorldCoordsPose(const Eigen::Vector3f& mapPose) const { return concreteGridMap->getWorldCoordsPose(mapPose); };
60  inline Eigen::Vector3f getMapCoordsPose(const Eigen::Vector3f& worldPose) const { return concreteGridMap->getMapCoordsPose(worldPose); };
61 
62  inline Eigen::Vector2f getWorldCoordsPoint(const Eigen::Vector2f& mapPoint) const { return concreteGridMap->getWorldCoords(mapPoint); };
63 
64  void getCompleteHessianDerivs(const Eigen::Vector3f& pose, const DataContainer& dataPoints, Eigen::Matrix3f& H, Eigen::Vector3f& dTr)
65  {
66  int size = dataPoints.getSize();
67 
68  Eigen::Affine2f transform(getTransformForState(pose));
69 
70  float sinRot = sin(pose[2]);
71  float cosRot = cos(pose[2]);
72 
73  H = Eigen::Matrix3f::Zero();
74  dTr = Eigen::Vector3f::Zero();
75 
76  for (int i = 0; i < size; ++i) {
77 
78  const Eigen::Vector2f& currPoint (dataPoints.getVecEntry(i));
79 
80  Eigen::Vector3f transformedPointData(interpMapValueWithDerivatives(transform * currPoint));
81 
82  float funVal = 1.0f - transformedPointData[0];
83 
84  dTr[0] += transformedPointData[1] * funVal;
85  dTr[1] += transformedPointData[2] * funVal;
86 
87  float rotDeriv = ((-sinRot * currPoint.x() - cosRot * currPoint.y()) * transformedPointData[1] + (cosRot * currPoint.x() - sinRot * currPoint.y()) * transformedPointData[2]);
88 
89  dTr[2] += rotDeriv * funVal;
90 
91  H(0, 0) += util::sqr(transformedPointData[1]);
92  H(1, 1) += util::sqr(transformedPointData[2]);
93  H(2, 2) += util::sqr(rotDeriv);
94 
95  H(0, 1) += transformedPointData[1] * transformedPointData[2];
96  H(0, 2) += transformedPointData[1] * rotDeriv;
97  H(1, 2) += transformedPointData[2] * rotDeriv;
98  }
99 
100  H(1, 0) = H(0, 1);
101  H(2, 0) = H(0, 2);
102  H(2, 1) = H(1, 2);
103 
104  }
105 
106  Eigen::Matrix3f getCovarianceForPose(const Eigen::Vector3f& mapPose, const DataContainer& dataPoints)
107  {
108 
109  float deltaTransX = 1.5f;
110  float deltaTransY = 1.5f;
111  float deltaAng = 0.05f;
112 
113  float x = mapPose[0];
114  float y = mapPose[1];
115  float ang = mapPose[2];
116 
117  Eigen::Matrix<float, 3, 7> sigmaPoints;
118 
119  sigmaPoints.block<3, 1>(0, 0) = Eigen::Vector3f(x + deltaTransX, y, ang);
120  sigmaPoints.block<3, 1>(0, 1) = Eigen::Vector3f(x - deltaTransX, y, ang);
121  sigmaPoints.block<3, 1>(0, 2) = Eigen::Vector3f(x, y + deltaTransY, ang);
122  sigmaPoints.block<3, 1>(0, 3) = Eigen::Vector3f(x, y - deltaTransY, ang);
123  sigmaPoints.block<3, 1>(0, 4) = Eigen::Vector3f(x, y, ang + deltaAng);
124  sigmaPoints.block<3, 1>(0, 5) = Eigen::Vector3f(x, y, ang - deltaAng);
125  sigmaPoints.block<3, 1>(0, 6) = mapPose;
126 
127  Eigen::Matrix<float, 7, 1> likelihoods;
128 
129  likelihoods[0] = getLikelihoodForState(Eigen::Vector3f(x + deltaTransX, y, ang), dataPoints);
130  likelihoods[1] = getLikelihoodForState(Eigen::Vector3f(x - deltaTransX, y, ang), dataPoints);
131  likelihoods[2] = getLikelihoodForState(Eigen::Vector3f(x, y + deltaTransY, ang), dataPoints);
132  likelihoods[3] = getLikelihoodForState(Eigen::Vector3f(x, y - deltaTransY, ang), dataPoints);
133  likelihoods[4] = getLikelihoodForState(Eigen::Vector3f(x, y, ang + deltaAng), dataPoints);
134  likelihoods[5] = getLikelihoodForState(Eigen::Vector3f(x, y, ang - deltaAng), dataPoints);
135  likelihoods[6] = getLikelihoodForState(Eigen::Vector3f(x, y, ang), dataPoints);
136 
137  float invLhNormalizer = 1 / likelihoods.sum();
138 
139  std::cout << "\n lhs:\n" << likelihoods;
140 
141  Eigen::Vector3f mean(Eigen::Vector3f::Zero());
142 
143  for (int i = 0; i < 7; ++i) {
144  mean += (sigmaPoints.block<3, 1>(0, i) * likelihoods[i]);
145  }
146 
147  mean *= invLhNormalizer;
148 
149  Eigen::Matrix3f covMatrixMap(Eigen::Matrix3f::Zero());
150 
151  for (int i = 0; i < 7; ++i) {
152  Eigen::Vector3f sigPointMinusMean(sigmaPoints.block<3, 1>(0, i) - mean);
153  covMatrixMap += (likelihoods[i] * invLhNormalizer) * (sigPointMinusMean * (sigPointMinusMean.transpose()));
154  }
155 
156  return covMatrixMap;
157 
158  //covMatrix.cwise() * invLhNormalizer;
159  //transform = getTransformForState(Eigen::Vector3f(x-deltaTrans, y, ang);
160  }
161 
162  Eigen::Matrix3f getCovMatrixWorldCoords(const Eigen::Matrix3f& covMatMap)
163  {
164 
165  //std::cout << "\nCovMap:\n" << covMatMap;
166 
167  Eigen::Matrix3f covMatWorld;
168 
169  float scaleTrans = concreteGridMap->getCellLength();
170  float scaleTransSq = util::sqr(scaleTrans);
171 
172  covMatWorld(0, 0) = covMatMap(0, 0) * scaleTransSq;
173  covMatWorld(1, 1) = covMatMap(1, 1) * scaleTransSq;
174 
175  covMatWorld(1, 0) = covMatMap(1, 0) * scaleTransSq;
176  covMatWorld(0, 1) = covMatWorld(1, 0);
177 
178  covMatWorld(2, 0) = covMatMap(2, 0) * scaleTrans;
179  covMatWorld(0, 2) = covMatWorld(2, 0);
180 
181  covMatWorld(2, 1) = covMatMap(2, 1) * scaleTrans;
182  covMatWorld(1, 2) = covMatWorld(2, 1);
183 
184  covMatWorld(2, 2) = covMatMap(2, 2);
185 
186  return covMatWorld;
187  }
188 
189  float getLikelihoodForState(const Eigen::Vector3f& state, const DataContainer& dataPoints)
190  {
191  float resid = getResidualForState(state, dataPoints);
192 
193  return getLikelihoodForResidual(resid, dataPoints.getSize());
194  }
195 
196  float getLikelihoodForResidual(float residual, int numDataPoints)
197  {
198  float numDataPointsA = static_cast<int>(numDataPoints);
199  float sizef = static_cast<float>(numDataPointsA);
200 
201  return 1 - (residual / sizef);
202  }
203 
204  float getResidualForState(const Eigen::Vector3f& state, const DataContainer& dataPoints)
205  {
206  int size = dataPoints.getSize();
207 
208  int stepSize = 1;
209  float residual = 0.0f;
210 
211 
212  Eigen::Affine2f transform(getTransformForState(state));
213 
214  for (int i = 0; i < size; i += stepSize) {
215 
216  float funval = 1.0f - interpMapValue(transform * dataPoints.getVecEntry(i));
217  residual += funval;
218  }
219 
220  return residual;
221  }
222 
223  float getUnfilteredGridPoint(Eigen::Vector2i& gridCoords) const
224  {
225  return (concreteGridMap->getGridProbabilityMap(gridCoords.x(), gridCoords.y()));
226  }
227 
228  float getUnfilteredGridPoint(int index) const
229  {
230  return (concreteGridMap->getGridProbabilityMap(index));
231  }
232 
233  float interpMapValue(const Eigen::Vector2f& coords)
234  {
235  //check if coords are within map limits.
236  if (concreteGridMap->pointOutOfMapBounds(coords)){
237  return 0.0f;
238  }
239 
240  //map coords are alway positive, floor them by casting to int
241  Eigen::Vector2i indMin(coords.cast<int>());
242 
243  //get factors for bilinear interpolation
244  Eigen::Vector2f factors(coords - indMin.cast<float>());
245 
246  int sizeX = concreteGridMap->getSizeX();
247 
248  int index = indMin[1] * sizeX + indMin[0];
249 
250  // get grid values for the 4 grid points surrounding the current coords. Check cached data first, if not contained
251  // filter gridPoint with gaussian and store in cache.
252  if (!cacheMethod.containsCachedData(index, intensities[0])) {
254  cacheMethod.cacheData(index, intensities[0]);
255  }
256 
257  ++index;
258 
259  if (!cacheMethod.containsCachedData(index, intensities[1])) {
261  cacheMethod.cacheData(index, intensities[1]);
262  }
263 
264  index += sizeX-1;
265 
266  if (!cacheMethod.containsCachedData(index, intensities[2])) {
268  cacheMethod.cacheData(index, intensities[2]);
269  }
270 
271  ++index;
272 
273  if (!cacheMethod.containsCachedData(index, intensities[3])) {
275  cacheMethod.cacheData(index, intensities[3]);
276  }
277 
278  float xFacInv = (1.0f - factors[0]);
279  float yFacInv = (1.0f - factors[1]);
280 
281  return
282  ((intensities[0] * xFacInv + intensities[1] * factors[0]) * (yFacInv)) +
283  ((intensities[2] * xFacInv + intensities[3] * factors[0]) * (factors[1]));
284 
285  }
286 
287  Eigen::Vector3f interpMapValueWithDerivatives(const Eigen::Vector2f& coords)
288  {
289  //check if coords are within map limits.
290  if (concreteGridMap->pointOutOfMapBounds(coords)){
291  return Eigen::Vector3f(0.0f, 0.0f, 0.0f);
292  }
293 
294  //map coords are always positive, floor them by casting to int
295  Eigen::Vector2i indMin(coords.cast<int>());
296 
297  //get factors for bilinear interpolation
298  Eigen::Vector2f factors(coords - indMin.cast<float>());
299 
300  int sizeX = concreteGridMap->getSizeX();
301 
302  int index = indMin[1] * sizeX + indMin[0];
303 
304  // get grid values for the 4 grid points surrounding the current coords. Check cached data first, if not contained
305  // filter gridPoint with gaussian and store in cache.
306  if (!cacheMethod.containsCachedData(index, intensities[0])) {
308  cacheMethod.cacheData(index, intensities[0]);
309  }
310 
311  ++index;
312 
313  if (!cacheMethod.containsCachedData(index, intensities[1])) {
315  cacheMethod.cacheData(index, intensities[1]);
316  }
317 
318  index += sizeX-1;
319 
320  if (!cacheMethod.containsCachedData(index, intensities[2])) {
322  cacheMethod.cacheData(index, intensities[2]);
323  }
324 
325  ++index;
326 
327  if (!cacheMethod.containsCachedData(index, intensities[3])) {
329  cacheMethod.cacheData(index, intensities[3]);
330  }
331 
332  float dx1 = intensities[0] - intensities[1];
333  float dx2 = intensities[2] - intensities[3];
334 
335  float dy1 = intensities[0] - intensities[2];
336  float dy2 = intensities[1] - intensities[3];
337 
338  float xFacInv = (1.0f - factors[0]);
339  float yFacInv = (1.0f - factors[1]);
340 
341  return Eigen::Vector3f(
342  ((intensities[0] * xFacInv + intensities[1] * factors[0]) * (yFacInv)) +
343  ((intensities[2] * xFacInv + intensities[3] * factors[0]) * (factors[1])),
344  -((dx1 * xFacInv) + (dx2 * factors[0])),
345  -((dy1 * yFacInv) + (dy2 * factors[1]))
346  );
347  }
348 
349  Eigen::Affine2f getTransformForState(const Eigen::Vector3f& transVector) const
350  {
351  return Eigen::Translation2f(transVector[0], transVector[1]) * Eigen::Rotation2Df(transVector[2]);
352  }
353 
354  Eigen::Translation2f getTranslationForState(const Eigen::Vector3f& transVector) const
355  {
356  return Eigen::Translation2f(transVector[0], transVector[1]);
357  }
358 
360  {
361  cacheMethod.resetCache();
362  }
363 
365  {
366  samplePoints.clear();
367  }
368 
369  const std::vector<Eigen::Vector3f>& getSamplePoints() const
370  {
371  return samplePoints;
372  }
373 
374 protected:
375 
376  Eigen::Vector4f intensities;
377 
378  ConcreteCacheMethod cacheMethod;
379 
380  const ConcreteOccGridMap* concreteGridMap;
381 
382  std::vector<Eigen::Vector3f> samplePoints;
383 
384  int size;
385 
387 };
388 
389 }
390 
391 
392 #endif
const std::vector< Eigen::Vector3f > & getSamplePoints() const
Eigen::Vector2f getWorldCoordsPoint(const Eigen::Vector2f &mapPoint) const
f
std::vector< Eigen::Vector3f > samplePoints
float getUnfilteredGridPoint(Eigen::Vector2i &gridCoords) const
static float sqr(float val)
Definition: UtilFunctions.h:50
Eigen::Vector3f getMapCoordsPose(const Eigen::Vector3f &worldPose) const
float getLikelihoodForResidual(float residual, int numDataPoints)
const ConcreteOccGridMap * concreteGridMap
TFSIMD_FORCE_INLINE const tfScalar & y() const
ConcreteCacheMethod cacheMethod
Eigen::Vector3f interpMapValueWithDerivatives(const Eigen::Vector2f &coords)
float getLikelihoodForState(const Eigen::Vector3f &state, const DataContainer &dataPoints)
float interpMapValue(const Eigen::Vector2f &coords)
const DataPointType & getVecEntry(int index) const
Eigen::Affine2f getTransformForState(const Eigen::Vector3f &transVector) const
Eigen::Matrix3f getCovarianceForPose(const Eigen::Vector3f &mapPose, const DataContainer &dataPoints)
Eigen::Translation2f getTranslationForState(const Eigen::Vector3f &transVector) const
Eigen::Matrix3f getCovMatrixWorldCoords(const Eigen::Matrix3f &covMatMap)
TFSIMD_FORCE_INLINE const tfScalar & x() const
float getResidualForState(const Eigen::Vector3f &state, const DataContainer &dataPoints)
float getUnfilteredGridPoint(int index) const
EIGEN_MAKE_ALIGNED_OPERATOR_NEW Eigen::Vector3f getWorldCoordsPose(const Eigen::Vector3f &mapPose) const
void getCompleteHessianDerivs(const Eigen::Vector3f &pose, const DataContainer &dataPoints, Eigen::Matrix3f &H, Eigen::Vector3f &dTr)
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
OccGridMapUtil(const ConcreteOccGridMap *gridMap)
INLINE Rall1d< T, V, S > sin(const Rall1d< T, V, S > &arg)


hector_mapping
Author(s): Stefan Kohlbrecher
autogenerated on Sun Nov 3 2019 03:18:33