Bench-MR
A Motion Planning Benchmark for Wheeled Mobile Robots
POSQ.hpp
Go to the documentation of this file.
1/*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2014, Social Robotics Laboratory, University of Freiburg.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of the Willow Garage nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *********************************************************************/
34
35/* Author: Luigi Palmieri */
36
37#pragma once
38#include <ompl/base/spaces/SE2StateSpace.h>
39
40#include "../../base/PlannerSettings.h"
41
42using namespace std;
45namespace ob = ompl::base;
46
49 // pose
50 double x_;
51 double y_;
52 double yaw_;
53
55 x_ = 0.0;
56 y_ = 0.0;
57 yaw_ = 0.0;
58 }
59
60 UnicycleState(double xx, double yy, double zz) : x_(xx), y_(yy), yaw_(zz) {}
61
62 UnicycleState(double *p) {
63 x_ = p[0];
64 y_ = p[1];
65 yaw_ = p[2];
66 }
67
69 x_ = copy.x_;
70 y_ = copy.y_;
71 yaw_ = copy.yaw_;
72 return *this;
73 }
74
76 x_ = copy.x_;
77 y_ = copy.y_;
78 yaw_ = copy.yaw_;
79 }
80
82};
83
86 // v, translational velocity
87 double v_;
88 // w, rotational velocity
89 double w_;
90
91 UnicycleControl(double vv = 0, double ww = 0) : v_(vv), w_(ww) {}
92
93 UnicycleControl(const double *p) {
94 v_ = p[0];
95 w_ = p[1];
96 }
97
98 UnicycleControl &operator=(UnicycleControl const &copy) = default;
99
101 v_ = copy.v_;
102 w_ = copy.w_;
103 }
104
105 virtual ~UnicycleControl() = default;
106};
107
109class POSQ {
110 public:
112 double B{.54};
113
115 double DT{0.1};
116
119 const int MAX_SIZE = 10001;
120
122 const double END_CONTROLS = 2000;
123
125 double *result_;
126 double *intRes_;
127
129 int *ind_;
130
132
133 ompl::base::StateSpacePtr space_;
134
136 space_ = std::make_shared<ompl::base::SE2StateSpace>();
137 result_ = (double *)malloc(sizeof(double) * 5);
138 intRes_ = (double *)malloc(sizeof(double) * 5);
139 ind_ = (int *)malloc(sizeof(int) * 1);
140
141 // Kalpha = 2.5; //6.91;
142 // Kbeta = -3;
143 // /** Read the paper and see how to set the proper gain values
144 //
145 // double Kphi;
146 // Kphi = -1;
147 // **/
148 // Krho = 25.2; //15.5; //0.2;
149 // Kv = 0.2; //13.8;// .2; //0.01; //global::settings.Kv;
150 //
151 // Vmax = Krho;
152 // RhoEndCondition = 0.015; //global::settings.rhoEndcondition;
153
154 Kalpha = 6.91;
155 Kbeta = -1;
161 Krho = 2; // 15.5; //0.2;
162 Kv = 1.2; // 13.8;// .2; //0.01; //global::settings.Kv;
163
164 Vmax = Krho;
165 RhoEndCondition = 0.1; // global::settings.rhoEndcondition;
166
168 // Luigi's values:
170 Kalpha = 3;
171 Kbeta = -1;
177 Krho = 1.2;
178 Kv = 1;
179 Vmax = 2000; // Krho;
180
182 // Configured values:
192 OMPL_INFORM(
193 "POSQ settings: Kalpha %f, Kbeta %f, Krho %f, RhoEndCondition %f, Kv %f, Vmax "
194 "%f, DT %f, B %f",
196 }
197
199 void setRes(const double *r) const {
200 this->intRes_[0] = r[0];
201 this->intRes_[1] = r[1];
202 this->intRes_[2] = r[2];
203 this->intRes_[3] = r[3];
204 this->intRes_[4] = r[4];
205 }
206
211 double normAngle(double a, double mina) const {
212 double ap, minap;
213 ap = a;
214 minap = mina;
215
216 while (ap >= (minap + M_PI * 2)) {
217 ap = ap - M_PI * 2;
218 }
219
220 while (ap < minap) {
221 ap = ap + M_PI * 2;
222 }
223
224 return ap;
225 }
226
238 double *posControlStep(double x_c, double y_c, double t_c, double x_end,
239 double y_end, double t_end, double ct, double b,
240 int dir, int &eot) const {
248 static double oldBeta;
249 //
250 // double Krho, Kalpha, Kbeta, Kv, Vmax, RhoEndCondition;
251 //
252 // Kalpha = 18; //6.91;
253 // Kbeta = -5;
254 // /** Read the paper and see how to set the proper gain values
255 //
256 // double Kphi;
257 // Kphi = -1;
258 // **/
259 // Krho = 0.2; //15.5; //0.2;
260 // Kv = 0.2; //13.8;// .2; //0.01; //global::settings.Kv;
261 //
262 // Vmax = Krho;
263 // RhoEndCondition = 0.15; //global::settings.rhoEndcondition;
264
265 if (Kalpha + Kbeta - Krho * Kv <= 0)
266 std::cerr << "K_alpha + K_phi - K_rho K_v = "
267 << Kalpha + Kbeta - Krho * Kv << std::endl;
268 if (Kalpha + 2 * Kbeta - 2 / M_PI * Krho * Kv <= 0)
269 std::cerr << "K_alpha + 2 K_phi - 2/pi K_rho K_v = "
270 << Kalpha + 2 * Kbeta - 2 / M_PI * Krho * Kv << std::endl;
271
272 if (ct == 0) oldBeta = 0;
273
274 double dx, dy, rho, fRho, alpha, phi, beta, v, w, vl, vr;
275
276 // rho
277 eot = 1;
278 dx = x_end - x_c;
279 dy = y_end - y_c;
280 rho = sqrt(dx * dx + dy * dy);
281 fRho = rho;
282
283 if (fRho > (Vmax / Krho)) fRho = Vmax / Krho;
284
285 // alpha
286 alpha = atan2(dy, dx) - t_c;
287 alpha = normAngle(alpha, -M_PI);
288
289 // direction
290 if (dir == 1) {
291 if (alpha > (M_PI / 2)) {
292 fRho = -fRho;
293 alpha = alpha - M_PI;
294 } else if (alpha <= -M_PI / 2) {
295 fRho = -fRho;
296 alpha = alpha + M_PI;
297 }
298 } else if (dir == -1) {
299 fRho = -fRho;
300 alpha = alpha + M_PI;
301
302 if (alpha > M_PI) {
303 alpha = alpha - 2 * M_PI;
304 }
305 }
306
307 // phi
308 phi = t_end - t_c;
309 phi = normAngle(phi, -M_PI);
310 beta = normAngle(phi - alpha, -M_PI);
311
312 if ((abs(oldBeta - beta) > M_PI)) beta = oldBeta;
313
314 oldBeta = beta;
315
316 // set speed
317 v = Krho * tanh(Kv * fRho);
318 w = Kalpha * alpha + Kbeta * beta;
319
320 eot = (int)rho < RhoEndCondition;
321
322 if (eot) w = 0.;
323
324 // Convert speed to wheel speed
325 vl = v - w * b / 2;
326 if (abs(vl) > Vmax) {
327 if (vl < 0)
328 vl = Vmax * -1;
329 else
330 vl = Vmax;
331 }
332
333 vr = v + w * b / 2;
334 if (abs(vr) > Vmax) {
335 if (vr < 0)
336 vr = Vmax * -1;
337 else
338 vr = Vmax;
339 }
340
341 result_[0] = vl;
342 result_[1] = vr;
343 result_[2] = (vl + vr) / 2;
344 result_[3] = (vr - vl) / b;
345 result_[4] = (int)eot;
346
347 return result_;
348 }
349
356 std::vector<UnicycleState> steer(const ob::State *from, const ob::State *to,
357 double &distance) const {
358 double sl, sr, oldSl, oldSr, t, dSl, dSr, dSm, dSd, vl, vr, enc_l, enc_r,
359 dir;
360 int eot;
361 dir = 1;
362 enc_l = 0;
363 enc_r = 0;
364 sl = 0;
365 sr = 0;
366 oldSl = 0;
367 oldSr = 0;
368 eot = 0;
369 t = 0;
370 vl = 0;
371 vr = 0;
372 distance = 0;
373 double x, y, th;
374 double x_fin, y_fin, th_fin;
375
376 x = from->as<ob::SE2StateSpace::StateType>()->getX();
377 y = from->as<ob::SE2StateSpace::StateType>()->getY();
378 th = from->as<ob::SE2StateSpace::StateType>()->getYaw();
379
380 x_fin = to->as<ob::SE2StateSpace::StateType>()->getX();
381 y_fin = to->as<ob::SE2StateSpace::StateType>()->getY();
382 th_fin = to->as<ob::SE2StateSpace::StateType>()->getYaw();
383
384 double vv, ww;
385 vv = 0;
386 ww = 0;
387
388 std::vector<UnicycleControl> controls;
389 std::vector<UnicycleState> states;
390 controls.clear();
391 states.clear();
392
393 int n_steps;
394 n_steps = 0;
395 while (eot == 0) {
396 // calculate distance for both wheels
397 dSl = sl - oldSl;
398 dSr = sr - oldSr;
399 dSm = (dSl + dSr) / 2;
400 dSd = (dSr - dSl) / B;
401 x = x + dSm * cos(th + dSd / 2);
402 y = y + dSm * sin(th + dSd / 2);
403 th = normAngle(th + dSd, -M_PI);
404 // intRes= posControlStep (x,y,th,x_fin,y_fin,th_fin, t,b,dir);
405 setRes(posControlStep(x, y, th, x_fin, y_fin, th_fin, t, B, dir, eot));
406 // Save the velocity commands,eot
407 vv = intRes_[2];
408 ww = intRes_[3];
409 // eot = intRes_[4];
410 vl = intRes_[0];
411 vr = intRes_[1];
412 // Increase the timer
413 t = t + DT;
414 // Count the number of steps
415 n_steps++;
416 // keep track of previous wheel position
417 oldSl = sl;
418 oldSr = sr;
419 // increase encoder values
420 enc_l = enc_l + DT * vl;
421 enc_r = enc_r + DT * vr;
422 sl = enc_l;
423 sr = enc_r;
424 if (eot == 1) {
425 // Add current values to the Trajectory
426 states.push_back(UnicycleState(x, y, th));
427 controls.push_back(UnicycleControl(vv, ww));
428
429 // save the last state!!!
430 double xf, yf, yawf, vf, wf;
431
432 vf = intRes_[2];
433 wf = intRes_[3];
434 dSl = sl - oldSl;
435 dSr = sr - oldSr;
436 dSm = (dSl + dSr) / 2;
437 dSd = (dSr - dSl) / B;
438 double dx = dSm * cos(th + dSd / 2);
439 double dy = dSm * sin(th + dSd / 2);
440 xf = x + dx;
441 yf = y + dy;
442 yawf = normAngle(th + dSd, -M_PI);
443 distance += sqrt(dx * dx + dy * dy);
444 states.push_back(UnicycleState(xf, yf, yawf));
445 controls.push_back(UnicycleControl(vf, wf));
446 } else {
447 // Add current values to the Trajectory
449 s.x_ = x;
450 s.y_ = y;
451 s.yaw_ = th;
452 states.push_back(s);
453
455 c.v_ = vv;
456 c.w_ = ww;
457 controls.push_back(c);
458 }
459 }
460
461 return states;
462 }
463
465 double distance(const ompl::base::State *state1,
466 const ompl::base::State *state2) {
467 double distance = 0;
468 steer(state1, state2, distance);
469 return distance;
470 }
471
474 std::vector<UnicycleState> states, const double t) {
475 // returning the state at time t;
476 int n_states = states.size();
477 int index_state_at_t_time = int(double(n_states) * t);
478 return states[index_state_at_t_time];
479 }
480};
ob::SE2StateSpace::StateType State
Definition: Primitives.h:12
POSQ class that implements the POSQ steering function.
Definition: POSQ.hpp:109
void setRes(const double *r) const
Set the current result of the integration.
Definition: POSQ.hpp:199
double RhoEndCondition
Definition: POSQ.hpp:131
double Kv
Definition: POSQ.hpp:131
UnicycleState interpolate(const ompl::base::State *from, std::vector< UnicycleState > states, const double t)
Return state at time t.
Definition: POSQ.hpp:473
double B
length of the wheels axis
Definition: POSQ.hpp:112
POSQ()
Definition: POSQ.hpp:135
ompl::base::StateSpacePtr space_
Definition: POSQ.hpp:133
std::vector< UnicycleState > steer(const ob::State *from, const ob::State *to, double &distance) const
Propagate the model of the system forward, starting at a given state, with a given control,...
Definition: POSQ.hpp:356
double * intRes_
Definition: POSQ.hpp:126
double Kalpha
Definition: POSQ.hpp:131
const int MAX_SIZE
Max Size of the Control (HacK: in this case equal to the dimension)
Definition: POSQ.hpp:119
double * result_
Internal Results of the integration.
Definition: POSQ.hpp:125
double DT
Integration Time Step
Definition: POSQ.hpp:115
const double END_CONTROLS
Value used to mark the end of the vector, no used at the moment.
Definition: POSQ.hpp:122
double Vmax
Definition: POSQ.hpp:131
double distance(const ompl::base::State *state1, const ompl::base::State *state2)
Compute the distance between two states.
Definition: POSQ.hpp:465
double Krho
Definition: POSQ.hpp:131
double * posControlStep(double x_c, double y_c, double t_c, double x_end, double y_end, double t_end, double ct, double b, int dir, int &eot) const
Single step of the Steer Function.
Definition: POSQ.hpp:238
double Kbeta
Definition: POSQ.hpp:131
int * ind_
Internal Counter to access the current control to propagate.
Definition: POSQ.hpp:129
double normAngle(double a, double mina) const
Normalize the angle a rispect to the minimum angle mina.
Definition: POSQ.hpp:211
double std(const std::vector< double > &values)
Definition: PathStatistics.hpp:85
Property< double > v
Definition: PlannerSettings.h:516
Property< double > rho
Definition: PlannerSettings.h:514
Property< double > dt
Integration time step.
Definition: PlannerSettings.h:527
Property< double > v_max
Definition: PlannerSettings.h:517
Property< double > axis_length
Length of the wheel axis.
Definition: PlannerSettings.h:522
Property< double > phi
Definition: PlannerSettings.h:513
Property< double > alpha
Definition: PlannerSettings.h:512
Property< double > rho_end_condition
Definition: PlannerSettings.h:515
PlannerSettings::GlobalSettings::SteerSettings::PosqSettings posq
PlannerSettings::GlobalSettings::SteerSettings steer
Internal definition of the Unicycle control type.
Definition: POSQ.hpp:85
UnicycleControl(double vv=0, double ww=0)
Definition: POSQ.hpp:91
UnicycleControl(const UnicycleControl &copy)
Definition: POSQ.hpp:100
virtual ~UnicycleControl()=default
UnicycleControl(const double *p)
Definition: POSQ.hpp:93
double v_
Definition: POSQ.hpp:87
UnicycleControl & operator=(UnicycleControl const &copy)=default
double w_
Definition: POSQ.hpp:89
Definition of the namespaces.
Definition: POSQ.hpp:48
UnicycleState & operator=(UnicycleState const &copy)
Definition: POSQ.hpp:68
double yaw_
Definition: POSQ.hpp:52
~UnicycleState(void)
Definition: POSQ.hpp:81
UnicycleState(double xx, double yy, double zz)
Definition: POSQ.hpp:60
UnicycleState()
Definition: POSQ.hpp:54
UnicycleState(double *p)
Definition: POSQ.hpp:62
double y_
Definition: POSQ.hpp:51
double x_
Definition: POSQ.hpp:50
UnicycleState(const UnicycleState &copy)
Definition: POSQ.hpp:75
static PlannerSettings::GlobalSettings settings
Definition: PlannerSettings.h:699