path2d.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018, the neonavigation authors
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  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of the copyright holder nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #ifndef TRAJECTORY_TRACKER_PATH2D_H
31 #define TRAJECTORY_TRACKER_PATH2D_H
32 
33 #include <vector>
34 #include <limits>
35 
36 #include <Eigen/Core>
37 #include <Eigen/Geometry>
38 
39 #include <geometry_msgs/Pose.h>
40 #include <tf2/utils.h>
41 
44 
45 namespace trajectory_tracker
46 {
47 class Pose2D
48 {
49 public:
50  Eigen::Vector2d pos_;
51  float yaw_;
52  float velocity_;
53 
54  inline Pose2D()
55  : pos_(0, 0)
56  , yaw_(0)
57  , velocity_(0)
58  {
59  }
60  inline Pose2D(const Eigen::Vector2d& p, float y, float velocity)
61  : pos_(p)
62  , yaw_(y)
63  , velocity_(velocity)
64  {
65  }
66  inline explicit Pose2D(const geometry_msgs::Pose& pose, float velocity)
67  : pos_(Eigen::Vector2d(pose.position.x, pose.position.y))
68  , yaw_(tf2::getYaw(pose.orientation))
69  , velocity_(velocity)
70  {
71  }
72  inline void rotate(const float ang)
73  {
74  const float org_x = pos_.x();
75  const float org_y = pos_.y();
76  const float cos_v = std::cos(ang);
77  const float sin_v = std::sin(ang);
78 
79  pos_.x() = cos_v * org_x - sin_v * org_y;
80  pos_.y() = sin_v * org_x + cos_v * org_y;
81  yaw_ += ang;
82  while (yaw_ < 0)
83  yaw_ += 2 * M_PI;
84  while (yaw_ > 2 * M_PI)
85  yaw_ -= 2 * M_PI;
86  }
87 };
88 class Path2D : public std::vector<Pose2D>
89 {
90 private:
91  using Super = std::vector<Pose2D>;
92 
93 public:
94  using Iterator = std::vector<Pose2D>::iterator;
95  using ConstIterator = std::vector<Pose2D>::const_iterator;
96 
97  inline float length() const
98  {
99  double l = 0;
100  for (size_t i = 1; i < size(); i++)
101  l += ((*this)[i - 1].pos_ - (*this)[i].pos_).norm();
102  return l;
103  }
105  const ConstIterator& begin,
106  const ConstIterator& end,
107  const bool allow_backward_motion) const
108  {
109  float sign_vel_prev = 0;
110  ConstIterator it_prev = begin;
111  for (ConstIterator it = begin + 1; it < end; ++it)
112  {
113  // stop reading forward if the path is switching back or in-place turning
114  if (it->pos_ == it_prev->pos_)
115  return it;
116 
117  const Eigen::Vector2d inc = it->pos_ - it_prev->pos_;
118 
119  const float angle = atan2(inc[1], inc[0]);
120  const float angle_pose = allow_backward_motion ? it->yaw_ : angle;
121  const float sign_vel_req = std::cos(angle) * std::cos(angle_pose) + std::sin(angle) * std::sin(angle_pose);
122  if (sign_vel_prev * sign_vel_req < 0)
123  return it;
124  sign_vel_prev = sign_vel_req;
125  it_prev = it;
126  }
127  return end;
128  }
130  const ConstIterator& begin,
131  const ConstIterator& end,
132  const Eigen::Vector2d& target,
133  const float max_search_range = 0,
134  const float epsilon = 1e-6) const
135  {
136  if (begin == end)
137  return end;
138 
139  float distance_path_search = 0;
140  ConstIterator it_nearest = begin;
141  float min_dist = (begin->pos_ - target).norm() + epsilon;
142 
143  ConstIterator it_prev = begin;
144  for (ConstIterator it = begin + 1; it < end; ++it)
145  {
146  const Eigen::Vector2d inc = it->pos_ - it_prev->pos_;
147  distance_path_search += inc.norm();
148  if (max_search_range > 0 && distance_path_search > max_search_range)
149  break;
150 
151  const float d =
152  trajectory_tracker::lineStripDistanceSigned(it_prev->pos_, it->pos_, target);
153 
154  // Use earlier point if the robot is same distance from two line strip
155  // to avoid chattering.
156  const float d_compare = (d > 0) ? d : (-d - epsilon);
157  const float d_abs = std::abs(d);
158 
159  // If it is the last point, select it as priority
160  // to calculate correct remained distance.
161  if (d_compare <= min_dist || (it + 1 == end && d_abs <= min_dist + epsilon))
162  {
163  min_dist = d_abs;
164  it_nearest = it;
165  }
166  it_prev = it;
167  }
168  return it_nearest;
169  }
170  inline double remainedDistance(
171  const ConstIterator& begin,
172  const ConstIterator& nearest,
173  const ConstIterator& end,
174  const Eigen::Vector2d& target_on_line) const
175  {
176  double remain = (nearest->pos_ - target_on_line).norm();
177  if (nearest + 1 >= end)
178  {
179  const ConstIterator last = end - 1;
180  const ConstIterator last_pre = end - 2;
181  if (last_pre < begin || last < begin)
182  {
183  // no enough points: orientation control mode
184  return 0;
185  }
186  const Eigen::Vector2d vec_path = last->pos_ - last_pre->pos_;
187  const Eigen::Vector2d vec_remain = last->pos_ - target_on_line;
188  if (vec_path.dot(vec_remain) >= 0)
189  {
190  // ongoing
191  return remain;
192  }
193  // overshoot
194  return -remain;
195  }
196  ConstIterator it_prev = nearest;
197  for (ConstIterator it = nearest + 1; it < end; ++it)
198  {
199  remain += (it_prev->pos_ - it->pos_).norm();
200  it_prev = it;
201  }
202  return remain;
203  }
204  inline float getCurvature(
205  const ConstIterator& begin,
206  const ConstIterator& end,
207  const Eigen::Vector2d& target_on_line,
208  const float max_search_range) const
209  {
210  if (end - begin <= 1)
211  {
212  return 0;
213  }
214  else if (end - begin == 2)
215  {
216  // When only two poses are remained, the logic same as planner_cspace::planner_3d::RotationCache is used.
217  ConstIterator it_prev = begin;
218  ConstIterator it = begin + 1;
219  Pose2D rel(it->pos_ - it_prev->pos_, it->yaw_, 0.0f);
220  rel.rotate(-it_prev->yaw_);
221  const float sin_v = std::sin(rel.yaw_);
222  static const float EPS = 1.0e-6f;
223  if (std::abs(sin_v) < EPS)
224  {
225  return 0;
226  }
227  const float cos_v = std::cos(rel.yaw_);
228  const float r1 = rel.pos_.y() + rel.pos_.x() * cos_v / sin_v;
229  const float r2 = std::copysign(
230  std::sqrt(std::pow(rel.pos_.x(), 2) + std::pow(rel.pos_.x() * cos_v / sin_v, 2)),
231  rel.pos_.x() * sin_v);
232  return 1.0f / ((r1 + r2) / 2);
233  }
234  const float max_search_range_sq = max_search_range * max_search_range;
236  ConstIterator it_prev2 = begin;
237  ConstIterator it_prev1 = begin + 1;
238  for (ConstIterator it = begin + 2; it < end; ++it)
239  {
240  curv += trajectory_tracker::curv3p(it_prev2->pos_, it_prev1->pos_, it->pos_);
241  if ((it->pos_ - target_on_line).squaredNorm() > max_search_range_sq)
242  break;
243  it_prev2 = it_prev1;
244  it_prev1 = it;
245  }
246  return curv;
247  }
248 };
249 } // namespace trajectory_tracker
250 
251 #endif // TRAJECTORY_TRACKER_PATH2D_H
d
double remainedDistance(const ConstIterator &begin, const ConstIterator &nearest, const ConstIterator &end, const Eigen::Vector2d &target_on_line) const
Definition: path2d.h:170
f
std::vector< Pose2D >::const_iterator ConstIterator
Definition: path2d.h:95
ConstIterator findLocalGoal(const ConstIterator &begin, const ConstIterator &end, const bool allow_backward_motion) const
Definition: path2d.h:104
ConstIterator findNearest(const ConstIterator &begin, const ConstIterator &end, const Eigen::Vector2d &target, const float max_search_range=0, const float epsilon=1e-6) const
Definition: path2d.h:129
TFSIMD_FORCE_INLINE const tfScalar & y() const
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
float getCurvature(const ConstIterator &begin, const ConstIterator &end, const Eigen::Vector2d &target_on_line, const float max_search_range) const
Definition: path2d.h:204
float lineStripDistanceSigned(const Eigen::Vector2d &a, const Eigen::Vector2d &b, const Eigen::Vector2d &c)
Definition: eigen_line.h:69
std::vector< Pose2D > Super
Definition: path2d.h:91
std::vector< Pose2D >::iterator Iterator
Definition: path2d.h:94
double epsilon
float curv3p(const Eigen::Vector2d &a, const Eigen::Vector2d &b, const Eigen::Vector2d &c)
Definition: eigen_line.h:40
TFSIMD_FORCE_INLINE const tfScalar & x() const
double getYaw(const tf2::Quaternion &q)
float length() const
Definition: path2d.h:97
INLINE Rall1d< T, V, S > atan2(const Rall1d< T, V, S > &y, const Rall1d< T, V, S > &x)
Pose2D(const Eigen::Vector2d &p, float y, float velocity)
Definition: path2d.h:60
Eigen::Vector2d pos_
Definition: path2d.h:50
Pose2D(const geometry_msgs::Pose &pose, float velocity)
Definition: path2d.h:66
void rotate(const float ang)
Definition: path2d.h:72


trajectory_tracker
Author(s): Atsushi Watanabe
autogenerated on Wed May 12 2021 02:20:40