cheshirekow  v0.1.0
LRL.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 Josh Bialkowski (jbialk@mit.edu)
3  *
4  * This file is part of mpblocks.
5  *
6  * mpblocks is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * mpblocks is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with mpblocks. If not, see <http://www.gnu.org/licenses/>.
18  */
26 #ifndef MPBLOCKS_DUBINS_CURVES_EIGEN_HYPER_TWO_THETA_Y_LRL_H_
27 #define MPBLOCKS_DUBINS_CURVES_EIGEN_HYPER_TWO_THETA_Y_LRL_H_
28 
29 namespace mpblocks {
30 namespace dubins {
31 namespace curves_eigen {
32 namespace hyper {
33 namespace two_theta_y {
34 
36 template <int ySpec, int tSpec, typename Format_t>
37 struct Solver<ySpec, tSpec, LRLa, Format_t> {
38  typedef Eigen::Matrix<Format_t, 3, 1> Vector3d_t;
39  typedef Eigen::Matrix<Format_t, 2, 1> Vector2d_t;
42 
43  static const unsigned int SPEC = SpecPack<OFF, ySpec, tSpec>::Result;
44 
45  static Result_t solve(const Vector3d_t& q0, const Hyper_t& h,
46  const Format_t r) {
47  Result_t out[5];
48  for (int i = 0; i < 5; i++) {
49  out[i].id = LRLa;
50  }
51 
52  // calculate the center of the left turn
53  const Vector2d_t c0 = leftCenter(q0, r);
54 
55  // the goal point (we'll vary the x coordinate)
56  Vector3d_t q1;
57  q1 << q0[0], get_constraint<ySpec, 1>(h), get_constraint<tSpec, 2>(h);
58 
59  // the center of the goal point (again, we'll vary the x coordinate)
60  Vector2d_t c2 = leftCenter(q1, r);
61 
62  // the arc location of the query and goal points with respect to
63  // their circle
64  const Format_t alpha0 = leftAngleOf(q0);
65  const Format_t alpha1 = leftAngleOf(q1);
66 
67  // vertical distance between centers
68  Format_t dy = c2[1] - c0[1];
69  Format_t eps = static_cast<Format_t>(1e-6);
70 
71  // if the two centers are more than 4r away from each other than
72  // there is no feasible LRL trajectory
73  if (std::abs(dy) + eps > 4 * r) {
74  return out[0];
75  }
76 
77  // the solution that minimizes the center arc requires that the
78  // two circles be x-aligned
79  c2[0] = c0[0];
80 
81  // this is the location of the second circle with respect to the
82  // first two
83  Format_t dx = std::sqrt(4 * r * r - (dy / 2) * (dy / 2));
84  Vector2d_t c1;
85  c1[1] = (c2[1] + c0[1]) / 2;
86  if (c2[1] > c0[1])
87  c1[0] = c0[0] + dx;
88  else
89  c1[0] = c0[0] - dx;
90 
91  Vector2d_t dc01 = c1 - c0;
92  Vector2d_t dc12 = c2 - c1;
93 
94  Format_t beta0 = alpha0;
95  Format_t beta1 = clampRadian(std::atan2(dc01[1], dc01[0]));
96  Format_t beta2 = clampRadian(beta1 + M_PI);
97  Format_t beta3 = clampRadian(std::atan2(dc12[1], dc12[0]));
98  Format_t beta4 = clampRadian(beta3 + M_PI);
99  Format_t beta5 = alpha1;
100  Format_t arc0 = ccwArc(beta0, beta1);
101  Format_t arc1 = cwArc(beta2, beta3);
102  Format_t arc2 = ccwArc(beta4, beta5);
103  Format_t dist = r * (arc0 + arc1 + arc2);
104 
105  out[0] = Vector3d_t(arc0, arc1, arc2);
106  int iBest = 0;
107 
108  Format_t dist_i = 0;
109 
110  // for the solution that minimizes L0, this requires an immediate
111  // R (i.e. arc0 is 0), so find c1
112  c1 = rightCenter(q0, r);
113 
114  // in order for a solution of this type to exist c1 must be within
115  // 2r vertical of c2
116  dy = c2[1] - c1[1];
117  if (std::abs(dy) + eps < 2 * r) {
118  // there are two solutions +dx and -dx
119  dx = std::sqrt(4 * r * r - dy * dy);
120 
121  // for the +dx solution
122  c2[0] = c1[0] + dx;
123 
124  dc01 = c1 - c0;
125  dc12 = c2 - c1;
126  beta0 = alpha0;
127  beta1 = clampRadian(std::atan2(dc01[1], dc01[0]));
128  beta2 = clampRadian(beta1 + M_PI);
129  beta3 = clampRadian(std::atan2(dc12[1], dc12[0]));
130  beta4 = clampRadian(beta3 + M_PI);
131  beta5 = alpha1;
132  arc0 = 0;
133  arc1 = cwArc(beta2, beta3);
134  arc2 = ccwArc(beta4, beta5);
135  dist_i = r * (arc0 + arc1 + arc2);
136 
137  out[1] = Vector3d_t(arc0, arc1, arc2);
138  if (dist_i < dist) {
139  iBest = 1;
140  dist = dist_i;
141  }
142 
143  // for the -dx solution
144  c2[0] = c1[0] - dx;
145 
146  dc01 = c1 - c0;
147  dc12 = c2 - c1;
148  beta0 = alpha0;
149  beta1 = clampRadian(std::atan2(dc01[1], dc01[0]));
150  beta2 = clampRadian(beta1 + M_PI);
151  beta3 = clampRadian(std::atan2(dc12[1], dc12[0]));
152  beta4 = clampRadian(beta3 + M_PI);
153  beta5 = alpha1;
154  arc0 = 0;
155  arc1 = cwArc(beta2, beta3);
156  arc2 = ccwArc(beta4, beta5);
157  dist_i = r * (arc0 + arc1 + arc2);
158 
159  out[2] = Vector3d_t(arc0, arc1, arc2);
160  if (dist_i < dist) {
161  iBest = 2;
162  dist = dist_i;
163  }
164  }
165 
166  // for the solution that minimizes L1, this requires no arc2
167  c1 = rightCenter(q1, r);
168  c2 = leftCenter(q1, r);
169  dy = c1[1] - c0[1];
170  if (std::abs(dy) + eps < 2 * r) {
171  // there are two solutions +dx and -dx
172  dx = std::sqrt(4 * r * r - dy * dy);
173 
174  // for the +dx solution, first we compute how much c0[0] + dx would
175  // change c1[0], so we can apply the same translation to
176  // c2
177  Format_t dxx = (c0[0] + dx) - c1[0];
178  c1[0] += dxx;
179  c2[0] += dxx;
180 
181  dc01 = c1 - c0;
182  dc12 = c2 - c1;
183  beta0 = alpha0;
184  beta1 = clampRadian(std::atan2(dc01[1], dc01[0]));
185  beta2 = clampRadian(beta1 + M_PI);
186  beta3 = clampRadian(std::atan2(dc12[1], dc12[0]));
187  beta4 = clampRadian(beta3 + M_PI);
188  arc0 = ccwArc(beta0, beta1);
189  arc1 = cwArc(beta2, beta3);
190  arc2 = 0;
191  dist_i = r * (arc0 + arc1 + arc2);
192 
193  out[3] = Vector3d_t(arc0, arc1, arc2);
194  if (dist_i < dist) {
195  iBest = 3;
196  dist = dist_i;
197  }
198 
199  dxx = -2 * dx;
200  c1[0] += dxx;
201  c2[0] += dxx;
202 
203  dc01 = c1 - c0;
204  dc12 = c2 - c1;
205  beta0 = alpha0;
206  beta1 = clampRadian(std::atan2(dc01[1], dc01[0]));
207  beta2 = clampRadian(beta1 + M_PI);
208  beta3 = clampRadian(std::atan2(dc12[1], dc12[0]));
209  beta4 = clampRadian(beta3 + M_PI);
210  arc0 = ccwArc(beta0, beta1);
211  arc1 = cwArc(beta2, beta3);
212  arc2 = 0;
213  dist_i = r * (arc0 + arc1 + arc2);
214 
215  out[4] = Vector3d_t(arc0, arc1, arc2);
216  if (dist_i < dist) {
217  iBest = 4;
218  dist = dist_i;
219  }
220  }
221 
222  return out[iBest];
223  };
224 };
225 
226 } // namespace two_theta_y
227 } // namespace hyper
228 } // namespace curves_eigen
229 } // namespace dubins
230 } // namespace mpblocks
231 
232 #endif // MPBLOCKS_DUBINS_CURVES_EIGEN_HYPER_TWO_THETA_Y_LRL_H_
__host__ __device__ Format_t cwArc(Format_t a, Format_t b)
returns the clockwise (right) distance from a to b
Definition: funcs.hpp:72
Scalar leftAngleOf(const Scalar q_theta)
return the angle of the vector from the center of the counter clockwise (left) circle coincident to q...
Definition: funcs.hpp:87
__host__ __device__ Format_t ccwArc(Format_t a, Format_t b)
returns the counter clockwise (left) distance from a to b
Definition: funcs.hpp:51
interface for variants of solvers, default template is never instantiated
Definition: Solver.hpp:41
int id
identifies the type of path
Definition: path.h:45
A hyper-rectangle in dubins space: A rectangular prism in R^3.
Definition: hyper_rect.h:44
__host__ __device__ Format_t clampRadian(Format_t a)
wraps the input onto [-pi,pi]
Definition: funcs.hpp:37
Eigen::Matrix< Scalar, 2, 1 > rightCenter(const Eigen::Matrix< Scalar, 3, 1 > &q, Scalar r)
return the center of a clockwise (right) circle coincident to q with radius r
Definition: funcs.hpp:76
Encodes a dubins path primitive, which is three connected arc segments.
Definition: path.h:42
static Result_t solve(const Vector3d_t &q0, const Hyper_t &h, const Format_t r)
Definition: LRL.hpp:45
Eigen::Matrix< Scalar, 2, 1 > leftCenter(const Eigen::Matrix< Scalar, 3, 1 > &q, Scalar r)
return the center of a counter clockwise (left) circle coincident to q with radius r ...
Definition: funcs.hpp:54