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 #include <moveit/lazy_free_space_updater/lazy_free_space_updater.h>
00038 #include <ros/console.h>
00039
00040 namespace occupancy_map_monitor
00041 {
00042 LazyFreeSpaceUpdater::LazyFreeSpaceUpdater(const OccMapTreePtr& tree, unsigned int max_batch_size)
00043 : tree_(tree)
00044 , running_(true)
00045 , max_batch_size_(max_batch_size)
00046 , max_sensor_delta_(1e-3)
00047 ,
00048 process_occupied_cells_set_(NULL)
00049 , process_model_cells_set_(NULL)
00050 , update_thread_(boost::bind(&LazyFreeSpaceUpdater::lazyUpdateThread, this))
00051 , process_thread_(boost::bind(&LazyFreeSpaceUpdater::processThread, this))
00052 {
00053 }
00054
00055 LazyFreeSpaceUpdater::~LazyFreeSpaceUpdater()
00056 {
00057 running_ = false;
00058 {
00059 boost::unique_lock<boost::mutex> _(update_cell_sets_lock_);
00060 update_condition_.notify_one();
00061 }
00062 {
00063 boost::unique_lock<boost::mutex> _(cell_process_lock_);
00064 process_condition_.notify_one();
00065 }
00066 update_thread_.join();
00067 process_thread_.join();
00068 }
00069
00070 void LazyFreeSpaceUpdater::pushLazyUpdate(octomap::KeySet* occupied_cells, octomap::KeySet* model_cells,
00071 const octomap::point3d& sensor_origin)
00072 {
00073 ROS_DEBUG("Pushing %lu occupied cells and %lu model cells for lazy updating...",
00074 (long unsigned int)occupied_cells->size(), (long unsigned int)model_cells->size());
00075 boost::mutex::scoped_lock _(update_cell_sets_lock_);
00076 occupied_cells_sets_.push_back(occupied_cells);
00077 model_cells_sets_.push_back(model_cells);
00078 sensor_origins_.push_back(sensor_origin);
00079 update_condition_.notify_one();
00080 }
00081
00082 void LazyFreeSpaceUpdater::pushBatchToProcess(OcTreeKeyCountMap* occupied_cells, octomap::KeySet* model_cells,
00083 const octomap::point3d& sensor_origin)
00084 {
00085
00086
00087
00088 if (cell_process_lock_.try_lock())
00089 {
00090 process_occupied_cells_set_ = occupied_cells;
00091 process_model_cells_set_ = model_cells;
00092 process_sensor_origin_ = sensor_origin;
00093 process_condition_.notify_one();
00094 cell_process_lock_.unlock();
00095 }
00096 else
00097 {
00098 ROS_WARN("Previous batch update did not complete. Ignoring set of cells to be freed.");
00099 delete occupied_cells;
00100 delete model_cells;
00101 }
00102 }
00103
00104 void LazyFreeSpaceUpdater::processThread()
00105 {
00106 const float lg_0 = tree_->getClampingThresMinLog() - tree_->getClampingThresMaxLog();
00107 const float lg_miss = tree_->getProbMissLog();
00108
00109 octomap::KeyRay key_ray1, key_ray2;
00110 OcTreeKeyCountMap free_cells1, free_cells2;
00111
00112 while (running_)
00113 {
00114 free_cells1.clear();
00115 free_cells2.clear();
00116
00117 boost::unique_lock<boost::mutex> ulock(cell_process_lock_);
00118 while (!process_occupied_cells_set_ && running_)
00119 process_condition_.wait(ulock);
00120
00121 if (!running_)
00122 break;
00123
00124 ROS_DEBUG("Begin processing batched update: marking free cells due to %lu occupied cells and %lu model cells",
00125 (long unsigned int)process_occupied_cells_set_->size(),
00126 (long unsigned int)process_model_cells_set_->size());
00127
00128 ros::WallTime start = ros::WallTime::now();
00129 tree_->lockRead();
00130
00131 #pragma omp sections
00132 {
00133 #pragma omp section
00134 {
00135
00136 for (OcTreeKeyCountMap::iterator it = process_occupied_cells_set_->begin(),
00137 end = process_occupied_cells_set_->end();
00138 it != end; ++it)
00139 if (tree_->computeRayKeys(process_sensor_origin_, tree_->keyToCoord(it->first), key_ray1))
00140 for (octomap::KeyRay::iterator jt = key_ray1.begin(), end = key_ray1.end(); jt != end; ++jt)
00141 free_cells1[*jt] += it->second;
00142 }
00143
00144 #pragma omp section
00145 {
00146
00147 for (octomap::KeySet::iterator it = process_model_cells_set_->begin(), end = process_model_cells_set_->end();
00148 it != end; ++it)
00149 if (tree_->computeRayKeys(process_sensor_origin_, tree_->keyToCoord(*it), key_ray2))
00150 for (octomap::KeyRay::iterator jt = key_ray2.begin(), end = key_ray2.end(); jt != end; ++jt)
00151 free_cells2[*jt]++;
00152 }
00153 }
00154
00155 tree_->unlockRead();
00156
00157 for (OcTreeKeyCountMap::iterator it = process_occupied_cells_set_->begin(),
00158 end = process_occupied_cells_set_->end();
00159 it != end; ++it)
00160 {
00161 free_cells1.erase(it->first);
00162 free_cells2.erase(it->first);
00163 }
00164
00165 for (octomap::KeySet::iterator it = process_model_cells_set_->begin(), end = process_model_cells_set_->end();
00166 it != end; ++it)
00167 {
00168 free_cells1.erase(*it);
00169 free_cells2.erase(*it);
00170 }
00171 ROS_DEBUG("Marking %lu cells as free...", (long unsigned int)(free_cells1.size() + free_cells2.size()));
00172
00173 tree_->lockWrite();
00174
00175 try
00176 {
00177
00178 for (octomap::KeySet::iterator it = process_model_cells_set_->begin(), end = process_model_cells_set_->end();
00179 it != end; ++it)
00180 tree_->updateNode(*it, lg_0);
00181
00182
00183 for (OcTreeKeyCountMap::iterator it = free_cells1.begin(), end = free_cells1.end(); it != end; ++it)
00184 tree_->updateNode(it->first, it->second * lg_miss);
00185 for (OcTreeKeyCountMap::iterator it = free_cells2.begin(), end = free_cells2.end(); it != end; ++it)
00186 tree_->updateNode(it->first, it->second * lg_miss);
00187 }
00188 catch (...)
00189 {
00190 ROS_ERROR("Internal error while updating octree");
00191 }
00192 tree_->unlockWrite();
00193 tree_->triggerUpdateCallback();
00194
00195 ROS_DEBUG("Marked free cells in %lf ms", (ros::WallTime::now() - start).toSec() * 1000.0);
00196
00197 delete process_occupied_cells_set_;
00198 process_occupied_cells_set_ = NULL;
00199 delete process_model_cells_set_;
00200 process_model_cells_set_ = NULL;
00201 }
00202 }
00203
00204 void LazyFreeSpaceUpdater::lazyUpdateThread()
00205 {
00206 OcTreeKeyCountMap* occupied_cells_set = NULL;
00207 octomap::KeySet* model_cells_set = NULL;
00208 octomap::point3d sensor_origin;
00209 unsigned int batch_size = 0;
00210
00211 while (running_)
00212 {
00213 boost::unique_lock<boost::mutex> ulock(update_cell_sets_lock_);
00214 while (occupied_cells_sets_.empty() && running_)
00215 update_condition_.wait(ulock);
00216
00217 if (!running_)
00218 break;
00219
00220 if (batch_size == 0)
00221 {
00222 occupied_cells_set = new OcTreeKeyCountMap();
00223 octomap::KeySet* s = occupied_cells_sets_.front();
00224 occupied_cells_sets_.pop_front();
00225 for (octomap::KeySet::iterator it = s->begin(), end = s->end(); it != end; ++it)
00226 (*occupied_cells_set)[*it]++;
00227 delete s;
00228 model_cells_set = model_cells_sets_.front();
00229 model_cells_sets_.pop_front();
00230 sensor_origin = sensor_origins_.front();
00231 sensor_origins_.pop_front();
00232 batch_size++;
00233 }
00234
00235 while (!occupied_cells_sets_.empty())
00236 {
00237 if ((sensor_origins_.front() - sensor_origin).norm() > max_sensor_delta_)
00238 {
00239 ROS_DEBUG("Pushing %u sets of occupied/model cells to free cells update thread (origin changed)", batch_size);
00240 pushBatchToProcess(occupied_cells_set, model_cells_set, sensor_origin);
00241 batch_size = 0;
00242 break;
00243 }
00244 sensor_origins_.pop_front();
00245
00246 octomap::KeySet* add_occ = occupied_cells_sets_.front();
00247 for (octomap::KeySet::iterator it = add_occ->begin(), end = add_occ->end(); it != end; ++it)
00248 (*occupied_cells_set)[*it]++;
00249 occupied_cells_sets_.pop_front();
00250 delete add_occ;
00251 octomap::KeySet* mod_occ = model_cells_sets_.front();
00252 model_cells_set->insert(mod_occ->begin(), mod_occ->end());
00253 model_cells_sets_.pop_front();
00254 delete mod_occ;
00255 batch_size++;
00256 }
00257
00258 if (batch_size >= max_batch_size_)
00259 {
00260 ROS_DEBUG("Pushing %u sets of occupied/model cells to free cells update thread", batch_size);
00261 pushBatchToProcess(occupied_cells_set, model_cells_set, sensor_origin);
00262 occupied_cells_set = NULL;
00263 batch_size = 0;
00264 }
00265 }
00266 }
00267 }