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