hc_cc_circle.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 <cassert>
27 #include <cmath>
28 #include <iostream>
29 #include <limits>
30 
33 
34 using namespace std;
35 
36 namespace steering
37 {
38 
39 void HC_CC_Circle_Param::set_param(double _kappa, double _sigma, double _radius, double _mu, double _sin_mu,
40  double _cos_mu, double _delta_min)
41 {
42  kappa = _kappa;
43  kappa_inv = 1 / _kappa;
44  sigma = _sigma;
45  radius = _radius;
46  mu = _mu;
47  sin_mu = _sin_mu;
48  cos_mu = _cos_mu;
49  delta_min = _delta_min;
50 }
51 
52 HC_CC_Circle::HC_CC_Circle(const Configuration &_start, bool _left, bool _forward, bool _regular,
53  const HC_CC_Circle_Param &_param)
54 {
55  start = _start;
56  left = _left;
57  forward = _forward;
58  regular = _regular;
59  double delta_x = _param.radius * _param.sin_mu;
60  double delta_y = _param.radius * _param.cos_mu;
61  if (left)
62  {
63  kappa = _param.kappa;
64  kappa_inv = _param.kappa_inv;
65  sigma = _param.sigma;
66  if (forward)
67  global_frame_change(_start.x, _start.y, _start.theta, delta_x, delta_y, &xc, &yc);
68  else
69  global_frame_change(_start.x, _start.y, _start.theta, -delta_x, delta_y, &xc, &yc);
70  }
71  else
72  {
73  kappa = -_param.kappa;
74  kappa_inv = -_param.kappa_inv;
75  sigma = -_param.sigma;
76  if (forward)
77  global_frame_change(_start.x, _start.y, _start.theta, delta_x, -delta_y, &xc, &yc);
78  else
79  global_frame_change(_start.x, _start.y, _start.theta, -delta_x, -delta_y, &xc, &yc);
80  }
81  radius = _param.radius;
82  mu = _param.mu;
83  sin_mu = _param.sin_mu;
84  cos_mu = _param.cos_mu;
85  delta_min = _param.delta_min;
86 }
87 
88 HC_CC_Circle::HC_CC_Circle(double _xc, double _yc, bool _left, bool _forward, bool _regular,
89  const HC_CC_Circle_Param &_param)
90 {
91  start = Configuration(0, 0, 0, 0);
92  left = _left;
93  forward = _forward;
94  regular = _regular;
95  if (left)
96  {
97  kappa = _param.kappa;
98  kappa_inv = _param.kappa_inv;
99  sigma = _param.sigma;
100  }
101  else
102  {
103  kappa = -_param.kappa;
104  kappa_inv = -_param.kappa_inv;
105  sigma = -_param.sigma;
106  }
107  xc = _xc;
108  yc = _yc;
109  radius = _param.radius;
110  mu = _param.mu;
111  sin_mu = _param.sin_mu;
112  cos_mu = _param.cos_mu;
113  delta_min = _param.delta_min;
114 }
115 
116 double HC_CC_Circle::deflection(const Configuration &q) const
117 {
118  double alpha_c = this->start.theta;
119  double alpha_q = q.theta;
120  if ((this->left && this->forward) || (!this->left && !this->forward))
121  {
122  return twopify(alpha_q - alpha_c);
123  }
124  else
125  {
126  return twopify(alpha_c - alpha_q);
127  }
128 }
129 
130 double HC_CC_Circle::D1(double alpha) const
131 {
132  double fresnel_s, fresnel_c;
133  double s = sqrt(2 * alpha / PI);
134  fresnel(s, fresnel_s, fresnel_c);
135  return cos(alpha) * fresnel_c + sin(alpha) * fresnel_s;
136 }
137 
138 double HC_CC_Circle::rs_circular_deflection(double delta) const
139 {
140  // regular rs-turn
141  if (this->regular)
142  return delta;
143  // irregular rs-turn
144  else
145  return (delta <= PI) ? delta : delta - TWO_PI;
146 }
147 
148 double HC_CC_Circle::rs_turn_length(const Configuration &q) const
149 {
150  assert(fabs(fabs(this->kappa) - fabs(q.kappa)) < get_epsilon() &&
151  fabs(fabs(this->sigma) - numeric_limits<double>::max()) < get_epsilon());
152  double delta = this->deflection(q);
153  return fabs(this->kappa_inv * this->rs_circular_deflection(delta));
154 }
155 
156 double HC_CC_Circle::hc_circular_deflection(double delta) const
157 {
158  double delta_min_twopified = twopify(this->delta_min);
159  // regular hc-turn
160  if (this->regular)
161  {
162  if (delta < delta_min_twopified)
163  return TWO_PI + delta - delta_min_twopified;
164  else
165  return delta - delta_min_twopified;
166  }
167  // irregular hc-turn
168  else
169  {
170  double delta_arc1, delta_arc2;
171  if (delta < delta_min_twopified)
172  {
173  delta_arc1 = delta - delta_min_twopified; // negative
174  delta_arc2 = delta_arc1 + TWO_PI; // positive
175  }
176  else
177  {
178  delta_arc1 = delta - delta_min_twopified; // positive
179  delta_arc2 = delta_arc1 - TWO_PI; // negative
180  }
181  return (fabs(delta_arc1) < fabs(delta_arc2)) ? delta_arc1 : delta_arc2;
182  }
183 }
184 
185 double HC_CC_Circle::hc_turn_length(const Configuration &q) const
186 {
187  assert(fabs(fabs(this->kappa) - fabs(q.kappa)) < get_epsilon());
188  double delta = this->deflection(q);
189  return fabs(this->kappa / this->sigma) + fabs(this->kappa_inv * this->hc_circular_deflection(delta));
190 }
191 
192 bool HC_CC_Circle::cc_elementary_sharpness(const Configuration &q, double delta, double &sigma0) const
193 {
194  double distance = point_distance(this->start.x, this->start.y, q.x, q.y);
195  // existence conditions for an elementary path (also see: A. Scheuer and T. Fraichard, "Continuous-Curvature Path
196  // Planning for Car-Like Vehicles," in IEEE/RSJ International Conference on Intelligent Robots and Systems, 1997.
197  if (delta < 4.5948 && distance > get_epsilon())
198  {
199  sigma0 = 4 * PI * pow(this->D1(0.5 * delta), 2) / pow(distance, 2);
200  if (!this->left)
201  {
202  sigma0 = -sigma0;
203  }
204  return true;
205  }
206  return false;
207 }
208 
209 double HC_CC_Circle::cc_circular_deflection(double delta) const
210 {
211  double two_delta_min_twopified = twopify(2 * this->delta_min);
212  // regular cc-turn
213  if (this->regular)
214  {
215  if (delta < two_delta_min_twopified)
216  return TWO_PI + delta - two_delta_min_twopified;
217  else
218  return delta - two_delta_min_twopified;
219  }
220  // irregular cc-turn
221  else
222  {
223  double delta_arc1, delta_arc2;
224  if (delta < two_delta_min_twopified)
225  {
226  delta_arc1 = delta - two_delta_min_twopified; // negative
227  delta_arc2 = delta_arc1 + TWO_PI; // positive
228  }
229  else
230  {
231  delta_arc1 = delta - two_delta_min_twopified; // positive
232  delta_arc2 = delta_arc1 - TWO_PI; // negative
233  }
234  return (fabs(delta_arc1) < fabs(delta_arc2)) ? delta_arc1 : delta_arc2;
235  }
236 }
237 
238 double HC_CC_Circle::cc_turn_length(const Configuration &q) const
239 {
240  assert(fabs(q.kappa) < get_epsilon());
241  double delta = this->deflection(q);
242  // delta = 0
243  if (delta < get_epsilon())
244  {
245  return 2 * this->radius * this->sin_mu;
246  }
247  // 0 < delta < 2 * delta_min
248  double length_min = fabs(this->kappa / this->sigma);
249  double length_default = 2 * length_min + fabs(this->kappa_inv * this->cc_circular_deflection(delta));
250  if (delta < 2 * this->delta_min)
251  {
252  double sigma0;
253  if (this->cc_elementary_sharpness(q, delta, sigma0))
254  {
255  double length_elementary = 2 * sqrt(delta / fabs(sigma0));
256  return (length_elementary < length_default) ? length_elementary : length_default;
257  }
258  else
259  {
260  return length_default;
261  }
262  }
263  // delta >= 2 * delta_min
264  else
265  {
266  return length_default;
267  }
268 }
269 
270 void HC_CC_Circle::print(bool eol) const
271 {
272  cout << "HC_CC_Circle: ";
273  cout << "start: ";
274  start.print(false);
275  if (left)
276  {
277  cout << ", left";
278  }
279  else
280  {
281  cout << ", right";
282  }
283  if (forward)
284  {
285  cout << ", forward";
286  }
287  else
288  {
289  cout << ", backward";
290  }
291  if (regular)
292  {
293  cout << ", regular";
294  }
295  else
296  {
297  cout << ", irregular";
298  }
299  cout << ", kappa: " << kappa << ", sigma: " << sigma;
300  cout << ", centre: (" << xc << ", " << yc << "), radius " << radius << ", mu: " << mu;
301  if (eol)
302  {
303  cout << endl;
304  }
305 }
306 
307 double center_distance(const HC_CC_Circle &c1, const HC_CC_Circle &c2)
308 {
309  return sqrt(pow(c2.xc - c1.xc, 2) + pow(c2.yc - c1.yc, 2));
310 }
311 
313 {
314  double distance = point_distance(c.xc, c.yc, q.x, q.y);
315  if (fabs(distance - c.radius) > get_epsilon())
316  {
317  return false;
318  }
319  double angle = atan2(q.y - c.yc, q.x - c.xc);
320  if (c.left && c.forward)
321  {
322  angle = angle + HALF_PI - c.mu;
323  }
324  if (c.left && !c.forward)
325  {
326  angle = angle + HALF_PI + c.mu;
327  }
328  if (!c.left && c.forward)
329  {
330  angle = angle - HALF_PI + c.mu;
331  }
332  if (!c.left && !c.forward)
333  {
334  angle = angle - HALF_PI - c.mu;
335  }
336  angle = twopify(angle);
337  return fabs(q.theta - angle) < get_epsilon();
338 }
339 
340 } // namespace steering
plot_states.alpha
alpha
Definition: plot_states.py:107
steering::point_distance
double point_distance(double x1, double y1, double x2, double y2)
Cartesian distance between two points.
Definition: utilities.cpp:67
angle
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
steering::HC_CC_Circle_Param
Definition: hc_cc_circle.hpp:57
steering::HC_CC_Circle_Param::mu
double mu
Angle between the initial orientation and the tangent to the circle at the initial position.
Definition: hc_cc_circle.hpp:94
s
XmlRpcServer s
TWO_PI
#define TWO_PI
Definition: utilities.hpp:33
steering::HC_CC_Circle::left
bool left
Turning direction: left/right.
Definition: hc_cc_circle.hpp:123
steering::HC_CC_Circle_Param::delta_min
double delta_min
Minimal deflection.
Definition: hc_cc_circle.hpp:100
steering::HC_CC_Circle
Definition: hc_cc_circle.hpp:80
steering::HC_CC_Circle_Param::cos_mu
double cos_mu
Definition: hc_cc_circle.hpp:97
steering::HC_CC_Circle::xc
double xc
Center of the circle.
Definition: hc_cc_circle.hpp:132
steering::HC_CC_Circle_Param::kappa_inv
double kappa_inv
Definition: hc_cc_circle.hpp:88
steering::Configuration::kappa
double kappa
Curvature.
Definition: configuration.hpp:94
steering::fresnel
void fresnel(double s, double &S_f, double &C_f)
Fresnel integrals: S_f = int_0_s(sin(pi/2 u*u)du), C_f = int_0_s(cos(pi/2 u*u)du) approximated with C...
Definition: utilities.cpp:161
steering::HC_CC_Circle::yc
double yc
Definition: hc_cc_circle.hpp:132
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
hc_cc_circle.hpp
steering::HC_CC_Circle_Param::sigma
double sigma
Definition: hc_cc_circle.hpp:88
distance
double distance(double x0, double y0, double x1, double y1)
steering::HC_CC_Circle_Param::sin_mu
double sin_mu
Sine and cosine of mu.
Definition: hc_cc_circle.hpp:97
steering::Configuration
Definition: configuration.hpp:55
start
ROSCPP_DECL void start()
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::get_epsilon
double get_epsilon()
Return value of epsilon.
Definition: utilities.cpp:57
std
steering::HC_CC_Circle_Param::kappa
double kappa
Max. curvature, inverse of max. curvature, max. sharpness.
Definition: hc_cc_circle.hpp:88
plot_states.kappa
kappa
Definition: plot_states.py:106
steering
Definition: dubins_state_space.hpp:70
PI
#define PI
Definition: utilities.hpp:31
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::y
double y
Definition: configuration.hpp:88
HALF_PI
#define HALF_PI
Definition: utilities.hpp:32
steering::HC_CC_Circle_Param::radius
double radius
Radius of the outer circle.
Definition: hc_cc_circle.hpp:91
steering::twopify
double twopify(double alpha)
Conversion of arbitrary angle given in [rad] to [0, 2*pi[.
Definition: utilities.cpp:78
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_functions
Author(s): Holger Banzhaf
autogenerated on Mon Dec 11 2023 03:27:43