cheshirekow  v0.1.0
SolutionRLRb.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_B_HPP_
28 #define MPBLOCKS_DUBINS_CURVES_CUDA2_SOLUTION_RLR_B_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<RLRb,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  Vector2d_t A = normalize( mktmp(c[0]-c[1]) );
110  Vector2d_t B = mktmp(R*A) * (_2*r);
111  c[2] = c[1] + B;
112 
113  // calculate the arc distance we travel on the first circle
114  Vector2d_t dc;
115  Format_t b,l[3];
116 
117  dc = c[2] - c[0]; //< vector between centers of circles
118  b = Dispatch::atan2( get<1>(dc), get<0>(dc) );
119  //< angle of that vector
120  d = clampRadian( get<2>(q0) + (_PI/_2) );
121  //< angle of vector from center to q1
122  l[0] = cwArc(d,b); //< ccwise distance
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] = cwArc(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 template <typename Format_t>
160  const Vector3d_t& q0,
161  const Vector3d_t& q1,
162  const Format_t r,
163  DebugResult& out )
164 {
165  using namespace std;
166  using namespace cuda::linalg2;
167 
168  const Format_t _PI = static_cast<Format_t>(M_PI);
169  const Format_t _2 = static_cast<Format_t>(2);
170  const Format_t _4 = static_cast<Format_t>(4);
171 
172  Vector2d_t x,v,c[3];
173 
174  // calculate the center of the circle to which q1 is tangent
175  x = view<0,2>( q0 );
176  v << Dispatch::sin( get<2>(q0) ),
177  -Dispatch::cos( get<2>(q0) );
178  c[0] = x + mktmp(r*v);
179 
180  // calculate the center of the circle to which q2 is tangent
181  x = view<0,2>( q1 );
182  v << Dispatch::sin( get<2>(q1) ),
183  -Dispatch::cos( get<2>(q1) );
184  c[1] = x + mktmp(r*v);
185 
186  // the distance between the centers of these two circles
187  Format_t d = norm(c[0]-c[1]);
188 
189  // if the distance is too large, then this primitive is not the solution,
190  // and we can bail here
191  if( d > _4*r )
192  return Result_t();
193 
194  // the base angle of the isosceles triangle whose vertices are the centers
195  // of the the three circles, note acos returns [0,pi]
196  Format_t a = -Dispatch::acos( d / (_4*r) );
197 
198  // create a clockwise rotation of magnitude alpha
199  Rotation2d_t R( Dispatch::sin(a), Dispatch::cos(a) );
200 
201  // we find the third vertex of this triangle by taking the vector between
202  // the two circle centers, normalizing it, and rotating it by alpha, and
203  // scaling it to magnitude 2r, then it points from the center of
204  // one the circle tangent to q1 to the third vertex
205  Vector2d_t A = normalize( mktmp(c[0]-c[1]) );
206  Vector2d_t B = mktmp(R*A) * (_2*r);
207  c[2] = c[1] + B;
208 
209  // calculate the arc distance we travel on the first circle
210  Vector2d_t dc;
211  Format_t b,l[3];
212 
213  dc = c[2] - c[0]; //< vector between centers of circles
214  b = Dispatch::atan2( get<1>(dc), get<0>(dc) );
215  //< angle of that vector
216  d = clampRadian( get<2>(q0) + (_PI/_2) );
217  //< angle of vector from center to q1
218  l[0] = cwArc(d,b); //< ccwise distance
219 
220  // calculate the arc distance we travel on the second circle
221  dc = c[2] - c[1]; //< vector between centers of circles
222  b = Dispatch::atan2( get<1>(dc), get<0>(dc) );
223  //< angle of that vector
224  d = clampRadian( get<2>(q1) + (_PI/_2) );
225  //< angle of vector from center to q1
226  l[1] = cwArc(b,d); //< ccwise distance
227 
228  // calculate the arc distance we travel on the third circle
229  l[2] = _PI + _2*a;
230 
231  // sum the resulting segments
232  Format_t dist = 0;
233 #ifdef __CUDACC__
234  #pragma unroll
235 #endif
236  for(int i=0; i < 3; i++)
237  dist += l[i];
238 
239 #ifdef __CUDACC__
240  #pragma unroll
241 #endif
242  for(int i=0; i < 3; i++)
243  {
244  out.c[i] = c[i];
245  out.l[i] = l[i];
246  }
247 
248  return Result_t( r*dist );
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 #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