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
00032 #include <sbpl_arm_planner/bfs_3d.h>
00033
00034
00035 BFS3D::BFS3D(int dim_x, int dim_y, int dim_z, int radius, int cost_per_cell)
00036 {
00037 if(dim_x < 0 || dim_y < 0 || dim_z < 0)
00038 SBPL_ERROR("Dimensions must have positive values. Fix this.\n");
00039
00040 grid3D_ = NULL;
00041 df_ = NULL;
00042
00043 dimX_ = dim_x;
00044 dimY_ = dim_y;
00045 dimZ_ = dim_z;
00046 radius_ = radius;
00047
00048 cost_1_move_ = cost_per_cell;
00049 cost_sqrt2_move_ = cost_per_cell*sqrt(2.0);
00050 cost_sqrt3_move_ = cost_per_cell*sqrt(3.0);
00051
00052 enable_df_ = false;
00053 radius_m_ = 0.1;
00054
00055 SBPL_DEBUG("goal bounds: %d %d %d\n",dimX_, dimY_,dimZ_);
00056 }
00057
00058 BFS3D::~BFS3D()
00059 {
00060 if (grid3D_ != NULL)
00061 {
00062 for (short unsigned int x = 0; x < dimX_; x++)
00063 {
00064 for (short unsigned int y = 0; y < dimY_; y++)
00065 delete [] grid3D_[x][y];
00066 delete [] grid3D_[x];
00067 }
00068 delete [] grid3D_;
00069 grid3D_ = NULL;
00070 }
00071 }
00072
00073 void BFS3D::init()
00074 {
00075 short unsigned int x,y,z;
00076 grid3D_ = new unsigned char** [dimX_];
00077 for (x = 0; x < dimX_; x++)
00078 {
00079 grid3D_[x] = new unsigned char* [dimY_];
00080 for (y = 0; y < dimY_; y++)
00081 {
00082 grid3D_[x][y] = new unsigned char [dimZ_];
00083 for (z = 0; z < dimZ_; z++)
00084 {
00085 grid3D_[x][y][z] = 255;
00086 }
00087 }
00088 }
00089 }
00090
00091 bool BFS3D::setGoal(std::vector<short unsigned int> goal)
00092 {
00093 if(goal.empty() || goal.size() < 3)
00094 return false;
00095
00096 goal_.clear();
00097
00098 if(goal[0] < dimX_ && goal[1] < dimY_ && goal[2] < dimZ_)
00099 goal_.push_back(goal);
00100
00101 if(goal_.empty())
00102 {
00103 SBPL_ERROR("[bfs3d] Error: No valid goals were received.");
00104 return false;
00105 }
00106 return true;
00107 }
00108
00109 bool BFS3D::setGoals(std::vector<std::vector<short unsigned int> > goals)
00110 {
00111 if(goals.size() <= 0)
00112 {
00113 SBPL_DEBUG("[bfs3d] No goal cell received. Exiting.");
00114 return false;
00115 }
00116
00117 goal_.clear();
00118
00119
00120 for(unsigned int i = 0; i < goals.size(); ++i)
00121 {
00122 if(goals[i].size() < 3)
00123 continue;
00124
00125 if(goals[i][0] < dimX_ && goals[i][1] < dimY_ && goals[i][2] < dimZ_)
00126 goal_.push_back(goals[i]);
00127 else
00128 SBPL_DEBUG("Goal: %u %u %u is invalid.",goals[i][0],goals[i][1],goals[i][2]);
00129 }
00130
00131 if(goal_.empty())
00132 {
00133 SBPL_DEBUG("Error: No valid goals were received.\n");
00134 return false;
00135 }
00136 return true;
00137 }
00138
00139 void BFS3D::reInitializeState3D(State3D* state)
00140 {
00141 state->g = INFINITE_COST;
00142 state->iterationclosed = 0;
00143 }
00144
00145 void BFS3D::initializeState3D(State3D* state, short unsigned int x, short unsigned int y, short unsigned int z)
00146 {
00147 state->g = INFINITE_COST;
00148 state->iterationclosed = 0;
00149 state->x = x;
00150 state->y = y;
00151 state->z = z;
00152 }
00153
00154 void BFS3D::create3DStateSpace(State3D**** statespace3D)
00155 {
00156 short unsigned int x,y,z;
00157
00158 *statespace3D = new State3D** [dimX_];
00159 for (x = 0; x < dimX_; x++)
00160 {
00161 (*statespace3D)[x] = new State3D* [dimY_];
00162 for(y = 0; y < dimY_; y++)
00163 {
00164 (*statespace3D)[x][y] = new State3D [dimZ_];
00165 for(z = 0; z < dimZ_; z++)
00166 {
00167 initializeState3D(&(*statespace3D)[x][y][z],x,y,z);
00168 }
00169 }
00170 }
00171 }
00172
00173 void BFS3D::delete3DStateSpace(State3D**** statespace3D)
00174 {
00175 short unsigned int x,y;
00176
00177 if((*statespace3D) != NULL)
00178 {
00179 for (x = 0; x < dimX_; x++)
00180 {
00181 for (y = 0; y < dimY_; y++)
00182 delete [] (*statespace3D)[x][y];
00183
00184 delete [] (*statespace3D)[x];
00185 }
00186 delete [] (*statespace3D);
00187 (*statespace3D) = NULL;
00188 }
00189 }
00190
00191 bool BFS3D::runBFS()
00192 {
00193 #if DEBUG_TIME
00194 clock_t currenttime = clock();
00195 #endif
00196
00197 if(goal_.empty())
00198 {
00199 SBPL_ERROR("[bfs3d] Goal location is not set. Exiting.\n");
00200 return false;
00201 }
00202
00203 dist_length_ = (dimX_-1) + (dimY_-1)*(dimX_) + (dimZ_-1)*(dimX_)*(dimY_) + 1;
00204 dist_.resize(dist_length_);
00205
00206 State3D*** statespace3D;
00207 create3DStateSpace(&statespace3D);
00208
00209 search3DwithQueue(statespace3D);
00210
00211 delete3DStateSpace(&statespace3D);
00212 #if DEBUG_TIME
00213 SBPL_DEBUG("completed in %.3f seconds.\n", double(clock()-currenttime) / CLOCKS_PER_SEC);
00214 #endif
00215
00216 return true;
00217 }
00218
00219 void BFS3D::search3DwithQueue(State3D*** statespace)
00220 {
00221 State3D* ExpState;
00222 int newx, newy, newz;
00223 short unsigned int x,y,z;
00224 unsigned int g_temp;
00225
00226
00227 int dx[DIRECTIONS3D] = { 1, 1, 1, 0, 0, 0, -1, -1, -1, 1, 1, 1, 0, 0, -1, -1, -1, 1, 1, 1, 0, 0, 0, -1, -1, -1};
00228 int dy[DIRECTIONS3D] = { 1, 0, -1, 1, 0, -1, -1, 0, 1, 1, 0, -1, 1, -1, -1, 0, 1, 1, 0, -1, 1, 0, -1, -1, 0, 1};
00229 int dz[DIRECTIONS3D] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1};
00230
00231
00232 queue<State3D*> Queue;
00233
00234
00235 for (x = 0; x < dimX_; x++)
00236 {
00237 for (y = 0; y < dimY_; y++)
00238 {
00239 for (z = 0; z < dimZ_; z++)
00240 {
00241 dist_[xyzToIndex(x,y,z)] = INFINITE_COST;
00242 reInitializeState3D(&statespace[x][y][z]);
00243 }
00244 }
00245 }
00246
00247
00248 for(unsigned int i = 0; i < goal_.size(); ++i)
00249 {
00250 statespace[goal_[i][0]][goal_[i][1]][goal_[i][2]].g = 0;
00251 Queue.push(&statespace[goal_[i][0]][goal_[i][1]][goal_[i][2]]);
00252 }
00253
00254
00255 while((int)Queue.size() > 0)
00256 {
00257
00258 ExpState = Queue.front();
00259
00260 Queue.pop();
00261
00262
00263 if(ExpState->iterationclosed == 1)
00264 continue;
00265
00266
00267 ExpState->iterationclosed = 1;
00268
00269
00270 dist_[xyzToIndex(ExpState->x, ExpState->y, ExpState->z)] = ExpState->g;
00271
00272
00273 for(int d = 0; d < DIRECTIONS3D; d++)
00274 {
00275 newx = ExpState->x + dx[d];
00276 newy = ExpState->y + dy[d];
00277 newz = ExpState->z + dz[d];
00278
00279
00280 if(0 > newx || newx >= dimX_ || 0 > newy || newy >= dimY_ || 0 > newz || newz >= dimZ_)
00281 continue;
00282
00283 if(!isValidCell(newx,newy,newz))
00284 continue;
00285
00286 if(statespace[newx][newy][newz].iterationclosed == 0)
00287 {
00288
00289 Queue.push(&statespace[newx][newy][newz]);
00290
00291
00292 if (ExpState->x != newx && ExpState->y != newy && ExpState->z != newz)
00293 g_temp = ExpState->g + cost_sqrt3_move_;
00294 else if ((ExpState->y != newy && ExpState->z != newz) ||
00295 (ExpState->x != newx && ExpState->z != newz) ||
00296 (ExpState->x != newx && ExpState->y != newy))
00297 g_temp = ExpState->g + cost_sqrt2_move_;
00298 else
00299 g_temp = ExpState->g + cost_1_move_;
00300
00301 if(statespace[newx][newy][newz].g > g_temp)
00302 statespace[newx][newy][newz].g = g_temp;
00303 }
00304 }
00305 }
00306 }
00307
00308 bool BFS3D::isGoal(const std::vector<int> &state)
00309 {
00310 for(unsigned int i = 0; i < goal_.size(); ++i)
00311 {
00312 if((state[0] <= goal_[i][0]+GOAL_TOLERANCE && state[0] >= goal_[i][0]-GOAL_TOLERANCE) && (state[1] <= goal_[i][1]+GOAL_TOLERANCE && state[1] >= goal_[i][1]-GOAL_TOLERANCE) && (state[2] <= goal_[i][2]+GOAL_TOLERANCE && state[2] >= goal_[i][2]-GOAL_TOLERANCE))
00313 return true;
00314 }
00315 return false;
00316 }
00317
00318 bool BFS3D::getShortestPath(std::vector<short unsigned int> start, std::vector<std::vector<int> > &path)
00319 {
00320 int val = 0, cntr = 0, min_val = INFINITE_COST;
00321 std::vector<int> state(3,0);
00322 std::vector<int> next_state(3,0);
00323 int newx,newy,newz;
00324
00325
00326 int max_path_length = dimX_*dimY_;
00327
00328 int dx[DIRECTIONS3D] = { 1, 1, 1, 0, 0, 0, -1, -1, -1, 1, 1, 1, 0, 0, -1, -1, -1, 1, 1, 1, 0, 0, 0, -1, -1, -1};
00329 int dy[DIRECTIONS3D] = { 1, 0, -1, 1, 0, -1, -1, 0, 1, 1, 0, -1, 1, -1, -1, 0, 1, 1, 0, -1, 1, 0, -1, -1, 0, 1};
00330 int dz[DIRECTIONS3D] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1};
00331
00332 path.resize(0);
00333 next_state[0] = start[0];
00334 next_state[1] = start[1];
00335 next_state[2] = start[2];
00336
00337 while(!isGoal(next_state) || cntr > max_path_length)
00338 {
00339 state = next_state;
00340 min_val = INFINITE_COST;
00341
00342
00343 for(int d = 0; d < DIRECTIONS3D; d++)
00344 {
00345 newx = state[0] + dx[d];
00346 newy = state[1] + dy[d];
00347 newz = state[2] + dz[d];
00348
00349
00350 if(0 > newx || newx >= dimX_ || 0 > newy || newy >= dimY_ || 0 > newz || newz >= dimZ_)
00351 continue;
00352
00353 val = dist_[xyzToIndex(newx,newy,newz)];
00354
00355 if(val >= INFINITE_COST)
00356 continue;
00357
00358 if (state[0] != newx && state[1] != newy && state[2] != newz)
00359 val += cost_sqrt3_move_;
00360 else if ((state[1] != newy && state[2] != newz) ||
00361 (state[0] != newx && state[2] != newz) ||
00362 (state[0] != newx && state[1] != newy))
00363 val += cost_sqrt2_move_;
00364 else
00365 val += cost_1_move_;
00366
00367 if(val < min_val)
00368 {
00369 min_val = val;
00370 next_state[0] = newx;
00371 next_state[1] = newy;
00372 next_state[2] = newz;
00373 }
00374 }
00375 path.push_back(next_state);
00376
00377 cntr++;
00378 }
00379
00380
00381 if(cntr > max_path_length)
00382 {
00383 SBPL_WARN("[BFS3D] Unable to find path to goal. Exiting.");
00384 path.clear();
00385 return false;
00386 }
00387
00388 return true;
00389 }
00390
00391 void BFS3D::configDistanceField(bool enable, const distance_field::PropagationDistanceField* df)
00392 {
00393 enable_df_ = enable;
00394 df_ = df;
00395
00396 radius_m_ = double(radius_ * df_->getResolution(distance_field::PropagationDistanceField::DIM_X));
00397 }
00398
00399
00400 bool BFS3D::isValidCell(const int x, const int y, const int z)
00401 {
00402 if(enable_df_)
00403 {
00404 if(df_->getDistanceFromCell(x,y,z) <= radius_m_)
00405 return false;
00406 }
00407 else
00408 {
00409 if(grid3D_[x][y][z] <= radius_)
00410 return false;
00411 }
00412 return true;
00413 }
00414
00415 void BFS3D::printConfig(FILE* fOut)
00416 {
00417 SBPL_FPRINTF(fOut,"BFS3D Configuration:\n");
00418 SBPL_FPRINTF(fOut,"dimX: %d dimY: %d dimZ: %d\n",dimX_,dimY_,dimZ_);
00419 SBPL_FPRINTF(fOut,"robot radius(cells): %d robot radius(meters): %0.3f\n",radius_,radius_m_);
00420 }
00421
00422 void BFS3D::printGrid()
00423 {
00424 for(unsigned int z = 0; z < dimZ_; ++z)
00425 {
00426 SBPL_DEBUG("---------------------------------");
00427 SBPL_DEBUG("z: %u",z);
00428 for(unsigned int x = 0; x < dimX_; ++x)
00429 {
00430 for(unsigned int y = 0; y < dimY_; ++y)
00431 SBPL_DEBUG("%u ", grid3D_[x][y][z]);
00432 }
00433 }
00434 }
00435
00436 void BFS3D::printCostToGoal()
00437 {
00438 {
00439 for(unsigned int z = 0; z < dimZ_; ++z)
00440 {
00441 SBPL_DEBUG("---------------------------------");
00442 SBPL_DEBUG("z: %u",z);
00443 for(unsigned int x = 0; x < dimX_; ++x)
00444 {
00445 for(unsigned int y = 0; y < dimY_; ++y)
00446 SBPL_DEBUG("%u ", dist_[xyzToIndex(x,y,z)]);
00447 }
00448 }
00449 }
00450 }
00451