MIRA
RasterRangeScan.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) by
3  * MetraLabs GmbH (MLAB), GERMANY
4  * and
5  * Neuroinformatics and Cognitive Robotics Labs (NICR) at TU Ilmenau, GERMANY
6  * All rights reserved.
7  *
8  * Redistribution and modification of this code is strictly prohibited.
9  *
10  * IN NO EVENT SHALL "MLAB" OR "NICR" BE LIABLE TO ANY PARTY FOR DIRECT,
11  * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
12  * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF "MLAB" OR
13  * "NICR" HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14  *
15  * "MLAB" AND "NICR" SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
16  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
18  * ON AN "AS IS" BASIS, AND "MLAB" AND "NICR" HAVE NO OBLIGATION TO
19  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR MODIFICATIONS.
20  */
21 
31 #ifndef _MIRA_RASTERRANGESCAN_H_
32 #define _MIRA_RASTERRANGESCAN_H_
33 
34 #include <math/Math.h>
35 
37 #include <transform/Pose.h>
38 #include <robot/RangeScanInfo.h>
39 #include <geometry/DistanceLUT.h>
40 
41 namespace mira { namespace maps {
42 
44 
45 
66 {
67  Pose2 origin; // the offset and orientation of the sensor cone origin
68 
69  float distanceOffset; // the distance offset from the sensor cone origin to
70  // the sensor 'plane' (start of measurement)
71 
72  float coneAngle; // the cones opening angle
73 };
223 template<typename Visitor, bool VisitorUsesWorldDistance=true>
224 void rasterSensorCone(const RangeScanCone& c,
225  float maxRange, float cellSize, Visitor& visitor);
226 
229 // Implementation:
230 
231 template<typename Visitor, bool VisitorUsesWorldDistance>
233 {
234 public:
235  RasterSensorConeVisitor(Visitor& visitor, const DistanceLUT::Region& region, float cellSize, float distOffset) :
236  mVisitor(visitor), mRegion(region), mCellSize(cellSize), mDistanceOffset(distOffset) {}
237 
238  void operator()(int xl, int xr, int y)
239  {
240  mVisitor.beginScanline(y);
241 
242  DistanceLUT::iterator i = mRegion.getIterator(xl,y);
243  for(int x=xl; x<=xr; ++x, ++i)
244  {
245  if constexpr (VisitorUsesWorldDistance) {
246  float min_d = i->minDist * mCellSize - mDistanceOffset;
247  float max_d = i->maxDist * mCellSize - mDistanceOffset;
248  mVisitor(x,y, min_d, max_d);
249  } else {
250  mVisitor(x,y, i->minDist, i->maxDist);
251  }
252  }
253  }
254 
255 private:
256 
257 
258  Visitor& mVisitor;
259  const DistanceLUT::Region& mRegion;
260  float mCellSize;
261  float mDistanceOffset;
262 };
263 
265 
266 template<typename Visitor, bool VisitorUsesWorldDistance>
267 inline void rasterSensorCone(const RangeScanCone& c,
268  float maxRange, float cellSize, Visitor& visitor)
269 {
270  float alpha = c.coneAngle / 2.0f; // the half cone angle
271 
272  float x = c.origin.x();
273  float y = c.origin.y();
274  float phi = c.origin.phi();
275 
276  float phi_left = phi - alpha;
277  float phi_right = phi + alpha;
278 
292  maxRange += c.distanceOffset;
293  maxRange += cellSize;
294 
295  if (cosf(alpha) < std::numeric_limits<float>::min()) {
296  MIRA_THROW(XInvalidConfig, "rasterSensorCone: "
297  "Invalid cone angle " << c.coneAngle << " (must be 0 < angle < 180deg)");
298  // avoid div-by-zero or negative maxRange!
299  }
300  maxRange /= cosf(alpha);
301 
302  // ending position of left ray of the cone
303  float x_left = cosf(phi_left) * maxRange + x;
304  float y_left = sinf(phi_left) * maxRange + y;
305 
306  // ending position of right ray of the cone
307  float x_right = cosf(phi_right) * maxRange + x;
308  float y_right = sinf(phi_right) * maxRange + y;
309 
310  int xi, yi;
311  float xi_eps, yi_eps;
312 
313  // cell of the origin
314  xi = (int)floor(x/cellSize);
315  yi = (int)floor(y/cellSize);
316 
317  // get the position of the origin within the cell (for sub-cell precision)
318  xi_eps = x/cellSize - (float)xi;
319  yi_eps = y/cellSize - (float)yi;
320 
321  //std::cout << "x:" << x << ",y:"<<y<<",xi:"<<xi<<",yi"<<yi<<",xi_eps"<<xi_eps<<",yi_eps"<<yi_eps<< std::endl;
322 
323  // compute the index of the cells where the left and right ray end
324  int xi_left, yi_left;
325  int xi_right, yi_right;
326 
327  xi_left = (int)floor(x_left/cellSize);
328  yi_left = (int)floor(y_left/cellSize);
329 
330  xi_right = (int)floor(x_right/cellSize);
331  yi_right = (int)floor(y_right/cellSize);
332 
333  // get region we need from the distance LUT
334  int ri = maxRange / cellSize;
335  DistanceLUT::Region r = DistanceLUT::instance().getRegion(Point2f(xi_eps, yi_eps),
336  Rect2i(Point2i(-ri,-ri),
337  Point2i(ri,ri)));
338 
339  // and raster the triangle, via our RasterSensorConeVisitor, that translates
340  // the calls to the user specified visitor.
341  visitor.beginScan(c);
343  ConeVisitor coneVisitor(visitor, r, cellSize, c.distanceOffset);
344  Point2i center(0,0);
345  Point2i left(xi_left-xi,yi_left-yi);
346  Point2i right(xi_right-xi,yi_right-yi);
347  rasterTriangle(center, left, right, coneVisitor);
348 }
349 
351 
352 }}
353 
354 #endif
Rect< int, 2 > Rect2i
Definition: RasterRangeScan.h:232
Configuration of a sensor cone.
Definition: RasterRangeScan.h:65
static Type & instance()
float distanceOffset
Definition: RasterRangeScan.h:69
Point< int, 2 > Point2i
void rasterTriangle(Point2i p0, Point2i p1, Point2i p2, Visitor &&visitor)
Pose2 origin
Definition: RasterRangeScan.h:67
#define MIRA_THROW(ex, msg)
const CellDist * iterator
void rasterSensorCone(const RangeScanCone &c, float maxRange, float cellSize, Visitor &visitor)
Function for fast rasterization of sensor cones cell by cell.
Definition: RasterRangeScan.h:267
T alpha
RasterSensorConeVisitor(Visitor &visitor, const DistanceLUT::Region &region, float cellSize, float distOffset)
Definition: RasterRangeScan.h:235
Point< float, 2 > Point2f
void operator()(int xl, int xr, int y)
Definition: RasterRangeScan.h:238
float coneAngle
Definition: RasterRangeScan.h:72
iterator getIterator(int x, int y) const