Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <global_planner/gradient_path.h>
00039 #include <algorithm>
00040 #include <stdio.h>
00041 #include <global_planner/planner_core.h>
00042
00043 namespace global_planner {
00044
00045 GradientPath::GradientPath(PotentialCalculator* p_calc) :
00046 Traceback(p_calc), pathStep_(0.5) {
00047 gradx_ = grady_ = NULL;
00048 }
00049
00050 GradientPath::~GradientPath() {
00051
00052 if (gradx_)
00053 delete[] gradx_;
00054 if (grady_)
00055 delete[] grady_;
00056 }
00057
00058 void GradientPath::setSize(int xs, int ys) {
00059 Traceback::setSize(xs, ys);
00060 if (gradx_)
00061 delete[] gradx_;
00062 if (grady_)
00063 delete[] grady_;
00064 gradx_ = new float[xs * ys];
00065 grady_ = new float[xs * ys];
00066 }
00067
00068 bool GradientPath::getPath(float* potential, double start_x, double start_y, double goal_x, double goal_y, std::vector<std::pair<float, float> >& path) {
00069 std::pair<float, float> current;
00070 int stc = getIndex(goal_x, goal_y);
00071
00072
00073 float dx = goal_x - (int)goal_x;
00074 float dy = goal_y - (int)goal_y;
00075 int ns = xs_ * ys_;
00076 memset(gradx_, 0, ns * sizeof(float));
00077 memset(grady_, 0, ns * sizeof(float));
00078
00079 int c = 0;
00080 while (c++<ns*4) {
00081
00082 double nx = stc % xs_ + dx, ny = stc / xs_ + dy;
00083
00084 if (fabs(nx - start_x) < .5 && fabs(ny - start_y) < .5) {
00085 current.first = start_x;
00086 current.second = start_y;
00087 path.push_back(current);
00088 return true;
00089 }
00090
00091 if (stc < xs_ || stc > xs_ * ys_ - xs_)
00092 {
00093 printf("[PathCalc] Out of bounds\n");
00094 return false;
00095 }
00096
00097 current.first = nx;
00098 current.second = ny;
00099
00100
00101
00102 path.push_back(current);
00103
00104 bool oscillation_detected = false;
00105 int npath = path.size();
00106 if (npath > 2 && path[npath - 1].first == path[npath - 3].first
00107 && path[npath - 1].second == path[npath - 3].second) {
00108 ROS_DEBUG("[PathCalc] oscillation detected, attempting fix.");
00109 oscillation_detected = true;
00110 }
00111
00112 int stcnx = stc + xs_;
00113 int stcpx = stc - xs_;
00114
00115
00116 if (potential[stc] >= POT_HIGH || potential[stc + 1] >= POT_HIGH || potential[stc - 1] >= POT_HIGH
00117 || potential[stcnx] >= POT_HIGH || potential[stcnx + 1] >= POT_HIGH || potential[stcnx - 1] >= POT_HIGH
00118 || potential[stcpx] >= POT_HIGH || potential[stcpx + 1] >= POT_HIGH || potential[stcpx - 1] >= POT_HIGH
00119 || oscillation_detected) {
00120 ROS_DEBUG("[Path] Pot fn boundary, following grid (%0.1f/%d)", potential[stc], (int) path.size());
00121
00122 int minc = stc;
00123 int minp = potential[stc];
00124 int st = stcpx - 1;
00125 if (potential[st] < minp) {
00126 minp = potential[st];
00127 minc = st;
00128 }
00129 st++;
00130 if (potential[st] < minp) {
00131 minp = potential[st];
00132 minc = st;
00133 }
00134 st++;
00135 if (potential[st] < minp) {
00136 minp = potential[st];
00137 minc = st;
00138 }
00139 st = stc - 1;
00140 if (potential[st] < minp) {
00141 minp = potential[st];
00142 minc = st;
00143 }
00144 st = stc + 1;
00145 if (potential[st] < minp) {
00146 minp = potential[st];
00147 minc = st;
00148 }
00149 st = stcnx - 1;
00150 if (potential[st] < minp) {
00151 minp = potential[st];
00152 minc = st;
00153 }
00154 st++;
00155 if (potential[st] < minp) {
00156 minp = potential[st];
00157 minc = st;
00158 }
00159 st++;
00160 if (potential[st] < minp) {
00161 minp = potential[st];
00162 minc = st;
00163 }
00164 stc = minc;
00165 dx = 0;
00166 dy = 0;
00167
00168
00169
00170
00171 if (potential[stc] >= POT_HIGH) {
00172 ROS_DEBUG("[PathCalc] No path found, high potential");
00173
00174 return 0;
00175 }
00176 }
00177
00178
00179 else {
00180
00181
00182 gradCell(potential, stc);
00183 gradCell(potential, stc + 1);
00184 gradCell(potential, stcnx);
00185 gradCell(potential, stcnx + 1);
00186
00187
00188 float x1 = (1.0 - dx) * gradx_[stc] + dx * gradx_[stc + 1];
00189 float x2 = (1.0 - dx) * gradx_[stcnx] + dx * gradx_[stcnx + 1];
00190 float x = (1.0 - dy) * x1 + dy * x2;
00191 float y1 = (1.0 - dx) * grady_[stc] + dx * grady_[stc + 1];
00192 float y2 = (1.0 - dx) * grady_[stcnx] + dx * grady_[stcnx + 1];
00193 float y = (1.0 - dy) * y1 + dy * y2;
00194
00195
00196 ROS_DEBUG(
00197 "[Path] %0.2f,%0.2f %0.2f,%0.2f %0.2f,%0.2f %0.2f,%0.2f; final x=%.3f, y=%.3f\n", gradx_[stc], grady_[stc], gradx_[stc+1], grady_[stc+1], gradx_[stcnx], grady_[stcnx], gradx_[stcnx+1], grady_[stcnx+1], x, y);
00198
00199
00200 if (x == 0.0 && y == 0.0) {
00201 ROS_DEBUG("[PathCalc] Zero gradient");
00202 return 0;
00203 }
00204
00205
00206 float ss = pathStep_ / hypot(x, y);
00207 dx += x * ss;
00208 dy += y * ss;
00209
00210
00211 if (dx > 1.0) {
00212 stc++;
00213 dx -= 1.0;
00214 }
00215 if (dx < -1.0) {
00216 stc--;
00217 dx += 1.0;
00218 }
00219 if (dy > 1.0) {
00220 stc += xs_;
00221 dy -= 1.0;
00222 }
00223 if (dy < -1.0) {
00224 stc -= xs_;
00225 dy += 1.0;
00226 }
00227
00228 }
00229
00230
00231
00232 }
00233
00234 return false;
00235 }
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266 float GradientPath::gradCell(float* potential, int n) {
00267 if (gradx_[n] + grady_[n] > 0.0)
00268 return 1.0;
00269
00270 if (n < xs_ || n > xs_ * ys_ - xs_)
00271 return 0.0;
00272 float cv = potential[n];
00273 float dx = 0.0;
00274 float dy = 0.0;
00275
00276
00277 if (cv >= POT_HIGH) {
00278 if (potential[n - 1] < POT_HIGH)
00279 dx = -lethal_cost_;
00280 else if (potential[n + 1] < POT_HIGH)
00281 dx = lethal_cost_;
00282
00283 if (potential[n - xs_] < POT_HIGH)
00284 dy = -lethal_cost_;
00285 else if (potential[xs_ + 1] < POT_HIGH)
00286 dy = lethal_cost_;
00287 }
00288
00289 else
00290 {
00291
00292 if (potential[n - 1] < POT_HIGH)
00293 dx += potential[n - 1] - cv;
00294 if (potential[n + 1] < POT_HIGH)
00295 dx += cv - potential[n + 1];
00296
00297
00298 if (potential[n - xs_] < POT_HIGH)
00299 dy += potential[n - xs_] - cv;
00300 if (potential[n + xs_] < POT_HIGH)
00301 dy += cv - potential[n + xs_];
00302 }
00303
00304
00305 float norm = hypot(dx, dy);
00306 if (norm > 0) {
00307 norm = 1.0 / norm;
00308 gradx_[n] = norm * dx;
00309 grady_[n] = norm * dy;
00310 }
00311 return norm;
00312 }
00313
00314 }
00315