ccpmpm_dubins_state_space.cpp
Go to the documentation of this file.
1 /*********************************************************************
2 * Copyright (c) 2017 - for information on the respective copyright
3 * owner see the NOTICE file and/or the repository
4 *
5 * https://github.com/hbanzhaf/steering_functions.git
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
16 * implied. See the License for the specific language governing
17 * permissions and limitations under the License.
18 
19 * This source code is derived from Continuous Curvature (CC) Steer.
20 * Copyright (c) 2016, Thierry Fraichard and Institut national de
21 * recherche en informatique et en automatique (Inria), licensed under
22 * the BSD license, cf. 3rd-party-licenses.txt file in the root
23 * directory of this source tree.
24 **********************************************************************/
25 
26 #include <cmath>
27 #include <limits>
28 
32 
33 using namespace std;
34 
35 namespace steering
36 {
37 
39 {
40 private:
42 
43 public:
45  {
46  parent_ = parent;
47  }
48 
49  double distance = 0.0;
50  double angle = 0.0;
51 
52  // ##### TT ###################################################################
53  bool TT_exists(const HC_CC_Circle &c1, const HC_CC_Circle &c2) const
54  {
55  if (c1.left == c2.left)
56  {
57  return false;
58  }
59  if (c1.forward == c2.forward)
60  {
61  return false;
62  }
63  return fabs(distance - 2 * parent_->radius_) < get_epsilon();
64  }
65 
66  void TT_tangent_circles(const HC_CC_Circle &c1, const HC_CC_Circle &c2, Configuration **q) const
67  {
68  double x = (c1.xc + c2.xc) / 2;
69  double y = (c1.yc + c2.yc) / 2;
70  double angle = atan2(c2.yc - c1.yc, c2.xc - c1.xc);
71  double theta;
72  if (c1.left)
73  {
74  if (c1.forward)
75  {
76  theta = angle + HALF_PI - parent_->mu_;
77  }
78  else
79  {
80  theta = angle + HALF_PI + parent_->mu_;
81  }
82  }
83  else
84  {
85  if (c1.forward)
86  {
87  theta = angle - HALF_PI + parent_->mu_;
88  }
89  else
90  {
91  theta = angle - HALF_PI - parent_->mu_;
92  }
93  }
94  *q = new Configuration(x, y, theta, 0);
95  }
96 
97  double TT_path(const HC_CC_Circle &c1, const HC_CC_Circle &c2, HC_CC_Circle **cstart, HC_CC_Circle **cend,
98  Configuration **q1, Configuration **q2, Configuration **q3) const
99  {
100  TT_tangent_circles(c1, c2, q2);
101  *cstart = new HC_CC_Circle(**q2, c1.left, !c1.forward, true, parent_->hc_cc_circle_param_);
102  *cend = new HC_CC_Circle(**q2, c2.left, !c2.forward, true, parent_->hc_cc_circle_param_);
103  *q1 = new Configuration(c1.start.x, c1.start.y, c1.start.theta, c1.kappa);
104  *q3 = new Configuration(c2.start.x, c2.start.y, c2.start.theta, c2.kappa);
105  return (*cstart)->hc_turn_length(**q1) + (*cend)->hc_turn_length(**q3);
106  }
107 
108  // ##### Dubins families: #####################################################
109 
110  // ##### TST ##################################################################
111  bool TiST_exists(const HC_CC_Circle &c1, const HC_CC_Circle &c2) const
112  {
113  if (c1.left == c2.left)
114  {
115  return false;
116  }
117  if (c1.forward == c2.forward)
118  {
119  return false;
120  }
121  return distance >= 2 * parent_->radius_;
122  }
123 
124  bool TeST_exists(const HC_CC_Circle &c1, const HC_CC_Circle &c2) const
125  {
126  if (c1.left != c2.left)
127  {
128  return false;
129  }
130  if (c1.forward == c2.forward)
131  {
132  return false;
133  }
134  return distance >= 2 * parent_->radius_ * parent_->sin_mu_;
135  }
136 
137  bool TST_exists(const HC_CC_Circle &c1, const HC_CC_Circle &c2) const
138  {
139  return TiST_exists(c1, c2) || TeST_exists(c1, c2);
140  }
141 
143  Configuration **q2) const
144  {
145  double distance = center_distance(c1, c2);
146  double angle = atan2(c2.yc - c1.yc, c2.xc - c1.xc);
147  double alpha = asin(2 * parent_->radius_ * parent_->cos_mu_ / distance);
148  double delta_x = parent_->radius_ * parent_->sin_mu_;
149  double delta_y = parent_->radius_ * parent_->cos_mu_;
150  double x, y, theta;
151  if (c1.left && c1.forward)
152  {
153  theta = angle + alpha;
154  global_frame_change(c1.xc, c1.yc, theta, delta_x, -delta_y, &x, &y);
155  *q1 = new Configuration(x, y, theta, 0);
156  global_frame_change(c2.xc, c2.yc, theta, -delta_x, delta_y, &x, &y);
157  *q2 = new Configuration(x, y, theta, 0);
158  }
159  if (c1.left && !c1.forward)
160  {
161  theta = angle - alpha;
162  global_frame_change(c1.xc, c1.yc, theta, delta_x, delta_y, &x, &y);
163  *q1 = new Configuration(x, y, theta + PI, 0);
164  global_frame_change(c2.xc, c2.yc, theta, -delta_x, -delta_y, &x, &y);
165  *q2 = new Configuration(x, y, theta + PI, 0);
166  }
167  if (!c1.left && c1.forward)
168  {
169  theta = angle - alpha;
170  global_frame_change(c1.xc, c1.yc, theta, delta_x, delta_y, &x, &y);
171  *q1 = new Configuration(x, y, theta, 0);
172  global_frame_change(c2.xc, c2.yc, theta, -delta_x, -delta_y, &x, &y);
173  *q2 = new Configuration(x, y, theta, 0);
174  }
175  if (!c1.left && !c1.forward)
176  {
177  theta = angle + alpha;
178  global_frame_change(c1.xc, c1.yc, theta, delta_x, -delta_y, &x, &y);
179  *q1 = new Configuration(x, y, theta + PI, 0);
180  global_frame_change(c2.xc, c2.yc, theta, -delta_x, delta_y, &x, &y);
181  *q2 = new Configuration(x, y, theta + PI, 0);
182  }
183  }
184 
186  Configuration **q2) const
187  {
188  double delta_x = parent_->radius_ * parent_->sin_mu_;
189  double delta_y = parent_->radius_ * parent_->cos_mu_;
190  double theta = atan2(c2.yc - c1.yc, c2.xc - c1.xc);
191  double x, y;
192  if (c1.left && c1.forward)
193  {
194  global_frame_change(c1.xc, c1.yc, theta, delta_x, -delta_y, &x, &y);
195  *q1 = new Configuration(x, y, theta, 0);
196  global_frame_change(c2.xc, c2.yc, theta, -delta_x, -delta_y, &x, &y);
197  *q2 = new Configuration(x, y, theta, 0);
198  }
199  if (c1.left && !c1.forward)
200  {
201  global_frame_change(c1.xc, c1.yc, theta, delta_x, delta_y, &x, &y);
202  *q1 = new Configuration(x, y, theta + PI, 0);
203  global_frame_change(c2.xc, c2.yc, theta, -delta_x, delta_y, &x, &y);
204  *q2 = new Configuration(x, y, theta + PI, 0);
205  }
206  if (!c1.left && c1.forward)
207  {
208  global_frame_change(c1.xc, c1.yc, theta, delta_x, delta_y, &x, &y);
209  *q1 = new Configuration(x, y, theta, 0);
210  global_frame_change(c2.xc, c2.yc, theta, -delta_x, delta_y, &x, &y);
211  *q2 = new Configuration(x, y, theta, 0);
212  }
213  if (!c1.left && !c1.forward)
214  {
215  global_frame_change(c1.xc, c1.yc, theta, delta_x, -delta_y, &x, &y);
216  *q1 = new Configuration(x, y, theta + PI, 0);
217  global_frame_change(c2.xc, c2.yc, theta, -delta_x, -delta_y, &x, &y);
218  *q2 = new Configuration(x, y, theta + PI, 0);
219  }
220  }
221 
222  double TiST_path(const HC_CC_Circle &c1, const HC_CC_Circle &c2, HC_CC_Circle **cstart, HC_CC_Circle **cend,
223  Configuration **q1, Configuration **q2, Configuration **q3, Configuration **q4) const
224  {
225  TiST_tangent_circles(c1, c2, q2, q3);
226  *cstart = new HC_CC_Circle(**q2, c1.left, !c1.forward, true, parent_->hc_cc_circle_param_);
227  *cend = new HC_CC_Circle(**q3, c2.left, !c2.forward, true, parent_->hc_cc_circle_param_);
228  *q1 = new Configuration(c1.start.x, c1.start.y, c1.start.theta, c1.kappa);
229  *q4 = new Configuration(c2.start.x, c2.start.y, c2.start.theta, c2.kappa);
230  return (*cstart)->hc_turn_length(**q1) + configuration_distance(**q2, **q3) + (*cend)->hc_turn_length(**q4);
231  }
232 
233  double TeST_path(const HC_CC_Circle &c1, const HC_CC_Circle &c2, HC_CC_Circle **cstart, HC_CC_Circle **cend,
234  Configuration **q1, Configuration **q2, Configuration **q3, Configuration **q4) const
235  {
236  TeST_tangent_circles(c1, c2, q2, q3);
237  *cstart = new HC_CC_Circle(**q2, c1.left, !c1.forward, true, parent_->hc_cc_circle_param_);
238  *cend = new HC_CC_Circle(**q3, c2.left, !c2.forward, true, parent_->hc_cc_circle_param_);
239  *q1 = new Configuration(c1.start.x, c1.start.y, c1.start.theta, c1.kappa);
240  *q4 = new Configuration(c2.start.x, c2.start.y, c2.start.theta, c2.kappa);
241  return (*cstart)->hc_turn_length(**q1) + configuration_distance(**q2, **q3) + (*cend)->hc_turn_length(**q4);
242  }
243 
244  double TST_path(const HC_CC_Circle &c1, const HC_CC_Circle &c2, HC_CC_Circle **cstart, HC_CC_Circle **cend,
245  Configuration **q1, Configuration **q2, Configuration **q3, Configuration **q4) const
246  {
247  if (TiST_exists(c1, c2))
248  {
249  return TiST_path(c1, c2, cstart, cend, q1, q2, q3, q4);
250  }
251  if (TeST_exists(c1, c2))
252  {
253  return TeST_path(c1, c2, cstart, cend, q1, q2, q3, q4);
254  }
255  return numeric_limits<double>::max();
256  }
257 
258  // ##### TTT ##################################################################
259  bool TTT_exists(const HC_CC_Circle &c1, const HC_CC_Circle &c2) const
260  {
261  if (c1.left != c2.left)
262  {
263  return false;
264  }
265  if (c1.forward == c2.forward)
266  {
267  return false;
268  }
269  return distance <= 4 * parent_->radius_;
270  }
271 
273  Configuration **q3, Configuration **q4) const
274  {
275  double theta = angle;
276  double r = 2 * parent_->radius_;
277  double delta_x = 0.5 * distance;
278  double delta_y = sqrt(pow(r, 2) - pow(delta_x, 2));
279  double x, y;
280 
281  global_frame_change(c1.xc, c1.yc, theta, delta_x, delta_y, &x, &y);
282  HC_CC_Circle tgt1(x, y, !c1.left, c1.forward, c1.regular, parent_->hc_cc_circle_param_);
283  global_frame_change(c1.xc, c1.yc, theta, delta_x, -delta_y, &x, &y);
284  HC_CC_Circle tgt2(x, y, !c1.left, c1.forward, c1.regular, parent_->hc_cc_circle_param_);
285 
286  TT_tangent_circles(c1, tgt1, q1);
287  TT_tangent_circles(tgt1, c2, q2);
288  TT_tangent_circles(c1, tgt2, q3);
289  TT_tangent_circles(tgt2, c2, q4);
290  }
291 
292  double TTT_path(const HC_CC_Circle &c1, const HC_CC_Circle &c2, HC_CC_Circle **cstart, HC_CC_Circle **cend,
293  Configuration **q1, Configuration **q2, Configuration **q3, HC_CC_Circle **ci) const
294  {
295  Configuration *qa, *qb, *qc, *qd;
296  TTT_tangent_circles(c1, c2, &qa, &qb, &qc, &qd);
297  HC_CC_Circle *start1, *start2, *end1, *end2, *middle1, *middle2;
298  start1 = new HC_CC_Circle(*qa, c1.left, !c1.forward, true, parent_->hc_cc_circle_param_);
299  middle1 = new HC_CC_Circle(*qa, !c1.left, c1.forward, true, parent_->hc_cc_circle_param_);
300  end1 = new HC_CC_Circle(*qb, c2.left, !c2.forward, true, parent_->hc_cc_circle_param_);
301  start2 = new HC_CC_Circle(*qc, c1.left, !c1.forward, true, parent_->hc_cc_circle_param_);
302  middle2 = new HC_CC_Circle(*qc, !c1.left, c1.forward, true, parent_->hc_cc_circle_param_);
303  end2 = new HC_CC_Circle(*qd, c2.left, !c2.forward, true, parent_->hc_cc_circle_param_);
304 
305  *q1 = new Configuration(c1.start.x, c1.start.y, c1.start.theta, c1.kappa);
306  *q3 = new Configuration(c2.start.x, c2.start.y, c2.start.theta, c2.kappa);
307 
308  // select shortest connection
309  double length1 = start1->hc_turn_length(**q1) + middle1->cc_turn_length(*qb) + end1->hc_turn_length(**q3);
310  double length2 = start2->hc_turn_length(**q1) + middle2->cc_turn_length(*qd) + end2->hc_turn_length(**q3);
311  if (length1 < length2)
312  {
313  *cstart = start1;
314  *ci = middle1;
315  *cend = end1;
316  *q2 = qb;
317  delete qa;
318  delete qc;
319  delete qd;
320  delete start2;
321  delete middle2;
322  delete end2;
323  return length1;
324  }
325  else
326  {
327  *cstart = start2;
328  *ci = middle2;
329  *cend = end2;
330  *q2 = qd;
331  delete qa;
332  delete qb;
333  delete qc;
334  delete start1;
335  delete middle1;
336  delete end1;
337  return length2;
338  }
339  return numeric_limits<double>::max();
340  }
341 
342  // ############################################################################
343 
344  // ##### TTTT #################################################################
345  bool TTTT_exists(const HC_CC_Circle &c1, const HC_CC_Circle &c2) const
346  {
347  if (c1.left == c2.left)
348  {
349  return false;
350  }
351  if (c1.forward == c2.forward)
352  {
353  return false;
354  }
355  return distance <= 6 * parent_->radius_;
356  }
357 
359  Configuration **q3, Configuration **q4, Configuration **q5, Configuration **q6) const
360  {
361  double theta = angle;
362  double r1, delta_x, delta_y, x, y;
363  r1 = 2 * parent_->radius_;
364  if (distance < r1)
365  {
366  delta_x = (distance + r1) / 2;
367  delta_y = sqrt(pow(r1, 2) - pow(delta_x, 2));
368  }
369  else
370  {
371  delta_x = (distance - r1) / 2;
372  delta_y = sqrt(pow(r1, 2) - pow(delta_x, 2));
373  }
374 
375  global_frame_change(c1.xc, c1.yc, theta, delta_x, delta_y, &x, &y);
376  HC_CC_Circle tgt1(x, y, !c1.left, c1.forward, c1.regular, parent_->hc_cc_circle_param_);
377  global_frame_change(c2.xc, c2.yc, theta, -delta_x, delta_y, &x, &y);
378  HC_CC_Circle tgt2(x, y, !c2.left, !c2.forward, c2.regular, parent_->hc_cc_circle_param_);
379 
380  global_frame_change(c1.xc, c1.yc, theta, delta_x, -delta_y, &x, &y);
381  HC_CC_Circle tgt3(x, y, !c1.left, c1.forward, c1.regular, parent_->hc_cc_circle_param_);
382  global_frame_change(c2.xc, c2.yc, theta, -delta_x, -delta_y, &x, &y);
383  HC_CC_Circle tgt4(x, y, !c2.left, !c2.forward, c2.regular, parent_->hc_cc_circle_param_);
384 
385  TT_tangent_circles(c1, tgt1, q1);
386  TT_tangent_circles(tgt1, tgt2, q2);
387  TT_tangent_circles(tgt2, c2, q3);
388 
389  TT_tangent_circles(c1, tgt3, q4);
390  TT_tangent_circles(tgt3, tgt4, q5);
391  TT_tangent_circles(tgt4, c2, q6);
392  }
393 
394  double TTTT_path(const HC_CC_Circle &c1, const HC_CC_Circle &c2, HC_CC_Circle **cstart, HC_CC_Circle **cend,
395  Configuration **q1, Configuration **q2, Configuration **q3, HC_CC_Circle **ci1,
396  HC_CC_Circle **ci2) const
397  {
398  Configuration *qa, *qb, *qc, *qd, *qe, *qf;
399  TTTT_tangent_circles(c1, c2, &qa, &qb, &qc, &qd, &qe, &qf);
400  HC_CC_Circle *start1, *start2, *end1, *end2, *middle1, *middle2, *middle3, *middle4;
401  start1 = new HC_CC_Circle(*qa, c1.left, !c1.forward, true, parent_->hc_cc_circle_param_);
402  middle1 = new HC_CC_Circle(*qa, !c1.left, c1.forward, true, parent_->hc_cc_circle_param_);
403  middle2 = new HC_CC_Circle(*qc, !c2.left, c2.forward, true, parent_->hc_cc_circle_param_);
404  end1 = new HC_CC_Circle(*qc, c2.left, !c2.forward, true, parent_->hc_cc_circle_param_);
405  start2 = new HC_CC_Circle(*qd, c1.left, !c1.forward, true, parent_->hc_cc_circle_param_);
406  middle3 = new HC_CC_Circle(*qd, !c1.left, c1.forward, true, parent_->hc_cc_circle_param_);
407  middle4 = new HC_CC_Circle(*qf, !c2.left, c2.forward, true, parent_->hc_cc_circle_param_);
408  end2 = new HC_CC_Circle(*qf, c2.left, !c2.forward, true, parent_->hc_cc_circle_param_);
409 
410  *q1 = new Configuration(c1.start.x, c1.start.y, c1.start.theta, c1.kappa);
411  *q3 = new Configuration(c2.start.x, c2.start.y, c2.start.theta, c2.kappa);
412 
413  // select shortest connection
414  double length1 = start1->hc_turn_length(**q1) + middle1->cc_turn_length(*qb) + middle2->cc_turn_length(*qb) +
415  end1->hc_turn_length(**q3);
416  double length2 = start2->hc_turn_length(**q1) + middle3->cc_turn_length(*qe) + middle4->cc_turn_length(*qe) +
417  end2->hc_turn_length(**q3);
418  if (length1 < length2)
419  {
420  *cstart = start1;
421  *cend = end1;
422  *ci1 = middle1;
423  *ci2 = middle2;
424  *q2 = qb;
425  delete qa;
426  delete qc;
427  delete qd;
428  delete qe;
429  delete qf;
430  delete start2, delete end2, delete middle3;
431  delete middle4;
432  return length1;
433  }
434  else
435  {
436  *cstart = start2;
437  *cend = end2;
438  *ci1 = middle3;
439  *ci2 = middle4;
440  *q2 = qe;
441  delete qa;
442  delete qb;
443  delete qc;
444  delete qd;
445  delete qf;
446  delete start1;
447  delete end1;
448  delete middle1;
449  delete middle2;
450  return length2;
451  }
452  return numeric_limits<double>::max();
453  }
454 };
455 
456 // ############################################################################
457 
458 CCpmpm_Dubins_State_Space::CCpmpm_Dubins_State_Space(double kappa, double sigma, double discretization, bool forwards)
459  : HC_CC_State_Space(kappa, sigma, discretization)
460  , forwards_(forwards)
461  , ccpmpm_dubins_{ unique_ptr<CCpmpm_Dubins>(new CCpmpm_Dubins(this)) }
462 {
463  rs_circle_param_.set_param(kappa_, numeric_limits<double>::max(), 1 / kappa_, 0.0, 0.0, 1.0, 0.0);
464  radius_ = hc_cc_circle_param_.radius;
465  mu_ = hc_cc_circle_param_.mu;
466  sin_mu_ = hc_cc_circle_param_.sin_mu;
467  cos_mu_ = hc_cc_circle_param_.cos_mu;
468 }
469 
471 
473  const HC_CC_Circle &c2) const
474 {
475  // table containing the lengths of the paths, the intermediate configurations and circles
476  double length[nb_cc_dubins_paths];
477  double_array_init(length, nb_cc_dubins_paths, numeric_limits<double>::max());
479  pointer_array_init((void **)qi1, nb_cc_dubins_paths);
481  pointer_array_init((void **)qi2, nb_cc_dubins_paths);
483  pointer_array_init((void **)qi3, nb_cc_dubins_paths);
485  pointer_array_init((void **)qi4, nb_cc_dubins_paths);
487  pointer_array_init((void **)cstart, nb_cc_dubins_paths);
489  pointer_array_init((void **)ci1, nb_cc_dubins_paths);
491  pointer_array_init((void **)ci2, nb_cc_dubins_paths);
493  pointer_array_init((void **)cend, nb_cc_dubins_paths);
494 
495  // precomputations
496  ccpmpm_dubins_->distance = center_distance(c1, c2);
497  ccpmpm_dubins_->angle = atan2(c2.yc - c1.yc, c2.xc - c1.xc);
498 
499  // case E
500  if (configuration_equal(c1.start, c2.start))
501  {
502  length[cc_dubins::E] = 0;
503  goto label_end;
504  }
505  // case T
507  {
508  cstart[cc_dubins::T] = new HC_CC_Circle(c1.start, c1.left, c1.forward, true, rs_circle_param_);
509  length[cc_dubins::T] = cstart[cc_dubins::T]->rs_turn_length(c2.start);
510  goto label_end;
511  }
512  // case TT
513  if (ccpmpm_dubins_->TT_exists(c1, c2))
514  {
515  length[cc_dubins::TT] = ccpmpm_dubins_->TT_path(c1, c2, &cstart[cc_dubins::TT], &cend[cc_dubins::TT],
516  &qi1[cc_dubins::TT], &qi2[cc_dubins::TT], &qi3[cc_dubins::TT]);
517  }
518  // ##### Dubins families: ######################################################
519  // case TST
520  if (ccpmpm_dubins_->TST_exists(c1, c2))
521  {
523  ccpmpm_dubins_->TST_path(c1, c2, &cstart[cc_dubins::TST], &cend[cc_dubins::TST], &qi1[cc_dubins::TST],
524  &qi2[cc_dubins::TST], &qi3[cc_dubins::TST], &qi4[cc_dubins::TST]);
525  }
526  // case TTT
527  if (ccpmpm_dubins_->TTT_exists(c1, c2))
528  {
530  ccpmpm_dubins_->TTT_path(c1, c2, &cstart[cc_dubins::TTT], &cend[cc_dubins::TTT], &qi1[cc_dubins::TTT],
531  &qi2[cc_dubins::TTT], &qi3[cc_dubins::TTT], &ci1[cc_dubins::TTT]);
532  }
533  // ############################################################################
534  // case TTTT
535  if (ccpmpm_dubins_->TTTT_exists(c1, c2))
536  {
537  length[cc_dubins::TTTT] = ccpmpm_dubins_->TTTT_path(
538  c1, c2, &cstart[cc_dubins::TTTT], &cend[cc_dubins::TTTT], &qi1[cc_dubins::TTTT], &qi2[cc_dubins::TTTT],
539  &qi3[cc_dubins::TTTT], &ci1[cc_dubins::TTTT], &ci2[cc_dubins::TTTT]);
540  }
541 label_end:
542  // select shortest path
545  path = new CC_Dubins_Path(c1.start, c2.start, best_path, kappa_, sigma_, qi1[best_path], qi2[best_path],
546  qi3[best_path], qi4[best_path], cstart[best_path], cend[best_path], ci1[best_path],
547  ci2[best_path], length[best_path]);
548 
549  // clean up
550  for (int i = 0; i < nb_cc_dubins_paths; i++)
551  {
552  if (i != best_path)
553  {
554  delete qi1[i];
555  delete qi2[i];
556  delete qi3[i];
557  delete qi4[i];
558  delete cstart[i];
559  delete ci1[i];
560  delete ci2[i];
561  delete cend[i];
562  }
563  }
564  return path;
565 }
566 
568 {
569  // compute the 2 circles at the intial and final configuration
570  Configuration start1(state1.x, state1.y, state1.theta, kappa_);
571  Configuration start2(state1.x, state1.y, state1.theta, -kappa_);
572  Configuration end1(state2.x, state2.y, state2.theta, kappa_);
573  Configuration end2(state2.x, state2.y, state2.theta, -kappa_);
574 
575  HC_CC_Circle *start_circle[2];
576  HC_CC_Circle *end_circle[2];
577  if (forwards_)
578  {
579  start_circle[0] = new HC_CC_Circle(start1, true, true, true, rs_circle_param_);
580  start_circle[1] = new HC_CC_Circle(start2, false, true, true, rs_circle_param_);
581  end_circle[0] = new HC_CC_Circle(end1, true, false, true, rs_circle_param_);
582  end_circle[1] = new HC_CC_Circle(end2, false, false, true, rs_circle_param_);
583  }
584  else
585  {
586  start_circle[0] = new HC_CC_Circle(start1, true, false, true, rs_circle_param_);
587  start_circle[1] = new HC_CC_Circle(start2, false, false, true, rs_circle_param_);
588  end_circle[0] = new HC_CC_Circle(end1, true, true, true, rs_circle_param_);
589  end_circle[1] = new HC_CC_Circle(end2, false, true, true, rs_circle_param_);
590  }
591 
592  // compute the shortest path for the 4 combinations (2 circles at the beginning and 2 at the end)
593  CC_Dubins_Path *path[] = { nullptr, nullptr, nullptr, nullptr };
594 
595  double lg[] = { numeric_limits<double>::max(), numeric_limits<double>::max(), numeric_limits<double>::max(),
596  numeric_limits<double>::max() };
597 
598  for (int i = 0; i < 2; i++)
599  {
600  // skip circle at the beginning for curvature continuity
601  if (i == 0 && state1.kappa < 0)
602  continue;
603  else if (i == 1 && state1.kappa > 0)
604  continue;
605  for (int j = 0; j < 2; j++)
606  {
607  // skip circle at the end for curvature continuity
608  if (j == 0 && state2.kappa < 0)
609  continue;
610  else if (j == 1 && state2.kappa > 0)
611  continue;
612  path[2 * i + j] = ccpmpm_circles_dubins_path(*start_circle[i], *end_circle[j]);
613  if (path[2 * i + j])
614  {
615  lg[2 * i + j] = path[2 * i + j]->length;
616  }
617  }
618  }
619 
620  // select shortest path
621  int best_path = array_index_min(lg, 4);
622 
623  // // display calculations
624  // cout << endl << "CCpmpm_Dubins_State_Space" << endl;
625  // for (int i = 0; i < 4; i++)
626  // {
627  // cout << i << ": ";
628  // if (path[i])
629  // {
630  // path[i]->print(true);
631  // cout << endl;
632  // }
633  // }
634  // cout << "shortest path: " << (int)best_path << endl;
635  // path[best_path]->print(true);
636 
637  // clean up
638  for (int i = 0; i < 2; i++)
639  {
640  delete start_circle[i];
641  delete end_circle[i];
642  }
643  for (int i = 0; i < 4; i++)
644  {
645  if (i != best_path)
646  {
647  delete path[i];
648  }
649  }
650  return path[best_path];
651 }
652 
653 double CCpmpm_Dubins_State_Space::get_distance(const State &state1, const State &state2) const
654 {
655  CC_Dubins_Path *p = this->ccpmpm_dubins(state1, state2);
656  double length = p->length;
657  delete p;
658  return length;
659 }
660 
661 vector<Control> CCpmpm_Dubins_State_Space::get_controls(const State &state1, const State &state2) const
662 {
663  vector<Control> cc_dubins_controls;
664  cc_dubins_controls.reserve(10);
665  CC_Dubins_Path *p = this->ccpmpm_dubins(state1, state2);
666  switch (p->type)
667  {
668  case cc_dubins::E:
669  empty_controls(cc_dubins_controls);
670  break;
671  case cc_dubins::T:
672  rs_turn_controls(*(p->cstart), p->end, true, cc_dubins_controls);
673  break;
674  case cc_dubins::TT:
675  hc_turn_controls(*(p->cstart), *(p->qi1), false, cc_dubins_controls);
676  hc_turn_controls(*(p->cend), *(p->qi3), true, cc_dubins_controls);
677  break;
678  // ##### Dubins families: #####################################################
679  case cc_dubins::TST:
680  hc_turn_controls(*(p->cstart), *(p->qi1), false, cc_dubins_controls);
681  straight_controls(*(p->qi2), *(p->qi3), cc_dubins_controls);
682  hc_turn_controls(*(p->cend), *(p->qi4), true, cc_dubins_controls);
683  break;
684  case cc_dubins::TTT:
685  hc_turn_controls(*(p->cstart), *(p->qi1), false, cc_dubins_controls);
686  cc_turn_controls(*(p->ci1), *(p->qi2), true, cc_dubins_controls);
687  hc_turn_controls(*(p->cend), *(p->qi3), true, cc_dubins_controls);
688  break;
689  // ############################################################################
690  case cc_dubins::TTTT:
691  hc_turn_controls(*(p->cstart), *(p->qi1), false, cc_dubins_controls);
692  cc_turn_controls(*(p->ci1), *(p->qi2), true, cc_dubins_controls);
693  cc_turn_controls(*(p->ci2), *(p->qi2), false, cc_dubins_controls);
694  hc_turn_controls(*(p->cend), *(p->qi3), true, cc_dubins_controls);
695  break;
696  default:
697  break;
698  }
699  delete p;
700  return cc_dubins_controls;
701 }
702 
703 } // namespace steering
steering::cc_dubins::TST
@ TST
Definition: paths.hpp:88
steering::rs_turn_controls
void rs_turn_controls(const HC_CC_Circle &c, const Configuration &q, bool order, std::vector< Control > &controls)
Appends controls with a rs-turn.
plot_states.alpha
alpha
Definition: plot_states.py:107
steering::CCpmpm_Dubins_State_Space::CCpmpm_Dubins::TTTT_tangent_circles
void TTTT_tangent_circles(const HC_CC_Circle &c1, const HC_CC_Circle &c2, Configuration **q1, Configuration **q2, Configuration **q3, Configuration **q4, Configuration **q5, Configuration **q6) const
Definition: ccpmpm_dubins_state_space.cpp:358
steering::Path::length
double length
Path length.
Definition: paths.hpp:98
steering::HC_CC_State_Space::hc_cc_circle_param_
HC_CC_Circle_Param hc_cc_circle_param_
Parameters of a hc-/cc-circle.
Definition: hc_cc_state_space.hpp:101
steering::CCpmpm_Dubins_State_Space::CCpmpm_Dubins::TTT_path
double TTT_path(const HC_CC_Circle &c1, const HC_CC_Circle &c2, HC_CC_Circle **cstart, HC_CC_Circle **cend, Configuration **q1, Configuration **q2, Configuration **q3, HC_CC_Circle **ci) const
Definition: ccpmpm_dubins_state_space.cpp:292
steering::CCpmpm_Dubins_State_Space::CCpmpm_Dubins::TT_tangent_circles
void TT_tangent_circles(const HC_CC_Circle &c1, const HC_CC_Circle &c2, Configuration **q) const
Definition: ccpmpm_dubins_state_space.cpp:66
steering::cc_dubins::TT
@ TT
Definition: paths.hpp:86
steering::State
Description of a kinematic car's state.
Definition: steering_functions.hpp:44
angle
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
steering::HC_CC_State_Space::sigma_
double sigma_
Definition: hc_cc_state_space.hpp:95
steering::CC_Dubins_Path::cstart
HC_CC_Circle * cstart
Start, end and intermediate circles.
Definition: paths.hpp:117
plot_states.path
path
Definition: plot_states.py:88
steering::CCpmpm_Dubins_State_Space::mu_
double mu_
Angle between a configuration on the hc-/cc-circle and the tangent to the circle at that position.
Definition: ccpmpm_dubins_state_space.hpp:131
steering::cc_dubins::path_type
path_type
Definition: paths.hpp:81
steering::State::theta
double theta
Orientation of the robot.
Definition: steering_functions.hpp:70
steering::CCpmpm_Dubins_State_Space::CCpmpm_Dubins::TST_path
double TST_path(const HC_CC_Circle &c1, const HC_CC_Circle &c2, HC_CC_Circle **cstart, HC_CC_Circle **cend, Configuration **q1, Configuration **q2, Configuration **q3, Configuration **q4) const
Definition: ccpmpm_dubins_state_space.cpp:244
configuration.hpp
steering::CCpmpm_Dubins_State_Space::get_distance
double get_distance(const State &state1, const State &state2) const
Returns shortest path length from state1 to state2.
Definition: ccpmpm_dubins_state_space.cpp:653
steering::CCpmpm_Dubins_State_Space::ccpmpm_dubins
CC_Dubins_Path * ccpmpm_dubins(const State &state1, const State &state2) const
Returns a sequence of turns and straight lines connecting a start and an end configuration.
Definition: ccpmpm_dubins_state_space.cpp:567
steering::HC_CC_Circle::left
bool left
Turning direction: left/right.
Definition: hc_cc_circle.hpp:123
steering::CCpmpm_Dubins_State_Space::CCpmpm_Dubins::TiST_exists
bool TiST_exists(const HC_CC_Circle &c1, const HC_CC_Circle &c2) const
Definition: ccpmpm_dubins_state_space.cpp:111
steering::CCpmpm_Dubins_State_Space::CCpmpm_Dubins::TTT_exists
bool TTT_exists(const HC_CC_Circle &c1, const HC_CC_Circle &c2) const
Definition: ccpmpm_dubins_state_space.cpp:259
steering::empty_controls
void empty_controls(std::vector< Control > &controls)
Appends controls with 0 input.
steering::CCpmpm_Dubins_State_Space::cos_mu_
double cos_mu_
Definition: ccpmpm_dubins_state_space.hpp:134
steering::nb_cc_dubins_paths
const int nb_cc_dubins_paths
Definition: paths.hpp:94
steering::State::kappa
double kappa
Curvature at position (x,y)
Definition: steering_functions.hpp:73
plot_statistics.CCpmpm_Dubins
CCpmpm_Dubins
Definition: plot_statistics.py:95
steering::HC_CC_Circle
Definition: hc_cc_circle.hpp:80
steering::CCpmpm_Dubins_State_Space::sin_mu_
double sin_mu_
Sine and cosine of mu.
Definition: ccpmpm_dubins_state_space.hpp:134
steering::State::y
double y
Position in y of the robot.
Definition: steering_functions.hpp:67
steering::HC_CC_Circle::xc
double xc
Center of the circle.
Definition: hc_cc_circle.hpp:132
steering::CC_Dubins_Path::qi3
Configuration * qi3
Definition: paths.hpp:114
steering::cc_dubins::TTT
@ TTT
Definition: paths.hpp:89
steering::CCpmpm_Dubins_State_Space::rs_circle_param_
HC_CC_Circle_Param rs_circle_param_
Parameter of a rs-circle.
Definition: ccpmpm_dubins_state_space.hpp:125
steering::configuration_distance
double configuration_distance(const Configuration &q1, const Configuration &q2)
Cartesian distance between two configurations.
Definition: configuration.cpp:54
steering::CCpmpm_Dubins_State_Space::CCpmpm_Dubins::TT_exists
bool TT_exists(const HC_CC_Circle &c1, const HC_CC_Circle &c2) const
Definition: ccpmpm_dubins_state_space.cpp:53
steering::HC_CC_Circle::yc
double yc
Definition: hc_cc_circle.hpp:132
steering::CCpmpm_Dubins_State_Space::forwards_
bool forwards_
Driving direction.
Definition: ccpmpm_dubins_state_space.hpp:116
steering::cc_dubins::E
@ E
Definition: paths.hpp:83
steering::global_frame_change
void global_frame_change(double x, double y, double theta, double local_x, double local_y, double *global_x, double *global_y)
Transformation of (local_x, local_y) from local coordinate system to global one.
Definition: utilities.cpp:223
steering::HC_CC_Circle::forward
bool forward
Driving direction: forwards/backwards.
Definition: hc_cc_circle.hpp:126
steering::CCpmpm_Dubins_State_Space::ccpmpm_dubins_
std::unique_ptr< CCpmpm_Dubins > ccpmpm_dubins_
Pimpl Idiom: unique pointer on class with families
Definition: ccpmpm_dubins_state_space.hpp:119
steering::CCpmpm_Dubins_State_Space::radius_
double radius_
Outer radius of a hc-/cc-circle.
Definition: ccpmpm_dubins_state_space.hpp:128
steering::CCpmpm_Dubins_State_Space::CCpmpm_Dubins
Definition: ccpmpm_dubins_state_space.cpp:38
steering::hc_turn_controls
void hc_turn_controls(const HC_CC_Circle &c, const Configuration &q, bool order, std::vector< Control > &controls)
Appends controls with a hc-turn.
steering::State::x
double x
Position in x of the robot.
Definition: steering_functions.hpp:64
steering::CCpmpm_Dubins_State_Space::CCpmpm_Dubins::TT_path
double TT_path(const HC_CC_Circle &c1, const HC_CC_Circle &c2, HC_CC_Circle **cstart, HC_CC_Circle **cend, Configuration **q1, Configuration **q2, Configuration **q3) const
Definition: ccpmpm_dubins_state_space.cpp:97
steering::pointer_array_init
void pointer_array_init(void *array[], int size)
Initialize an array with nullptr.
Definition: utilities.cpp:264
steering::HC_CC_State_Space::kappa_
double kappa_
Curvature, sharpness of clothoid.
Definition: hc_cc_state_space.hpp:95
steering::CC_Dubins_Path::ci1
HC_CC_Circle * ci1
Definition: paths.hpp:117
steering::straight_controls
void straight_controls(const Configuration &q1, const Configuration &q2, std::vector< Control > &controls)
Appends controls with a straight line.
distance
double distance(double x0, double y0, double x1, double y1)
steering::CCpmpm_Dubins_State_Space::CCpmpm_Dubins::TiST_path
double TiST_path(const HC_CC_Circle &c1, const HC_CC_Circle &c2, HC_CC_Circle **cstart, HC_CC_Circle **cend, Configuration **q1, Configuration **q2, Configuration **q3, Configuration **q4) const
Definition: ccpmpm_dubins_state_space.cpp:222
steering::HC_CC_State_Space
Definition: hc_cc_state_space.hpp:45
steering::CCpmpm_Dubins_State_Space::get_controls
std::vector< Control > get_controls(const State &state1, const State &state2) const
Returns controls of the shortest path from state1 to state2.
Definition: ccpmpm_dubins_state_space.cpp:661
steering::Configuration
Definition: configuration.hpp:55
steering::array_index_min
int array_index_min(double array[], int size)
Find index with minimal value in double array.
Definition: utilities.cpp:241
steering::HC_CC_Circle::cc_turn_length
double cc_turn_length(const Configuration &q) const
Length of a cc-turn.
Definition: hc_cc_circle.cpp:238
steering::center_distance
double center_distance(const HC_CC_Circle &c1, const HC_CC_Circle &c2)
Cartesian distance between the centers of two circles.
Definition: hc_cc_circle.cpp:307
steering::CCpmpm_Dubins_State_Space::ccpmpm_circles_dubins_path
CC_Dubins_Path * ccpmpm_circles_dubins_path(const HC_CC_Circle &c1, const HC_CC_Circle &c2) const
Returns a sequence of turns and straight lines connecting the two circles c1 and c2.
Definition: ccpmpm_dubins_state_space.cpp:472
steering::HC_CC_Circle::regular
bool regular
Type of the circle: regular/irregular.
Definition: hc_cc_circle.hpp:129
steering::get_epsilon
double get_epsilon()
Return value of epsilon.
Definition: utilities.cpp:57
steering::CCpmpm_Dubins_State_Space::CCpmpm_Dubins::TTTT_path
double TTTT_path(const HC_CC_Circle &c1, const HC_CC_Circle &c2, HC_CC_Circle **cstart, HC_CC_Circle **cend, Configuration **q1, Configuration **q2, Configuration **q3, HC_CC_Circle **ci1, HC_CC_Circle **ci2) const
Definition: ccpmpm_dubins_state_space.cpp:394
steering::CCpmpm_Dubins_State_Space::CCpmpm_Dubins::TeST_path
double TeST_path(const HC_CC_Circle &c1, const HC_CC_Circle &c2, HC_CC_Circle **cstart, HC_CC_Circle **cend, Configuration **q1, Configuration **q2, Configuration **q3, Configuration **q4) const
Definition: ccpmpm_dubins_state_space.cpp:233
std
steering::CCpmpm_Dubins_State_Space::CCpmpm_Dubins::TTT_tangent_circles
void TTT_tangent_circles(const HC_CC_Circle &c1, const HC_CC_Circle &c2, Configuration **q1, Configuration **q2, Configuration **q3, Configuration **q4) const
Definition: ccpmpm_dubins_state_space.cpp:272
steering::HC_CC_Circle_Param::kappa
double kappa
Max. curvature, inverse of max. curvature, max. sharpness.
Definition: hc_cc_circle.hpp:88
length
TFSIMD_FORCE_INLINE tfScalar length(const Quaternion &q)
steering::CCpmpm_Dubins_State_Space::CCpmpm_Dubins::TST_exists
bool TST_exists(const HC_CC_Circle &c1, const HC_CC_Circle &c2) const
Definition: ccpmpm_dubins_state_space.cpp:137
plot_states.kappa
kappa
Definition: plot_states.py:106
steering::CC_Dubins_Path::qi1
Configuration * qi1
Intermediate configurations.
Definition: paths.hpp:114
ccpmpm_dubins_state_space.hpp
steering::CC_Dubins_Path::qi2
Configuration * qi2
Definition: paths.hpp:114
steering::double_array_init
void double_array_init(double array[], int size, double value)
Initialize an array with a given value.
Definition: utilities.cpp:256
steering
Definition: dubins_state_space.hpp:70
steering::cc_turn_controls
void cc_turn_controls(const HC_CC_Circle &c, const Configuration &q, bool order, std::vector< Control > &controls)
Appends controls with a cc-turn.
steering::cc_dubins::TTTT
@ TTTT
Definition: paths.hpp:91
steering::CC_Dubins_Path::type
cc_dubins::path_type type
Path type.
Definition: paths.hpp:111
steering::CC_Dubins_Path::cend
HC_CC_Circle * cend
Definition: paths.hpp:117
steering::CCpmpm_Dubins_State_Space::CCpmpm_Dubins::TeST_tangent_circles
void TeST_tangent_circles(const HC_CC_Circle &c1, const HC_CC_Circle &c2, Configuration **q1, Configuration **q2) const
Definition: ccpmpm_dubins_state_space.cpp:185
PI
#define PI
Definition: utilities.hpp:31
steering::CCpmpm_Dubins_State_Space::CCpmpm_Dubins::TTTT_exists
bool TTTT_exists(const HC_CC_Circle &c1, const HC_CC_Circle &c2) const
Definition: ccpmpm_dubins_state_space.cpp:345
steering::configuration_on_hc_cc_circle
bool configuration_on_hc_cc_circle(const HC_CC_Circle &c, const Configuration &q)
Configuration on the circle?
Definition: hc_cc_circle.cpp:312
steering::configuration_equal
bool configuration_equal(const Configuration &q1, const Configuration &q2)
Are two configurations equal?
Definition: configuration.cpp:69
steering::CCpmpm_Dubins_State_Space::CCpmpm_Dubins::CCpmpm_Dubins
CCpmpm_Dubins(CCpmpm_Dubins_State_Space *parent)
Definition: ccpmpm_dubins_state_space.cpp:44
steering::CCpmpm_Dubins_State_Space::CCpmpm_Dubins::TeST_exists
bool TeST_exists(const HC_CC_Circle &c1, const HC_CC_Circle &c2) const
Definition: ccpmpm_dubins_state_space.cpp:124
steering::CC_Dubins_Path::ci2
HC_CC_Circle * ci2
Definition: paths.hpp:117
steering::Configuration::y
double y
Definition: configuration.hpp:88
steering::CC_Dubins_Path
Definition: paths.hpp:96
HALF_PI
#define HALF_PI
Definition: utilities.hpp:32
steering::CCpmpm_Dubins_State_Space::~CCpmpm_Dubins_State_Space
~CCpmpm_Dubins_State_Space()
Destructor.
steering::cc_dubins::T
@ T
Definition: paths.hpp:85
steering::Path::end
Configuration end
Definition: paths.hpp:92
steering::CC_Dubins_Path::qi4
Configuration * qi4
Definition: paths.hpp:114
steering::HC_CC_Circle::start
Configuration start
Start configuration.
Definition: hc_cc_circle.hpp:120
steering::Configuration::x
double x
Position.
Definition: configuration.hpp:88
utilities.hpp
steering::Configuration::theta
double theta
Orientation in rad between [0, 2*pi[.
Definition: configuration.hpp:91
steering::CCpmpm_Dubins_State_Space::CCpmpm_Dubins::TiST_tangent_circles
void TiST_tangent_circles(const HC_CC_Circle &c1, const HC_CC_Circle &c2, Configuration **q1, Configuration **q2) const
Definition: ccpmpm_dubins_state_space.cpp:142
steering::CCpmpm_Dubins_State_Space::CCpmpm_Dubins::parent_
CCpmpm_Dubins_State_Space * parent_
Definition: ccpmpm_dubins_state_space.cpp:41
steering::CCpmpm_Dubins_State_Space
An implementation of continuous curvature (CC) steer for a Dubins car with either positive (p) or neg...
Definition: ccpmpm_dubins_state_space.hpp:70
steering::HC_CC_Circle::hc_turn_length
double hc_turn_length(const Configuration &q) const
Length of a hc-turn.
Definition: hc_cc_circle.cpp:185


steering_functions
Author(s): Holger Banzhaf
autogenerated on Mon Dec 11 2023 03:27:43