cheshirekow  v0.1.0
SolutionLRLa.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_A_HPP_
28 #define MPBLOCKS_DUBINS_CURVES_CUDA2_SOLUTION_LRL_A_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<LRLa,Format_t>
39 {
46 
47 
50  const Vector3d_t& q0,
51  const Vector3d_t& q1,
52  const Format_t r );
53 
54  __host__ __device__ static Result<Format_t> solve_debug(
55  const Vector3d_t& q0,
56  const Vector3d_t& q1,
57  const Format_t r,
58  DebugResult& out );
59 };
60 
61 
62 template <typename Format_t>
64  const Vector3d_t& q0,
65  const Vector3d_t& q1,
66  const Format_t r )
67 {
68  using namespace std;
69  using namespace cuda::linalg2;
70 
71  const Format_t _PI = static_cast<Format_t>(M_PI);
72  const Format_t _2 = static_cast<Format_t>(2);
73  const Format_t _4 = static_cast<Format_t>(4);
74 
75  Vector2d_t x,v,c[3];
76 
77  // calculate the center of the circle to which q1 is tangent
78  x = view<0,2>( q0 );
79  v << -Dispatch::sin( get<2>(q0) ),
80  Dispatch::cos( get<2>(q0) );
81  c[0] = x + mktmp(r*v);
82 
83  // calculate the center of the circle to which q2 is tangent
84  x = view<0,2>(q1);
85  v << -Dispatch::sin( get<2>(q1) ),
86  Dispatch::cos( get<2>(q1) );
87  c[1] = x + mktmp(r*v);
88 
89  // the distance between the centers of these two circles
90  Format_t d = norm(c[0]-c[1]);
91 
92  // if the distance is too large, then this primitive is not the solution,
93  // and we can bail here
94  if( d > _4*r )
95  return Result_t();
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[1]-c[0]) );
109  Vector2d_t B = mktmp(R*A) * (_2*r);
110  c[2] = c[0] + 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( get<2>(q1) - (_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 
138 #ifdef __CUDACC__
139  #pragma unroll
140 #endif
141  for(int i=0; i < 3; i++)
142  dist += l[i];
143 
144  return Result_t(r*dist);
145 }
146 
147 
148 
149 
150 
151 
152 
153 
154 
155 template <typename Format_t>
157  const Vector3d_t& q0,
158  const Vector3d_t& q1,
159  const Format_t r,
160  DebugResult& out )
161 {
162  using namespace std;
163  using namespace cuda::linalg2;
164 
165  const Format_t _PI = static_cast<Format_t>(M_PI);
166  const Format_t _2 = static_cast<Format_t>(2);
167  const Format_t _4 = static_cast<Format_t>(4);
168 
169  Vector2d_t x,v,c[3];
170 
171  // calculate the center of the circle to which q1 is tangent
172  x = view<0,2>( q0 );
173  v << -Dispatch::sin( get<2>(q0) ),
174  Dispatch::cos( get<2>(q0) );
175  c[0] = x + mktmp(r*v);
176 
177  // calculate the center of the circle to which q2 is tangent
178  x = view<0,2>(q1);
179  v << -Dispatch::sin( get<2>(q1) ),
180  Dispatch::cos( get<2>(q1) );
181  c[1] = x + mktmp(r*v);
182 
183  // the distance between the centers of these two circles
184  Format_t d = norm(c[0]-c[1]);
185 
186  // if the distance is too large, then this primitive is not the solution,
187  // and we can bail here
188  if( d > _4*r )
189  return Result_t();
190 
191  // the base angle of the isosceles triangle whose vertices are the centers
192  // of the the three circles, note acos returns [0,pi]
193  Format_t a = -Dispatch::acos( d / (_4*r) );
194 
195  // create a clockwise rotation of magnitude alpha
196  Rotation2d_t R( Dispatch::sin(a), Dispatch::cos(a) );
197 
198  // we find the third vertex of this triangle by taking the vector between
199  // the two circle centers, normalizing it, and rotating it by alpha, and
200  // scaling it to magnitude 2r, then it points from the center of
201  // one the circle tangent to q1 to the third vertex
202  Vector2d_t A = normalize( mktmp(c[1]-c[0]) );
203  Vector2d_t B = mktmp(R*A) * (_2*r);
204  c[2] = c[0] + B;
205 
206  // calculate the arc distance we travel on the first circle
207  Vector2d_t dc;
208  Format_t b,l[3];
209 
210  dc = c[2] - c[0]; //< vector between centers of circles
211  b = Dispatch::atan2( get<1>(dc), get<0>(dc) );
212  //< angle of that vector
213  d = clampRadian( get<2>(q0) - (_PI/_2) );
214  //< angle of vector from center to q1
215  l[0] = ccwArc(d,b); //< ccwise distance
216 
217 
218  // calculate the arc distance we travel on the second circle
219  dc = c[2] - c[1]; //< vector between centers of circles
220  b = Dispatch::atan2( get<1>(dc), get<0>(dc) );
221  //< angle of that vector
222  d = clampRadian( get<2>(q1) - (_PI/_2) );
223  //< angle of vector from center to q1
224  l[1] = ccwArc(b,d); //< ccwise distance
225 
226  // calculate the arc distance we travel on the third circle
227  l[2] = _PI + _2*a;
228 
229  // sum the resulting segments
230  Format_t dist = 0;
231 #ifdef __CUDACC__
232  #pragma unroll
233 #endif
234  for(int i=0; i < 3; i++)
235  dist += l[i];
236 
237 #ifdef __CUDACC__
238  #pragma unroll
239 #endif
240  for(int i=0; i < 3; i++)
241  {
242  out.c[i] = c[i];
243  out.l[i] = l[i];
244  }
245 
246  return Result_t(r*dist);
247 }
248 
249 
250 
251 
252 
253 
254 
255 
256 
257 
258 
259 
260 
261 
262 
263 
264 
265 
266 
267 } // curves
268 } // dubins
269 } // mpblocks
270 
271 
272 
273 #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