n-Dimensional Fast Methods  0.7
 All Classes Functions Variables Typedefs Pages
ddqm.hpp
1 
29 #ifndef DDQM_HPP_
30 #define DDQM_HPP_
31 
32 #include <queue>
33 
34 #include <fast_methods/fm/eikonalsolver.hpp>
35 #include <fast_methods/ndgridmap/fmcell.h>
36 
37 #include <fast_methods//utils/utils.h>
38 
39 
41 template < class grid_t > class DDQM : public EikonalSolver<grid_t> {
42 
43  public:
44  DDQM(const char * name = "DDQM") : EikonalSolver<grid_t>(name) {}
45 
47  virtual void setEnvironment
48  (grid_t * g) {
50  thStep_ = 1.5 *grid_->getLeafSize() / grid_->getAvgSpeed();
52  }
53 
55  virtual void setup
56  () {
58  if (int(goal_idx_) != -1)
59  console::warning("Setting a goal point in DDQM is experimental. It may lead to wrong results.");
60  }
61 
63  virtual void computeInternal
64  () {
65  if (!setup_)
66  setup();
67 
68  // FMState::FROZEN - locked and FMState::OPEN - unlocked.
69  // The time this takes is negligible and if done in setup or
70  // setEnvironment it can affect other planners run in the same
71  // grid.
72  for(size_t i = 0; i < grid_->size(); ++i)
73  grid_->getCell(i).setState(FMState::FROZEN);
74 
75  // Initialization
76  unsigned int n_neighs = 0;
77  for (unsigned int i: init_points_) {
78  grid_->getCell(i).setArrivalTime(0);
79  n_neighs = grid_->getNeighbors(i, neighbors_);
80  for (unsigned int j = 0; j < n_neighs; ++j) {
81  if (grid_->getCell(neighbors_[j]).isOccupied())
82  continue;
83  grid_->getCell(neighbors_[j]).setState(FMState::OPEN);
84  queues_[0].push(neighbors_[j]);
85  }
86  }
87 
88  bool stopPropagation = false;
89 
90  // lq is the index of the lower queue (to avoid swapping and copying).
91  unsigned int lq = 0;
92  // counts[0] tracks insertions in lower queue. counts[1] is total insertions.
93  std::array<size_t, 2> counts = {0,0};
94 
95  while ((!queues_[0].empty() || !queues_[1].empty()) && !stopPropagation) {
96  while (!queues_[lq].empty() && !stopPropagation) {
97  unsigned int idx = queues_[lq].front();
98  queues_[lq].pop();
99  if (grid_->getCell(idx).isOccupied())
100  continue;
101  double newT = solveEikonal(idx);
102  if (utils::isTimeBetterThan(newT, grid_->getCell(idx).getArrivalTime())) {
103  grid_->getCell(idx).setArrivalTime(newT);
104  n_neighs = grid_->getNeighbors(idx, neighbors_);
105  for (unsigned int j = 0; j < n_neighs; ++j) {
106  unsigned int n = neighbors_[j];
107  if (grid_->getCell(n).getState() == FMState::FROZEN) // In the paper they say unlocked here, but makes no sense!!
108  if(utils::isTimeBetterThan(newT, grid_->getCell(n).getArrivalTime())) {
109  grid_->getCell(n).setState(FMState::OPEN);
110  counts[1] += 1;
111  if (utils::isTimeBetterThan(newT, threshold_)) {
112  queues_[lq].push(n); // Insert in lower queue.
113  counts[0] += 1;
114  }
115  else
116  queues_[(lq+1)%2].push(n); // Insert in higher queue.
117  }
118  }
119  } // If time is improved.
120  grid_->getCell(idx).setState(FMState::FROZEN);
121  // EXPERIMENTAL - Value not updated, it has converged
122  if(idx == goal_idx_)
123  stopPropagation = true;
124 
125  } // While lower queue is not empty.
126 
127  lq = (lq+1)%2;
128  increaseThreshold(counts);
129  }
130  }
131 
133  void increaseThreshold
134  (std::array<size_t, 2> & counts) {
135  double minPercent = 0.65;
136  double maxPercent = 0.75;
137  double currentPercent;
138  if (counts[1] != 0)
139  currentPercent = counts[0]/double(counts[1]);
140  else
141  currentPercent = 1.0;
142  if (currentPercent <= minPercent)
143  thStep_ *= 1.5;
144  else if (currentPercent >= maxPercent)
145  thStep_ /= 2.0;
146  threshold_ += thStep_;
147  counts = {0,0};
148  }
149 
150  virtual void reset
151  () {
153 
154  while(!queues_[0].empty())
155  queues_[0].pop();
156  while(!queues_[1].empty())
157  queues_[1].pop();
158  double avgSpeed = 1.0/(grid_->getAvgSpeed()*grid_->getLeafSize());
159  thStep_ = 1.5 / avgSpeed;
161  }
162 
163  virtual void printRunInfo
164  () const {
165  console::info("Double Dynamic Queue Method");
166  std::cout << '\t' << name_ << '\n'
167  << '\t' << "Elapsed time: " << time_ << " ms\n";
168  }
169 
170  protected:
180 
182  std::array<std::queue<unsigned int>, 2> queues_;
183 
185  double threshold_;
186 
188  double thStep_;
189 };
190 
191 #endif /* DDQM_HPP_*/
Abstract class that serves as interface for the actual EikonalSolvers implemented. It requires (at least) the computeInternal method to be implemented,.
virtual void setup()
Executes EikonalSolver setup and other checks.
Definition: ddqm.hpp:56
double time_
Time elapsed by the compute method.
Definition: solver.hpp:237
double thStep_
Threshold step for each full iteration.
Definition: ddqm.hpp:188
virtual void setEnvironment(grid_t *g)
Sets and cleans the grid in which operations will be performed.
Definition: solver.hpp:51
virtual void setup()
Checks that the solver is ready to run. Sets the grid unclean.
Definition: solver.hpp:94
std::array< unsigned int, 2 *grid_t::getNDims()> neighbors_
Auxiliar array which stores the neighbor of each iteration of the computeFM() function.
std::array< std::queue< unsigned int >, 2 > queues_
Queues which contain the lower and higher cells to be expanded in further iterations.
Definition: ddqm.hpp:182
virtual double solveEikonal(const int &idx)
Solves nD Eikonal equation for cell idx. If heuristics are activated, it will add the estimated trave...
void increaseThreshold(std::array< size_t, 2 > &counts)
Dynamically increases the threshold according to the reference paper.
Definition: ddqm.hpp:134
grid_t * grid_
Grid container.
Definition: solver.hpp:219
static void info(const std::string &val)
std::vector< unsigned int > init_points_
Initial index.
Definition: solver.hpp:228
std::string name_
Solver name.
Definition: solver.hpp:222
virtual void reset()
Clears temporal data, so it is ready to run again.
Definition: ddqm.hpp:151
static bool isTimeBetterThan(double t1, double t2)
Returns true if t1 is at least epsilon-lower than t2, provides robust comparions for doubles...
Definition: utils.h:32
Implements Double Dynamic Queue Method.
Definition: ddqm.hpp:41
virtual void computeInternal()
Actual method that implements DDQM.
Definition: ddqm.hpp:64
bool setup_
Setup status.
Definition: solver.hpp:225
double threshold_
Current queue cutoff to divide lower and higher queues.
Definition: ddqm.hpp:185
unsigned int goal_idx_
Goal index.
Definition: solver.hpp:231
static void warning(const std::string &val)
virtual void setEnvironment(grid_t *g)
Calls EikonalSolver::setEnvironment() and sets the initial threshold.
Definition: ddqm.hpp:48
virtual void reset()
Clears temporal data, so it is ready to run again.
Definition: solver.hpp:176