hc_cc_circle_test.cpp
Go to the documentation of this file.
1 /*********************************************************************
2 * Copyright (c) 2019 Robert Bosch GmbH.
3 * All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 * *********************************************************************/
17 
18 #include <gtest/gtest.h>
19 
26 
27 #define EPS_DISTANCE 0.01 // [m]
28 #define EPS_KAPPA 1e-6 // [1/m]
29 #define EPS_SIGMA 1e-6 // [1/m^2]
30 #define KAPPA 1.0 // [1/m]
31 #define DISCRETIZATION 0.05 // [m]
32 
33 using namespace std;
34 using namespace steering;
35 
37 {
38 public:
39  Test_HC_CC_State_Space(double kappa, double sigma, double discretization)
40  : HC_CC_State_Space(kappa, sigma, discretization)
41  {
42  }
43 
44  vector<Control> get_controls(const State &state1, const State &state2) const
45  {
46  throw runtime_error("Test_HC_CC_State_Space.get_controls() not implemented");
47  }
48 
50  {
51  return hc_cc_circle_param_;
52  }
53 };
54 
55 Configuration get_cc_goal_config(double delta, const HC_CC_Circle_Param &hc_cc_circle_param)
56 {
57  double radius = hc_cc_circle_param.radius;
58  double mu = hc_cc_circle_param.mu;
59  double xc = radius * sin(mu);
60  double yc = radius * cos(mu);
61 
62  // goal config of cc-turn given in local frame (aligned with start config) assuming left = forward = true
63  Configuration goal;
64  goal.x = xc + radius * sin(delta + mu);
65  goal.y = yc - radius * cos(delta + mu);
66  goal.theta = delta;
67  goal.kappa = 0.0;
68  return goal;
69 }
70 
71 Configuration get_hc_goal_config(double delta, const HC_CC_Circle_Param &hc_cc_circle_param)
72 {
73  double radius = hc_cc_circle_param.radius;
74  double mu = hc_cc_circle_param.mu;
75  double xc = radius * sin(mu);
76  double yc = radius * cos(mu);
77  double kappa = hc_cc_circle_param.kappa;
78 
79  // goal config of hc-turn given in local frame (aligned with start config) assuming left = forward = true
80  Configuration goal;
81  goal.x = xc + (1 / kappa) * sin(delta);
82  goal.y = yc - (1 / kappa) * cos(delta);
83  goal.theta = delta;
84  goal.kappa = kappa;
85  return goal;
86 }
87 
88 vector<double> get_linear_samples(double start, double stop, size_t num)
89 {
90  double step = (stop - start) / static_cast<double>(num - 1);
91  vector<double> samples(num);
92  double sample = start;
93  for (vector<double>::iterator iter = samples.begin(); iter != samples.end(); ++iter, sample += step)
94  *iter = sample;
95  return samples;
96 }
97 
98 double get_distance(const State &state1, const State &state2)
99 {
100  return sqrt(pow(state2.x - state1.x, 2) + pow(state2.y - state1.y, 2));
101 }
102 
103 double get_path_length(const vector<State> &path)
104 {
105  double path_length = 0;
106  State state1 = path.front();
107  for (const auto &state2 : path)
108  {
109  path_length += get_distance(state1, state2);
110  state1 = state2;
111  }
112  return path_length;
113 }
114 
115 Configuration start_config(0.0, 0.0, 0.0, 0.0); // do not change
116 vector<double> sigmas = get_linear_samples(0.02, 200.0, 1000); // [1/m^2]
117 vector<double> deltas = get_linear_samples(0.0, 2 * M_PI, 1e3); // [rad]
118 
119 TEST(HC_CC_Circle, pathLength)
120 {
121  State start_state;
122  start_state.x = start_config.x;
123  start_state.y = start_config.y;
124  start_state.theta = start_config.theta;
125  start_state.kappa = start_config.kappa;
126  start_state.d = 0.0;
127 
128  for (const auto &sigma : sigmas)
129  {
130  Test_HC_CC_State_Space hc_cc_ss(KAPPA, sigma, DISCRETIZATION);
131  HC_CC_Circle_Param hc_cc_circle_param = hc_cc_ss.get_hc_cc_circle_param();
132 
133  HC_CC_Circle reg_hc_cc_circle = HC_CC_Circle(start_config, true, true, true, hc_cc_circle_param);
134  HC_CC_Circle irreg_hc_cc_circle = HC_CC_Circle(start_config, true, true, false, hc_cc_circle_param);
135 
136  for (const auto &delta : deltas)
137  {
138  // cc-turn
139  Configuration cc_goal_config = get_cc_goal_config(delta, hc_cc_circle_param);
140 
141  // regular cc-turn
142  vector<Control> reg_cc_controls;
143  cc_turn_controls(reg_hc_cc_circle, cc_goal_config, true, reg_cc_controls);
144  vector<State> reg_cc_path = hc_cc_ss.integrate(start_state, reg_cc_controls);
145  double reg_cc_path_length =
146  accumulate(reg_cc_controls.begin(), reg_cc_controls.end(), 0.0,
147  [](double sum, const Control &control) { return sum + fabs(control.delta_s); });
148  EXPECT_LT(fabs(reg_cc_path_length - get_path_length(reg_cc_path)), EPS_DISTANCE);
149 
150  // irregular cc-turn
151  vector<Control> irreg_cc_controls;
152  cc_turn_controls(irreg_hc_cc_circle, cc_goal_config, true, irreg_cc_controls);
153  vector<State> irreg_cc_path = hc_cc_ss.integrate(start_state, irreg_cc_controls);
154  double irreg_cc_path_length =
155  accumulate(irreg_cc_controls.begin(), irreg_cc_controls.end(), 0.0,
156  [](double sum, const Control &control) { return sum + fabs(control.delta_s); });
157  EXPECT_LT(fabs(irreg_cc_path_length - get_path_length(irreg_cc_path)), EPS_DISTANCE);
158 
159  // hc-turn
160  Configuration hc_goal_config = get_hc_goal_config(delta, hc_cc_circle_param);
161 
162  // regular hc-turn
163  vector<Control> reg_hc_controls;
164  hc_turn_controls(reg_hc_cc_circle, hc_goal_config, true, reg_hc_controls);
165  vector<State> reg_hc_path = hc_cc_ss.integrate(start_state, reg_hc_controls);
166  double reg_hc_path_length =
167  accumulate(reg_hc_controls.begin(), reg_hc_controls.end(), 0.0,
168  [](double sum, const Control &control) { return sum + fabs(control.delta_s); });
169  EXPECT_LT(fabs(reg_hc_path_length - get_path_length(reg_hc_path)), EPS_DISTANCE);
170 
171  // irregular hc-turn
172  vector<Control> irreg_hc_controls;
173  hc_turn_controls(irreg_hc_cc_circle, hc_goal_config, true, irreg_hc_controls);
174  vector<State> irreg_hc_path = hc_cc_ss.integrate(start_state, irreg_hc_controls);
175  double irreg_hc_path_length =
176  accumulate(irreg_hc_controls.begin(), irreg_hc_controls.end(), 0.0,
177  [](double sum, const Control &control) { return sum + fabs(control.delta_s); });
178  EXPECT_LT(fabs(irreg_hc_path_length - get_path_length(irreg_hc_path)), EPS_DISTANCE);
179  }
180  }
181 }
182 
183 TEST(HC_CC_Circle, reachingGoal)
184 {
185  State start_state;
186  start_state.x = start_config.x;
187  start_state.y = start_config.y;
188  start_state.theta = start_config.theta;
189  start_state.kappa = start_config.kappa;
190  start_state.d = 0.0;
191 
192  for (const auto &sigma : sigmas)
193  {
194  Test_HC_CC_State_Space hc_cc_ss(KAPPA, sigma, DISCRETIZATION);
195  HC_CC_Circle_Param hc_cc_circle_param = hc_cc_ss.get_hc_cc_circle_param();
196 
197  HC_CC_Circle reg_hc_cc_circle = HC_CC_Circle(start_config, true, true, true, hc_cc_circle_param);
198  HC_CC_Circle irreg_hc_cc_circle = HC_CC_Circle(start_config, true, true, false, hc_cc_circle_param);
199 
200  for (const auto &delta : deltas)
201  {
202  // cc-turn
203  Configuration cc_goal_config = get_cc_goal_config(delta, hc_cc_circle_param);
204  State cc_goal_state;
205  cc_goal_state.x = cc_goal_config.x;
206  cc_goal_state.y = cc_goal_config.y;
207  cc_goal_state.theta = cc_goal_config.theta;
208  cc_goal_state.kappa = cc_goal_config.kappa;
209  cc_goal_state.d = 0.0;
210 
211  // regular cc-turn
212  vector<Control> reg_cc_controls;
213  cc_turn_controls(reg_hc_cc_circle, cc_goal_config, true, reg_cc_controls);
214  vector<State> reg_cc_path = hc_cc_ss.integrate(start_state, reg_cc_controls);
215  EXPECT_LT(get_distance(cc_goal_state, reg_cc_path.back()), EPS_DISTANCE);
216 
217  // irregular cc-turn
218  vector<Control> irreg_cc_controls;
219  cc_turn_controls(irreg_hc_cc_circle, cc_goal_config, true, irreg_cc_controls);
220  vector<State> irreg_cc_path = hc_cc_ss.integrate(start_state, irreg_cc_controls);
221  EXPECT_LT(get_distance(cc_goal_state, irreg_cc_path.back()), EPS_DISTANCE);
222 
223  // hc-turn
224  Configuration hc_goal_config = get_hc_goal_config(delta, hc_cc_circle_param);
225  State hc_goal_state;
226  hc_goal_state.x = hc_goal_config.x;
227  hc_goal_state.y = hc_goal_config.y;
228  hc_goal_state.theta = hc_goal_config.theta;
229  hc_goal_state.kappa = hc_goal_config.kappa;
230  hc_goal_state.d = 0.0;
231 
232  // regular hc-turn
233  vector<Control> reg_hc_controls;
234  hc_turn_controls(reg_hc_cc_circle, hc_goal_config, true, reg_hc_controls);
235  vector<State> reg_hc_path = hc_cc_ss.integrate(start_state, reg_hc_controls);
236  EXPECT_LT(get_distance(hc_goal_state, reg_hc_path.back()), EPS_DISTANCE);
237 
238  // irregular hc-turn
239  vector<Control> irreg_hc_controls;
240  hc_turn_controls(irreg_hc_cc_circle, hc_goal_config, true, irreg_hc_controls);
241  vector<State> irreg_hc_path = hc_cc_ss.integrate(start_state, irreg_hc_controls);
242  EXPECT_LT(get_distance(hc_goal_state, irreg_hc_path.back()), EPS_DISTANCE);
243  }
244  }
245 }
246 
247 TEST(HC_CC_Circle, maxSharpness)
248 {
249  for (const auto &sigma : sigmas)
250  {
251  Test_HC_CC_State_Space hc_cc_ss(KAPPA, sigma, DISCRETIZATION);
252  HC_CC_Circle_Param hc_cc_circle_param = hc_cc_ss.get_hc_cc_circle_param();
253  HC_CC_Circle hc_cc_circle = HC_CC_Circle(start_config, true, true, true, hc_cc_circle_param);
254 
255  for (const auto &delta : deltas)
256  {
257  // cc-turn
258  Configuration goal_config = get_cc_goal_config(delta, hc_cc_circle_param);
259  State goal_state;
260  goal_state.x = goal_config.x;
261  goal_state.y = goal_config.y;
262  goal_state.theta = goal_config.theta;
263  goal_state.kappa = goal_config.kappa;
264  goal_state.d = 0.0;
265 
266  vector<Control> cc_controls;
267  cc_turn_controls(hc_cc_circle, goal_config, true, cc_controls);
268  for (const auto &cc_control : cc_controls)
269  EXPECT_LT(fabs(cc_control.sigma), sigma + EPS_SIGMA);
270  }
271  }
272 }
273 
274 TEST(HC_CC_Circle, maxCurvature)
275 {
276  State start_state;
277  start_state.x = start_config.x;
278  start_state.y = start_config.y;
279  start_state.theta = start_config.theta;
280  start_state.kappa = start_config.kappa;
281  start_state.d = 0.0;
282 
283  for (const auto &sigma : sigmas)
284  {
285  Test_HC_CC_State_Space hc_cc_ss(KAPPA, sigma, DISCRETIZATION);
286  HC_CC_Circle_Param hc_cc_circle_param = hc_cc_ss.get_hc_cc_circle_param();
287  HC_CC_Circle hc_cc_circle = HC_CC_Circle(start_config, true, true, true, hc_cc_circle_param);
288 
289  for (const auto &delta : deltas)
290  {
291  // cc-turn
292  Configuration goal_config = get_cc_goal_config(delta, hc_cc_circle_param);
293  State goal_state;
294  goal_state.x = goal_config.x;
295  goal_state.y = goal_config.y;
296  goal_state.theta = goal_config.theta;
297  goal_state.kappa = goal_config.kappa;
298  goal_state.d = 0.0;
299 
300  vector<Control> cc_controls;
301  cc_turn_controls(hc_cc_circle, goal_config, true, cc_controls);
302  vector<State> cc_path = hc_cc_ss.integrate(start_state, cc_controls);
303  for (const auto &state : cc_path)
304  EXPECT_LT(fabs(state.kappa), KAPPA + EPS_KAPPA);
305  }
306  }
307 }
308 
309 int main(int argc, char **argv)
310 {
311  testing::InitGoogleTest(&argc, argv);
312  return RUN_ALL_TESTS();
313 }
get_cc_goal_config
Configuration get_cc_goal_config(double delta, const HC_CC_Circle_Param &hc_cc_circle_param)
Definition: hc_cc_circle_test.cpp:55
hc_cc_state_space.hpp
Test_HC_CC_State_Space::Test_HC_CC_State_Space
Test_HC_CC_State_Space(double kappa, double sigma, double discretization)
Definition: hc_cc_circle_test.cpp:39
steering::State
Description of a kinematic car's state.
Definition: steering_functions.hpp:44
steering::HC_CC_Circle_Param
Definition: hc_cc_circle.hpp:57
plot_states.path
path
Definition: plot_states.py:88
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
steering::State::theta
double theta
Orientation of the robot.
Definition: steering_functions.hpp:70
configuration.hpp
DISCRETIZATION
#define DISCRETIZATION
Definition: hc_cc_circle_test.cpp:31
steering::State::kappa
double kappa
Curvature at position (x,y)
Definition: steering_functions.hpp:73
steering::HC_CC_State_Space::integrate
std::vector< State > integrate(const State &state, const std::vector< Control > &controls) const
Returns integrated states given a start state and controls.
Definition: hc_cc_state_space.cpp:81
step
unsigned int step
EPS_KAPPA
#define EPS_KAPPA
Definition: hc_cc_circle_test.cpp:28
steering::HC_CC_Circle
Definition: hc_cc_circle.hpp:80
steering::State::y
double y
Position in y of the robot.
Definition: steering_functions.hpp:67
paths.hpp
steering::Control
Description of a path segment with its corresponding control inputs.
Definition: steering_functions.hpp:82
steering::Configuration::kappa
double kappa
Curvature.
Definition: configuration.hpp:94
get_distance
double get_distance(const State &state1, const State &state2)
Definition: hc_cc_circle_test.cpp:98
KAPPA
#define KAPPA
Definition: hc_cc_circle_test.cpp:30
hc_cc_circle.hpp
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.
deltas
vector< double > deltas
Definition: hc_cc_circle_test.cpp:117
steering::State::x
double x
Position in x of the robot.
Definition: steering_functions.hpp:64
Test_HC_CC_State_Space::get_controls
vector< Control > get_controls(const State &state1, const State &state2) const
Virtual function that returns controls of the shortest path from state1 to state2.
Definition: hc_cc_circle_test.cpp:44
start_config
Configuration start_config(0.0, 0.0, 0.0, 0.0)
EPS_DISTANCE
#define EPS_DISTANCE
Definition: hc_cc_circle_test.cpp:27
get_linear_samples
vector< double > get_linear_samples(double start, double stop, size_t num)
Definition: hc_cc_circle_test.cpp:88
steering::HC_CC_State_Space
Definition: hc_cc_state_space.hpp:45
sigmas
vector< double > sigmas
Definition: hc_cc_circle_test.cpp:116
steering::Configuration
Definition: configuration.hpp:55
start
ROSCPP_DECL void start()
Test_HC_CC_State_Space::get_hc_cc_circle_param
HC_CC_Circle_Param get_hc_cc_circle_param()
Definition: hc_cc_circle_test.cpp:49
std
steering::HC_CC_Circle_Param::kappa
double kappa
Max. curvature, inverse of max. curvature, max. sharpness.
Definition: hc_cc_circle.hpp:88
steering_functions.hpp
plot_states.kappa
kappa
Definition: plot_states.py:106
TEST
TEST(HC_CC_Circle, pathLength)
Definition: hc_cc_circle_test.cpp:119
EPS_SIGMA
#define EPS_SIGMA
Definition: hc_cc_circle_test.cpp:29
steering
Definition: dubins_state_space.hpp:70
Test_HC_CC_State_Space
Definition: hc_cc_circle_test.cpp:36
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::State::d
double d
Definition: steering_functions.hpp:76
steering::Configuration::y
double y
Definition: configuration.hpp:88
get_hc_goal_config
Configuration get_hc_goal_config(double delta, const HC_CC_Circle_Param &hc_cc_circle_param)
Definition: hc_cc_circle_test.cpp:71
steering::HC_CC_Circle_Param::radius
double radius
Radius of the outer circle.
Definition: hc_cc_circle.hpp:91
steering::Configuration::x
double x
Position.
Definition: configuration.hpp:88
main
int main(int argc, char **argv)
Definition: hc_cc_circle_test.cpp:309
utilities.hpp
steering::Configuration::theta
double theta
Orientation in rad between [0, 2*pi[.
Definition: configuration.hpp:91
get_path_length
double get_path_length(const vector< State > &path)
Definition: hc_cc_circle_test.cpp:103


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