lazy_free_space_updater.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2011, Willow Garage, Inc.
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 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: Ioan Sucan */
36 
38 #include <ros/console.h>
39 
40 namespace occupancy_map_monitor
41 {
42 static const std::string LOGNAME = "lazy_free_space_updater";
43 
45  : tree_(tree)
46  , running_(true)
47  , max_batch_size_(max_batch_size)
48  , max_sensor_delta_(1e-3) // 1mm
49  , process_occupied_cells_set_(nullptr)
50  , process_model_cells_set_(nullptr)
51  , update_thread_([this] { lazyUpdateThread(); })
52  , process_thread_([this] { processThread(); })
53 {
54 }
55 
56 LazyFreeSpaceUpdater::~LazyFreeSpaceUpdater()
57 {
58  running_ = false;
59  {
60  boost::unique_lock<boost::mutex> _(update_cell_sets_lock_);
61  update_condition_.notify_one();
62  }
63  {
64  boost::unique_lock<boost::mutex> _(cell_process_lock_);
65  process_condition_.notify_one();
66  }
67  update_thread_.join();
68  process_thread_.join();
69 }
70 
71 void LazyFreeSpaceUpdater::pushLazyUpdate(octomap::KeySet* occupied_cells, octomap::KeySet* model_cells,
72  const octomap::point3d& sensor_origin)
73 {
74  ROS_DEBUG_NAMED(LOGNAME, "Pushing %lu occupied cells and %lu model cells for lazy updating...",
75  (long unsigned int)occupied_cells->size(), (long unsigned int)model_cells->size());
76  boost::mutex::scoped_lock _(update_cell_sets_lock_);
77  occupied_cells_sets_.push_back(occupied_cells);
78  model_cells_sets_.push_back(model_cells);
79  sensor_origins_.push_back(sensor_origin);
80  update_condition_.notify_one();
81 }
82 
83 void LazyFreeSpaceUpdater::pushBatchToProcess(OcTreeKeyCountMap* occupied_cells, octomap::KeySet* model_cells,
84  const octomap::point3d& sensor_origin)
85 {
86  // this is basically a queue of size 1. if this function is called repeatedly without any work being done by
87  // processThread(),
88  // data can be lost; this is intentional, to avoid spending too much time clearing the octomap
89  if (cell_process_lock_.try_lock())
90  {
91  process_occupied_cells_set_ = occupied_cells;
92  process_model_cells_set_ = model_cells;
93  process_sensor_origin_ = sensor_origin;
94  process_condition_.notify_one();
95  cell_process_lock_.unlock();
96  }
97  else
98  {
99  ROS_WARN_NAMED(LOGNAME, "Previous batch update did not complete. Ignoring set of cells to be freed.");
100  delete occupied_cells;
101  delete model_cells;
102  }
103 }
104 
105 void LazyFreeSpaceUpdater::processThread()
106 {
107  const float lg_0 = tree_->getClampingThresMinLog() - tree_->getClampingThresMaxLog();
108  const float lg_miss = tree_->getProbMissLog();
109 
110  octomap::KeyRay key_ray1, key_ray2;
111  OcTreeKeyCountMap free_cells1, free_cells2;
112 
113  while (running_)
114  {
115  free_cells1.clear();
116  free_cells2.clear();
117 
118  boost::unique_lock<boost::mutex> ulock(cell_process_lock_);
119  while (!process_occupied_cells_set_ && running_)
120  process_condition_.wait(ulock);
121 
122  if (!running_)
123  break;
124 
126  "Begin processing batched update: marking free cells due to %lu occupied cells and %lu model cells",
127  (long unsigned int)process_occupied_cells_set_->size(),
128  (long unsigned int)process_model_cells_set_->size());
129 
131  tree_->lockRead();
132 
133 #pragma omp sections
134  {
135 #pragma omp section
136  {
137  /* compute the free cells along each ray that ends at an occupied cell */
138  for (std::pair<const octomap::OcTreeKey, unsigned int>& it : *process_occupied_cells_set_)
139  if (tree_->computeRayKeys(process_sensor_origin_, tree_->keyToCoord(it.first), key_ray1))
140  for (octomap::OcTreeKey& jt : key_ray1)
141  free_cells1[jt] += it.second;
142  }
143 
144 #pragma omp section
145  {
146  /* compute the free cells along each ray that ends at a model cell */
147  for (const octomap::OcTreeKey& it : *process_model_cells_set_)
148  if (tree_->computeRayKeys(process_sensor_origin_, tree_->keyToCoord(it), key_ray2))
149  for (octomap::OcTreeKey& jt : key_ray2)
150  free_cells2[jt]++;
151  }
152  }
153 
154  tree_->unlockRead();
155 
156  for (std::pair<const octomap::OcTreeKey, unsigned int>& it : *process_occupied_cells_set_)
157  {
158  free_cells1.erase(it.first);
159  free_cells2.erase(it.first);
160  }
161 
162  for (const octomap::OcTreeKey& it : *process_model_cells_set_)
163  {
164  free_cells1.erase(it);
165  free_cells2.erase(it);
166  }
167  ROS_DEBUG_NAMED(LOGNAME, "Marking %lu cells as free...",
168  (long unsigned int)(free_cells1.size() + free_cells2.size()));
169 
170  tree_->lockWrite();
171 
172  try
173  {
174  // set the logodds to the minimum for the cells that are part of the model
175  for (const octomap::OcTreeKey& it : *process_model_cells_set_)
176  tree_->updateNode(it, lg_0);
177 
178  /* mark free cells only if not seen occupied in this cloud */
179  for (std::pair<const octomap::OcTreeKey, unsigned int>& it : free_cells1)
180  tree_->updateNode(it.first, it.second * lg_miss);
181  for (std::pair<const octomap::OcTreeKey, unsigned int>& it : free_cells2)
182  tree_->updateNode(it.first, it.second * lg_miss);
183  }
184  catch (...)
185  {
186  ROS_ERROR_NAMED(LOGNAME, "Internal error while updating octree");
187  }
188  tree_->unlockWrite();
189  tree_->triggerUpdateCallback();
190 
191  ROS_DEBUG_NAMED(LOGNAME, "Marked free cells in %lf ms", (ros::WallTime::now() - start).toSec() * 1000.0);
192 
193  delete process_occupied_cells_set_;
194  process_occupied_cells_set_ = nullptr;
195  delete process_model_cells_set_;
196  process_model_cells_set_ = nullptr;
197  }
198 }
199 
200 void LazyFreeSpaceUpdater::lazyUpdateThread()
201 {
202  OcTreeKeyCountMap* occupied_cells_set = nullptr;
203  octomap::KeySet* model_cells_set = nullptr;
204  octomap::point3d sensor_origin;
205  unsigned int batch_size = 0;
206 
207  while (running_)
208  {
209  boost::unique_lock<boost::mutex> ulock(update_cell_sets_lock_);
210  while (occupied_cells_sets_.empty() && running_)
211  update_condition_.wait(ulock);
212 
213  if (!running_)
214  break;
215 
216  if (batch_size == 0)
217  {
218  occupied_cells_set = new OcTreeKeyCountMap();
219  octomap::KeySet* s = occupied_cells_sets_.front();
220  occupied_cells_sets_.pop_front();
221  for (const octomap::OcTreeKey& it : *s)
222  (*occupied_cells_set)[it]++;
223  delete s;
224  model_cells_set = model_cells_sets_.front();
225  model_cells_sets_.pop_front();
226  sensor_origin = sensor_origins_.front();
227  sensor_origins_.pop_front();
228  batch_size++;
229  }
230 
231  while (!occupied_cells_sets_.empty())
232  {
233  if ((sensor_origins_.front() - sensor_origin).norm() > max_sensor_delta_)
234  {
235  ROS_DEBUG_NAMED(LOGNAME, "Pushing %u sets of occupied/model cells to free cells update thread (origin changed)",
236  batch_size);
237  pushBatchToProcess(occupied_cells_set, model_cells_set, sensor_origin);
238  batch_size = 0;
239  break;
240  }
241  sensor_origins_.pop_front();
242 
243  octomap::KeySet* add_occ = occupied_cells_sets_.front();
244  for (const octomap::OcTreeKey& it : *add_occ)
245  (*occupied_cells_set)[it]++;
246  occupied_cells_sets_.pop_front();
247  delete add_occ;
248  octomap::KeySet* mod_occ = model_cells_sets_.front();
249  model_cells_set->insert(mod_occ->begin(), mod_occ->end());
250  model_cells_sets_.pop_front();
251  delete mod_occ;
252  batch_size++;
253  }
254 
255  if (batch_size >= max_batch_size_)
256  {
257  ROS_DEBUG_NAMED(LOGNAME, "Pushing %u sets of occupied/model cells to free cells update thread", batch_size);
258  pushBatchToProcess(occupied_cells_set, model_cells_set, sensor_origin);
259  occupied_cells_set = nullptr;
260  batch_size = 0;
261  }
262  }
263 }
264 } // namespace occupancy_map_monitor
lazy_free_space_updater.h
s
XmlRpcServer s
ROS_ERROR_NAMED
#define ROS_ERROR_NAMED(name,...)
octomap::KeyRay
octomath::Vector3
console.h
octomap::KeySet
unordered_ns::unordered_set< OcTreeKey, OcTreeKey::KeyHash > KeySet
ROS_DEBUG_NAMED
#define ROS_DEBUG_NAMED(name,...)
ros::WallTime::now
static WallTime now()
octomap::OcTreeKey
ros::WallTime
start
ROSCPP_DECL void start()
ROS_WARN_NAMED
#define ROS_WARN_NAMED(name,...)
occupancy_map_monitor::LOGNAME
static const std::string LOGNAME
occupancy_map_monitor
occupancy_map_monitor::LazyFreeSpaceUpdater::LazyFreeSpaceUpdater
LazyFreeSpaceUpdater(const collision_detection::OccMapTreePtr &tree, unsigned int max_batch_size=10)
Definition: lazy_free_space_updater.cpp:76
collision_detection::OccMapTreePtr
std::shared_ptr< OccMapTree > OccMapTreePtr


perception
Author(s): Ioan Sucan , Jon Binney , Suat Gedikli
autogenerated on Mon May 27 2024 02:27:57