38#include <rclcpp/logging.hpp>
39#include <rclcpp/clock.hpp>
48 , max_batch_size_(max_batch_size)
49 , max_sensor_delta_(1e-3)
50 , process_occupied_cells_set_(nullptr)
51 , process_model_cells_set_(nullptr)
52 , update_thread_([this] { lazyUpdateThread(); })
53 , process_thread_([
this] { processThread(); })
62 std::unique_lock<std::mutex> _(update_cell_sets_lock_);
63 update_condition_.notify_one();
66 std::unique_lock<std::mutex> _(cell_process_lock_);
67 process_condition_.notify_one();
69 update_thread_.join();
70 process_thread_.join();
74 const octomap::point3d& sensor_origin)
76 RCLCPP_DEBUG(logger_,
"Pushing %lu occupied cells and %lu model cells for lazy updating...",
77 static_cast<long unsigned int>(occupied_cells->size()),
78 static_cast<long unsigned int>(model_cells->size()));
79 std::scoped_lock _(update_cell_sets_lock_);
80 occupied_cells_sets_.push_back(occupied_cells);
81 model_cells_sets_.push_back(model_cells);
82 sensor_origins_.push_back(sensor_origin);
83 update_condition_.notify_one();
86void LazyFreeSpaceUpdater::pushBatchToProcess(OcTreeKeyCountMap* occupied_cells, octomap::KeySet* model_cells,
87 const octomap::point3d& sensor_origin)
92 if (cell_process_lock_.try_lock())
94 process_occupied_cells_set_ = occupied_cells;
95 process_model_cells_set_ = model_cells;
96 process_sensor_origin_ = sensor_origin;
97 process_condition_.notify_one();
98 cell_process_lock_.unlock();
102 RCLCPP_WARN(logger_,
"Previous batch update did not complete. Ignoring set of cells to be freed.");
103 delete occupied_cells;
108void LazyFreeSpaceUpdater::processThread()
110 const float lg_0 = tree_->getClampingThresMinLog() - tree_->getClampingThresMaxLog();
111 const float lg_miss = tree_->getProbMissLog();
113 octomap::KeyRay key_ray1, key_ray2;
114 OcTreeKeyCountMap free_cells1, free_cells2;
121 std::unique_lock<std::mutex> ulock(cell_process_lock_);
122 while (!process_occupied_cells_set_ && running_)
123 process_condition_.wait(ulock);
128 RCLCPP_DEBUG(logger_,
129 "Begin processing batched update: marking free cells due to %lu occupied cells and %lu model cells",
130 static_cast<long unsigned int>(process_occupied_cells_set_->size()),
131 static_cast<long unsigned int>(process_model_cells_set_->size()));
134 rclcpp::Time start = clock.now();
142 for (std::pair<const octomap::OcTreeKey, unsigned int>& it : *process_occupied_cells_set_)
144 if (tree_->computeRayKeys(process_sensor_origin_, tree_->keyToCoord(it.first), key_ray1))
146 for (octomap::OcTreeKey& jt : key_ray1)
147 free_cells1[jt] += it.second;
155 for (
const octomap::OcTreeKey& it : *process_model_cells_set_)
157 if (tree_->computeRayKeys(process_sensor_origin_, tree_->keyToCoord(it), key_ray2))
159 for (octomap::OcTreeKey& jt : key_ray2)
168 for (std::pair<const octomap::OcTreeKey, unsigned int>& it : *process_occupied_cells_set_)
170 free_cells1.erase(it.first);
171 free_cells2.erase(it.first);
174 for (
const octomap::OcTreeKey& it : *process_model_cells_set_)
176 free_cells1.erase(it);
177 free_cells2.erase(it);
179 RCLCPP_DEBUG(logger_,
"Marking %lu cells as free...",
180 static_cast<long unsigned int>(free_cells1.size() + free_cells2.size()));
187 for (
const octomap::OcTreeKey& it : *process_model_cells_set_)
188 tree_->updateNode(it, lg_0);
191 for (std::pair<const octomap::OcTreeKey, unsigned int>& it : free_cells1)
192 tree_->updateNode(it.first, it.second * lg_miss);
193 for (std::pair<const octomap::OcTreeKey, unsigned int>& it : free_cells2)
194 tree_->updateNode(it.first, it.second * lg_miss);
198 RCLCPP_ERROR(logger_,
"Internal error while updating octree");
200 tree_->unlockWrite();
201 tree_->triggerUpdateCallback();
203 RCLCPP_DEBUG(logger_,
"Marked free cells in %lf ms", (clock.now() - start).seconds() * 1000.0);
205 delete process_occupied_cells_set_;
206 process_occupied_cells_set_ =
nullptr;
207 delete process_model_cells_set_;
208 process_model_cells_set_ =
nullptr;
212void LazyFreeSpaceUpdater::lazyUpdateThread()
214 OcTreeKeyCountMap* occupied_cells_set =
nullptr;
215 octomap::KeySet* model_cells_set =
nullptr;
216 octomap::point3d sensor_origin;
217 unsigned int batch_size = 0;
221 std::unique_lock<std::mutex> ulock(update_cell_sets_lock_);
222 while (occupied_cells_sets_.empty() && running_)
223 update_condition_.wait(ulock);
230 occupied_cells_set =
new OcTreeKeyCountMap();
231 octomap::KeySet* s = occupied_cells_sets_.front();
232 occupied_cells_sets_.pop_front();
233 for (
const octomap::OcTreeKey& it : *s)
234 (*occupied_cells_set)[it]++;
236 model_cells_set = model_cells_sets_.front();
237 model_cells_sets_.pop_front();
238 sensor_origin = sensor_origins_.front();
239 sensor_origins_.pop_front();
243 while (!occupied_cells_sets_.empty())
245 if ((sensor_origins_.front() - sensor_origin).norm() > max_sensor_delta_)
247 RCLCPP_DEBUG(logger_,
"Pushing %u sets of occupied/model cells to free cells update thread (origin changed)",
249 pushBatchToProcess(occupied_cells_set, model_cells_set, sensor_origin);
253 sensor_origins_.pop_front();
255 octomap::KeySet* add_occ = occupied_cells_sets_.front();
256 for (
const octomap::OcTreeKey& it : *add_occ)
257 (*occupied_cells_set)[it]++;
258 occupied_cells_sets_.pop_front();
260 octomap::KeySet* mod_occ = model_cells_sets_.front();
261 model_cells_set->insert(mod_occ->begin(), mod_occ->end());
262 model_cells_sets_.pop_front();
267 if (batch_size >= max_batch_size_)
269 RCLCPP_DEBUG(logger_,
"Pushing %u sets of occupied/model cells to free cells update thread", batch_size);
270 pushBatchToProcess(occupied_cells_set, model_cells_set, sensor_origin);
271 occupied_cells_set =
nullptr;
void pushLazyUpdate(octomap::KeySet *occupied_cells, octomap::KeySet *model_cells, const octomap::point3d &sensor_origin)
LazyFreeSpaceUpdater(const collision_detection::OccMapTreePtr &tree, unsigned int max_batch_size=10)
std::shared_ptr< OccMapTree > OccMapTreePtr
rclcpp::Logger getLogger(const std::string &name)
Creates a namespaced logger.