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_X_LRL_H_
27 #define MPBLOCKS_DUBINS_CURVES_EIGEN_HYPER_TWO_THETA_X_LRL_H_
28 
29 namespace mpblocks {
30 namespace dubins {
31 namespace curves_eigen {
32 namespace hyper {
33 namespace two_theta_x {
34 
36 template <int xSpec, int tSpec, typename Format_t>
37 struct Solver<xSpec, 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<xSpec, OFF, 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 y coordinate)
56  Vector3d_t q1;
57  q1 << get_constraint<xSpec, 0>(h), q0[0], get_constraint<tSpec, 2>(h);
58 
59  // the center of the goal point (again, we'll vary the y 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 dx = c2[0] - c0[0];
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(dx) + eps > 4 * r) return out[0];
74 
75  // the solution that minimizes the center arc requires that the
76  // two circles be y-aligned
77  c2[1] = c0[1];
78 
79  // this is the location of the second circle with respect to the
80  // first two
81  Format_t dy = std::sqrt(4 * r * r - (dx / 2) * (dx / 2));
82  Vector2d_t c1;
83  c1[0] = (c2[0] + c0[0]) / 2;
84  if (c2[0] > c0[0])
85  c1[1] = c0[1] - dy;
86  else
87  c1[1] = c0[1] + dy;
88 
89  Vector2d_t dc01 = c1 - c0;
90  Vector2d_t dc12 = c2 - c1;
91  Format_t beta0 = alpha0;
92  Format_t beta1 = clampRadian(std::atan2(dc01[1], dc01[0]));
93  Format_t beta2 = clampRadian(beta1 + M_PI);
94  Format_t beta3 = clampRadian(std::atan2(dc12[1], dc12[0]));
95  Format_t beta4 = clampRadian(beta3 + M_PI);
96  Format_t beta5 = alpha1;
97  Format_t arc0 = ccwArc(beta0, beta1);
98  Format_t arc1 = cwArc(beta2, beta3);
99  Format_t arc2 = ccwArc(beta4, beta5);
100  Format_t dist = r * (arc0 + arc1 + arc2);
101 
102  out[0] = Vector3d_t(arc0, arc1, arc2);
103  int iBest = 0;
104  Format_t dist_i = 0;
105 
106  // for the solution that minimizes L0, this requires an immediate
107  // R (i.e. arc0 is 0), so find c1
108  c1 = rightCenter(q0, r);
109 
110  // in order for a solution of this type to exist c1 must be within
111  // 2r vertical of c2
112  dx = c2[0] - c1[0];
113  if (std::abs(dx) + eps < 2 * r) {
114  // there are two solutions +dx and -dx
115  dy = std::sqrt(4 * r * r - dx * dx);
116 
117  // for the +dx solution
118  c2[1] = c1[1] + dy;
119 
120  dc01 = c1 - c0;
121  dc12 = c2 - c1;
122  beta0 = alpha0;
123  beta1 = clampRadian(std::atan2(dc01[1], dc01[0]));
124  beta2 = clampRadian(beta1 + M_PI);
125  beta3 = clampRadian(std::atan2(dc12[1], dc12[0]));
126  beta4 = clampRadian(beta3 + M_PI);
127  beta5 = alpha1;
128  arc0 = 0;
129  arc1 = cwArc(beta2, beta3);
130  arc2 = ccwArc(beta4, beta5);
131  dist_i = r * (arc0 + arc1 + arc2);
132 
133  out[1] = Vector3d_t(arc0, arc1, arc2);
134  if (dist_i < dist) {
135  iBest = 1;
136  dist = dist_i;
137  }
138 
139  // for the -dx solution
140  c2[1] = c1[1] - dy;
141 
142  dc01 = c1 - c0;
143  dc12 = c2 - c1;
144  beta0 = alpha0;
145  beta1 = clampRadian(std::atan2(dc01[1], dc01[0]));
146  beta2 = clampRadian(beta1 + M_PI);
147  beta3 = clampRadian(std::atan2(dc12[1], dc12[0]));
148  beta4 = clampRadian(beta3 + M_PI);
149  beta5 = alpha1;
150  arc0 = 0;
151  arc1 = cwArc(beta2, beta3);
152  arc2 = ccwArc(beta4, beta5);
153  dist_i = r * (arc0 + arc1 + arc2);
154 
155  out[2] = Vector3d_t(arc0, arc1, arc2);
156  if (dist_i < dist) {
157  iBest = 2;
158  dist = dist_i;
159  }
160  }
161 
162  // for the solution that minimizes L1, this requires no arc2
163  c1 = rightCenter(q1, r);
164  c2 = leftCenter(q1, r);
165  dx = c1[0] - c0[0];
166  if (std::abs(dx) + eps < 2 * r) {
167  // there are two solutions +dx and -dx
168  dy = std::sqrt(4 * r * r - dx * dx);
169 
170  // for the +dx solution, first we compute how much c0[0] + dx would
171  // change c1[0], so we can apply the same translation to
172  // c2
173  Format_t dyy = (c0[1] + dy) - c1[1];
174  c1[1] += dyy;
175  c2[1] += dyy;
176 
177  dc01 = c1 - c0;
178  dc12 = c2 - c1;
179  beta0 = alpha0;
180  beta1 = clampRadian(std::atan2(dc01[1], dc01[0]));
181  beta2 = clampRadian(beta1 + M_PI);
182  beta3 = clampRadian(std::atan2(dc12[1], dc12[0]));
183  beta4 = clampRadian(beta3 + M_PI);
184  arc0 = ccwArc(beta0, beta1);
185  arc1 = cwArc(beta2, beta3);
186  arc2 = 0;
187  dist_i = r * (arc0 + arc1 + arc2);
188 
189  out[3] = Vector3d_t(arc0, arc1, arc2);
190  if (dist_i < dist) {
191  iBest = 3;
192  dist = dist_i;
193  }
194 
195  dyy = -2 * dy;
196  c1[1] += dyy;
197  c2[1] += dyy;
198 
199  dc01 = c1 - c0;
200  dc12 = c2 - c1;
201  beta0 = alpha0;
202  beta1 = clampRadian(std::atan2(dc01[1], dc01[0]));
203  beta2 = clampRadian(beta1 + M_PI);
204  beta3 = clampRadian(std::atan2(dc12[1], dc12[0]));
205  beta4 = clampRadian(beta3 + M_PI);
206  arc0 = ccwArc(beta0, beta1);
207  arc1 = cwArc(beta2, beta3);
208  arc2 = 0;
209  dist_i = r * (arc0 + arc1 + arc2);
210 
211  out[4] = Vector3d_t(arc0, arc1, arc2);
212  if (dist_i < dist) {
213  iBest = 4;
214  dist = dist_i;
215  }
216  }
217 
218  return out[iBest];
219  };
220 };
221 
222 } // namespace two_theta_x
223 } // namespace hyper
224 } // namespace curves_eigen
225 } // namespace dubins
226 } // namespace mpblocks
227 
228 #endif // MPBLOCKS_DUBINS_CURVES_EIGEN_HYPER_TWO_THETA_X_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
static Result_t solve(const Vector3d_t &q0, const Hyper_t &h, const Format_t r)
Definition: LRL.hpp:45
__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:37
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
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