MIRA
Curve.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) by
3  * MetraLabs GmbH (MLAB), GERMANY
4  * All rights reserved.
5  *
6  * Redistribution and modification of this code is strictly prohibited.
7  *
8  * IN NO EVENT SHALL "MLAB" BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
9  * SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE
10  * OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF "MLABS" HS BEEN
11  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12  *
13  * "MLAB" SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
14  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
15  * A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
16  * "AS IS" BASIS, AND "MLAB" HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
17  * SUPPORT, UPDATES, ENHANCEMENTS OR MODIFICATIONS.
18  */
19 
28 #ifndef _MLAB_CURVE_H_
29 #define _MLAB_CURVE_H_
30 
31 #include <geometry/Point.h>
32 #include <transform/Pose.h>
33 #include <image/Img.h>
34 #include <math/IsApprox.h>
35 
36 namespace mira { namespace localization {
37 
39 
40 class Curve : public std::vector<Point2f>
41 {
42 public:
43 
44  Curve() :
45  std::vector<Point2f>()
46  {}
47 
48  Curve(const Curve& c) :
49  std::vector<Point2f>(c)
50  {}
51 
52  template<typename Reflector>
53  void reflect(Reflector& r)
54  {
55  MIRA_REFLECT_BASE(r, std::vector<Point2f>);
56  }
57 
58  void transform(const Pose2& pose);
59 
60  float distToPoint(const Point2f& p) const;
61 
62  // skip specifies the number of points to skip (4 means, take every 4th point only)
63  size_t closestPoint(const Point2f& p, size_t skip = 4) const;
64 
65  double matchWithCurve(const Curve& c, float maxDist = std::numeric_limits<float>::max(),
66  float coverage = 0.0f, size_t skip = 4, const Pose2& tf = Pose2(0, 0, 0));
67 
68  void draw(Img8U3& img, Color::RGB col, float scale, int x0, int y0) const;
69 
70  void merge(const Curve& c) {
71  foreach(const Point2f& p, c)
72  push_back(p);
73  }
74 };
75 
77 
78 inline void Curve::transform(const Pose2& pose)
79 {
80  const Eigen::Matrix2f R = pose.r.toRotationMatrix();
81  const Eigen::Vector2f& t = pose.t;
82 
83  for(size_t i = 0; i < size(); ++i)
84  {
85  Point2f& p = operator[](i);
86  p = R * p + t;
87  }
88 }
89 
90 inline float Curve::distToPoint(const Point2f& p) const
91 {
92  const Point2f& c = at(closestPoint(p));
93  return (p - c).norm();
94 }
95 
96 inline size_t Curve::closestPoint(const Point2f& p, size_t skip) const
97 {
98  if(empty())
99  MIRA_THROW(XRuntime, "Curve has no points");
100 
101  float min_sqdist = std::numeric_limits<float>::max();
102  size_t best = 0;
103  for (size_t i = 0; i < size(); i += skip)
104  {
105  const float sqd = (operator[](i) - p).squaredNorm();
106  if (sqd < min_sqdist) {
107  min_sqdist = sqd;
108  best = i;
109  }
110  }
111 
112  return best;
113 }
114 
115 inline double Curve::matchWithCurve(const Curve& pC, float maxDist,
116  float coverage, size_t skip, const Pose2& tf)
117 {
118  if(pC.empty())
119  return std::numeric_limits<double>::max(); // same logic as below
120 
121  const float maxDistSq = maxDist * maxDist;
122  const bool applyTf = !(tf.t.isZero() && isApprox<float, float>(tf.phi(), 0.0f, std::numeric_limits<float>::epsilon()));
123  const Eigen::Matrix2f tfR = tf.r.toRotationMatrix();
124  const Eigen::Vector2f& tfT = tf.t;
125 
126  float error = 0.0;
127  size_t count = 0;
128  for (size_t i = 0; i < size(); i += skip)
129  {
130  const Point2f xt(applyTf ? (tfR * at(i) + tfT) : at(i));
131  const Point2f& y = pC.at(pC.closestPoint(xt, skip));
132 
133  const float d = (xt - y).squaredNorm();
134 
135  // don't take point if its distance is above the limit
136  if (d >= maxDistSq)
137  continue;
138 
139  error += d;
140  ++count;
141  }
142 
143  if (count < static_cast<size_t>(((size() / skip) * coverage)))
144  return std::numeric_limits<double>::max();
145 
146  return (error / static_cast<float>(count));
147 }
148 
149 inline void Curve::draw(Img8U3& img, Color::RGB col, float scale, int x0, int y0) const
150 {
151  for (size_t i = 0; i < size(); i++)
152  {
153  const Point2f& point = at(i);
154  int x = x0 + (int) (scale * point.x() + 0.5);
155  int y = y0 - (int) (scale * point.y() + 0.5);
156  if (x>0 && x<img.width() && y>0 && y<img.height())
157  img(x, y) = col;
158  }
159 }
160 
162 
163 }
164 
165 template<>
166 class IsCollection<localization::Curve> : public std::true_type {};
167 
168 }
169 
170 #endif
float distToPoint(const Point2f &p) const
Definition: Curve.h:90
Curve(const Curve &c)
Definition: Curve.h:48
#define MIRA_REFLECT_BASE(reflector, BaseClass)
STL namespace.
double matchWithCurve(const Curve &c, float maxDist=std::numeric_limits< float >::max(), float coverage=0.0f, size_t skip=4, const Pose2 &tf=Pose2(0, 0, 0))
Definition: Curve.h:115
void transform(const Pose2 &pose)
Definition: Curve.h:78
#define MIRA_THROW(ex, msg)
void draw(Img8U3 &img, Color::RGB col, float scale, int x0, int y0) const
Definition: Curve.h:149
RigidTransform< float, 2 > Pose2
size_t closestPoint(const Point2f &p, size_t skip=4) const
Definition: Curve.h:96
int height() const
Definition: Curve.h:40
int width() const
void reflect(Reflector &r)
Definition: Curve.h:53
void merge(const Curve &c)
Definition: Curve.h:70
Curve()
Definition: Curve.h:44