cheshirekow  v0.1.0
SolutionLRLb.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  */
27 #ifndef MPBLOCKS_DUBINS_CURVES_CUDA2_SOLUTION_LRL_B_HPP_
28 #define MPBLOCKS_DUBINS_CURVES_CUDA2_SOLUTION_LRL_B_HPP_
29 
30 #include <limits>
31 
32 namespace mpblocks {
33 namespace dubins {
34 namespace curves_cuda {
35 
37 template <typename Format_t>
38 struct Solver<LRLb,Format_t>
39 {
46 
49  const Vector3d_t& q0,
50  const Vector3d_t& q1,
51  const Format_t r );
52 
53  __host__ __device__ static Result<Format_t> solve_debug(
54  const Vector3d_t& q0,
55  const Vector3d_t& q1,
56  const Format_t r,
57  DebugResult& out );
58 };
59 
60 
61 template <typename Format_t>
63  const Vector3d_t& q0,
64  const Vector3d_t& q1,
65  const Format_t r )
66 {
67  using namespace std;
68  using namespace cuda::linalg2;
69 
70  const Format_t _PI = static_cast<Format_t>(M_PI);
71  const Format_t _2 = static_cast<Format_t>(2);
72  const Format_t _4 = static_cast<Format_t>(4);
73 
74  Vector2d_t x,v,c[3];
75 
76  // calculate the center of the circle to which q1 is tangent
77  x = view<0,2>( q0 );
78  v << -Dispatch::sin( get<2>(q0) ),
79  Dispatch::cos( get<2>(q0) );
80  c[0] = x + mktmp(r*v);
81 
82  // calculate the center of the circle to which q2 is tangent
83  x = view<0,2>( q1 );
84  v << -Dispatch::sin( get<2>(q1) ),
85  Dispatch::cos( get<2>(q1) );
86  c[1] = x + mktmp(r*v);
87 
88  // the distance between the centers of these two circles
89  Format_t d = norm(c[0]-c[1]);
90 
91  // if the distance is too large, then this primitive is not the solution,
92  // and we can bail here
93  if( d > _4*r )
94  return Result_t();
95 
96 
97  // the base angle of the isosceles triangle whose vertices are the centers
98  // of the the three circles, note acos returns [0,pi]
99  Format_t a = -Dispatch::acos( d / (4*r) );
100 
101  // create a clockwise rotation of magnitude alpha
102  Rotation2d_t R( Dispatch::sin(a), Dispatch::cos(a) );
103 
104  // we find the third vertex of this triangle by taking the vector between
105  // the two circle centers, normalizing it, and rotating it by alpha, and
106  // scaling it to magnitude 2r, then it points from the center of
107  // one the circle tangent to q1 to the third vertex
108  Vector2d_t A = normalize( mktmp(c[0]-c[1]) );
109  Vector2d_t B = mktmp(R*A) * (_2*r);
110  c[2] = c[1] + B;
111 
112  // calculate the arc distance we travel on the first circle
113  Vector2d_t dc;
114  Format_t b,l[3];
115 
116  dc = c[2] - c[0]; //< vector between centers of circles
117  b = Dispatch::atan2( get<1>(dc), get<0>(dc) );
118  //< angle of that vector
119  d = clampRadian( get<2>(q0) - (_PI/_2) );
120  //< angle of vector from center to q1
121  l[0] = ccwArc(d,b); //< ccwise distance
122 
123 
124  // calculate the arc distance we travel on the second circle
125  dc = c[2] - c[1]; //< vector between centers of circles
126  b = Dispatch::atan2( get<1>(dc), get<0>(dc) );
127  //< angle of that vector
128  d = clampRadian(q1[2] - (_PI/_2) );
129  //< angle of vector from center to q1
130  l[1] = ccwArc(b,d); //< ccwise distance
131 
132  // calculate the arc distance we travel on the third circle
133  l[2] = _PI - _2*a;
134 
135  // sum the resulting segments
136  Format_t dist = 0;
137 #ifdef __CUDACC__
138  #pragma unroll
139 #endif
140  for(int i=0; i < 3; i++)
141  dist += l[i];
142 
143  return Result_t(r*dist);
144 }
145 
146 
147 
148 
149 
150 
151 
152 
153 
154 
155 
156 
157 
158 
159 
160 template <typename Format_t>
162  const Vector3d_t& q0,
163  const Vector3d_t& q1,
164  const Format_t r,
165  DebugResult& out )
166 {
167  using namespace std;
168  using namespace cuda::linalg2;
169 
170  const Format_t _PI = static_cast<Format_t>(M_PI);
171  const Format_t _2 = static_cast<Format_t>(2);
172  const Format_t _4 = static_cast<Format_t>(4);
173 
174  Vector2d_t x,v,c[3];
175 
176  // calculate the center of the circle to which q1 is tangent
177  x = view<0,2>( q0 );
178  v << -Dispatch::sin( get<2>(q0) ),
179  Dispatch::cos( get<2>(q0) );
180  c[0] = x + mktmp(r*v);
181 
182  // calculate the center of the circle to which q2 is tangent
183  x = view<0,2>( q1 );
184  v << -Dispatch::sin( get<2>(q1) ),
185  Dispatch::cos( get<2>(q1) );
186  c[1] = x + mktmp(r*v);
187 
188  // the distance between the centers of these two circles
189  Format_t d = norm(c[0]-c[1]);
190 
191  // if the distance is too large, then this primitive is not the solution,
192  // and we can bail here
193  if( d > _4*r )
194  return Result_t();
195 
196 
197  // the base angle of the isosceles triangle whose vertices are the centers
198  // of the the three circles, note acos returns [0,pi]
199  Format_t a = -Dispatch::acos( d / (4*r) );
200 
201  // create a clockwise rotation of magnitude alpha
202  Rotation2d_t R( Dispatch::sin(a), Dispatch::cos(a) );
203 
204  // we find the third vertex of this triangle by taking the vector between
205  // the two circle centers, normalizing it, and rotating it by alpha, and
206  // scaling it to magnitude 2r, then it points from the center of
207  // one the circle tangent to q1 to the third vertex
208  Vector2d_t A = normalize( mktmp(c[0]-c[1]) );
209  Vector2d_t B = mktmp(R*A) * (_2*r);
210  c[2] = c[1] + B;
211 
212  // calculate the arc distance we travel on the first circle
213  Vector2d_t dc;
214  Format_t b,l[3];
215 
216  dc = c[2] - c[0]; //< vector between centers of circles
217  b = Dispatch::atan2( get<1>(dc), get<0>(dc) );
218  //< angle of that vector
219  d = clampRadian( get<2>(q0) - (_PI/_2) );
220  //< angle of vector from center to q1
221  l[0] = ccwArc(d,b); //< ccwise distance
222 
223 
224  // calculate the arc distance we travel on the second circle
225  dc = c[2] - c[1]; //< vector between centers of circles
226  b = Dispatch::atan2( get<1>(dc), get<0>(dc) );
227  //< angle of that vector
228  d = clampRadian(q1[2] - (_PI/_2) );
229  //< angle of vector from center to q1
230  l[1] = ccwArc(b,d); //< ccwise distance
231 
232  // calculate the arc distance we travel on the third circle
233  l[2] = _PI - _2*a;
234 
235  // sum the resulting segments
236  Format_t dist = 0;
237 #ifdef __CUDACC__
238  #pragma unroll
239 #endif
240  for(int i=0; i < 3; i++)
241  dist += l[i];
242 
243 #ifdef __CUDACC__
244  #pragma unroll
245 #endif
246  for(int i=0; i < 3; i++)
247  {
248  out.c[i] = c[i];
249  out.l[i] = l[i];
250  }
251 
252  return Result_t(r*dist);
253 }
254 
255 
256 
257 
258 
259 
260 
261 
262 
263 
264 
265 
266 
267 } // curves
268 } // dubins
269 } // mpblocks
270 
271 
272 #endif // SOLUTIONLRLA_H_
__device__ __host__ Normalize< Scalar, Exp > normalize(RValue< Scalar, Exp > const &A)
Definition: Normalize.h:92
empty struct used to template "variant" of three arc primitives
Definition: types.h:46
result::Result Result_t
Definition: common.h:370
__device__ __host__ Matrix< Scalar, ROWS, COLS > mktmp(RValue< Scalar, ROWS, COLS, Exp > const &M)
forces the creation of a temporary
Definition: mktmp.h:42
__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
empty struct used to template "variant" of three arc primitives
Definition: types.h:43
empty struct used to template "right turn" primitive
Definition: types.h:37
Encapsulates the solution distance along with a feasibility bit for a particular primitive solution...
Definition: result.h:44
__host__ __device__ Format_t clampRadian(Format_t a)
wraps the input onto [-pi,pi]
Definition: funcs.hpp:37
__device__ __host__ Scalar norm(const RValue< Scalar, ROWS, COLS, Exp > &M)
compute the norm
Definition: Norm.h:140
static Result< Format_t > solve(const Vector3d_t &q0, const Vector3d_t &q1, const Format_t r)
basic interface returns only the total distance
#define __device__
Definition: fakecuda.h:34
#define __host__
Definition: fakecuda.h:37
interface for different solutions
Definition: Solution.h:58