n-Dimensional Fast Methods  0.7
 All Classes Functions Variables Typedefs Pages
fmm.hpp
1 
43 #ifndef FMM_HPP_
44 #define FMM_HPP_
45 
46 #include <iostream>
47 #include <cmath>
48 #include <algorithm>
49 #include <numeric>
50 #include <fstream>
51 #include <array>
52 
53 #include <fast_methods/fm/eikonalsolver.hpp>
54 
55 #include <fast_methods/ndgridmap/fmcell.h>
56 #include <fast_methods/datastructures/fmdaryheap.hpp>
57 
58 #include <fast_methods/ndgridmap/ndgridmap.hpp>
59 #include <fast_methods/console/console.h>
60 
62 enum HeurStrategy {NOHEUR = 0, TIME, DISTANCE};
63 
64 template < class grid_t, class heap_t = FMDaryHeap<FMCell> > class FMM : public EikonalSolver<grid_t> {
65 
66  public:
67  FMM(HeurStrategy h = NOHEUR) : EikonalSolver<grid_t>("FMM"), heurStrategy_(h), precomputed_(false) {
69  //if (static_cast<FMFibHeap>(heap_t))
70  // name_ = "FMMFib";
71  }
72 
73  FMM(const char * name, HeurStrategy h = NOHEUR) : EikonalSolver<grid_t>(name), heurStrategy_(h), precomputed_(false) {}
74 
75  virtual ~FMM() { clear(); }
76 
78  virtual void setup
79  () {
81  narrow_band_.setMaxSize(grid_->size());
82  setHeuristics(heurStrategy_); // Redundant, but safe.
83 
84  if (int(goal_idx_) == -1 && heurStrategy_ != NOHEUR) {
85  console::warning("FMM/SFMM: Heuristics set with no goal point. Deactivating heuristics.");
86  heurStrategy_ = NOHEUR;
87  }
88  }
89 
91  virtual void computeInternal
92  () {
93  if (!setup_)
94  setup();
95 
96  unsigned int j = 0;
97  unsigned int n_neighs = 0;
98  bool stopWavePropagation = false;
99 
100  // Algorithm initialization
101  for (unsigned int &i: init_points_) { // For each initial point
102  grid_->getCell(i).setArrivalTime(0);
103  // Include heuristics if necessary.
104  if (heurStrategy_ == TIME)
105  grid_->getCell(i).setHeuristicTime( getPrecomputedDistance(i)/grid_->getCell(i).getVelocity() );
106  else if (heurStrategy_ == DISTANCE)
107  grid_->getCell(i).setHeuristicTime( getPrecomputedDistance(i) );
108  narrow_band_.push( &(grid_->getCell(i)) );
109  }
110 
111  // Main loop.
112  unsigned int idxMin = 0;
113  while (!stopWavePropagation && !narrow_band_.empty()) {
114  idxMin = narrow_band_.popMinIdx();
115  n_neighs = grid_->getNeighbors(idxMin, neighbors_);
116  grid_->getCell(idxMin).setState(FMState::FROZEN);
117  for (unsigned int s = 0; s < n_neighs; ++s) {
118  j = neighbors_[s];
119  if ((grid_->getCell(j).getState() == FMState::FROZEN) || grid_->getCell(j).isOccupied())
120  continue;
121  else {
122  double new_arrival_time = solveEikonal(j);
123 
124  // Include heuristics if necessary.
125  if (heurStrategy_ == TIME)
126  grid_->getCell(j).setHeuristicTime( getPrecomputedDistance(j)/grid_->getCell(j).getVelocity() );
127  else if (heurStrategy_ == DISTANCE)
128  grid_->getCell(j).setHeuristicTime( getPrecomputedDistance(j) );
129 
130  // Updating narrow band if necessary.
131  if (grid_->getCell(j).getState() == FMState::NARROW) {
132  if (utils::isTimeBetterThan(new_arrival_time, grid_->getCell(j).getArrivalTime())) {
133  grid_->getCell(j).setArrivalTime(new_arrival_time);
134  narrow_band_.increase( &(grid_->getCell(j)) );
135  }
136  }
137  else {
138  grid_->getCell(j).setState(FMState::NARROW);
139  grid_->getCell(j).setArrivalTime(new_arrival_time);
140  narrow_band_.push( &(grid_->getCell(j)) );
141  } // neighbors_ open.
142  } // neighbors_ not frozen.
143  } // For each neighbor.
144 
145  if (idxMin == goal_idx_)
146  stopWavePropagation = true;
147  } // while narrow band not empty
148  }
149 
152  void setHeuristics
153  (HeurStrategy h) {
154  if (h && int(goal_idx_)!=-1) {
155  heurStrategy_ = h;
156  grid_->idx2coord(goal_idx_, heur_coord_);
157  if (!precomputed_)
159  }
160  }
161 
163  HeurStrategy getHeuristics
164  () const {
165  return heurStrategy_;
166  }
167 
168  virtual void clear
169  () {
170  narrow_band_.clear();
171  distances_.clear();
172  precomputed_ = false;
173  }
174 
175  virtual void reset
176  () {
178  narrow_band_.clear();
179  }
180 
182  virtual void precomputeDistances
183  () {
184  distances_.reserve(grid_->size());
185  std::array <unsigned int, grid_t::getNDims()> coords;
186  double dist = 0;
187 
188  for (size_t i = 0; i < grid_->size(); ++i)
189  {
190  dist = 0;
191  grid_->idx2coord(i, coords);
192 
193  for (size_t j = 0; j < coords.size(); ++j)
194  dist += coords[j]*coords[j];
195 
196  distances_[i] = std::sqrt(dist);
197  }
198  precomputed_ = true;
199  }
200 
203  virtual double getPrecomputedDistance
204  (const unsigned int idx) {
205  std::array <unsigned int, grid_t::getNDims()> position, distance;
206  grid_->idx2coord(idx, position);
207 
208  for (unsigned int i = 0; i < grid_t::getNDims(); ++i)
209  distance[i] = utils::absUI(position[i] - heur_coord_[i]);
210 
211  unsigned int idx_dist;
212  grid_->coord2idx(distance, idx_dist);
213 
214  return distances_[idx_dist];
215  }
216 
217  virtual void printRunInfo
218  () const {
219  console::info("Fast Marching Method");
220  std::cout << '\t' << name_ << '\n'
221  << '\t' << "Heuristic type: " << heurStrategy_ << '\n'
222  << '\t' << "Elapsed time: " << time_ << " ms\n";
223  }
224 
225 
227  protected:
236 
237  private:
239  heap_t narrow_band_;
240 
242  HeurStrategy heurStrategy_;
243 
245  std::vector<double> distances_;
246 
249 
251  std::array <unsigned int, grid_t::getNDims()> heur_coord_;
252 };
253 
254 #endif /* FMM_HPP_*/
Abstract class that serves as interface for the actual EikonalSolvers implemented. It requires (at least) the computeInternal method to be implemented,.
virtual void computeInternal()
Actual method that implements FMM.
Definition: fmm.hpp:92
heap_t narrow_band_
Instance of the heap used.
Definition: fmm.hpp:239
double time_
Time elapsed by the compute method.
Definition: solver.hpp:237
std::array< unsigned int, grid_t::getNDims()> heur_coord_
Goal coord, goal of the second wave propagation (actually the initial point of the path)...
Definition: fmm.hpp:251
virtual void setup()
Checks that the solver is ready to run. Sets the grid unclean.
Definition: solver.hpp:94
bool precomputed_
Flag to indicate if distances_ is already computed.
Definition: fmm.hpp:248
std::array< unsigned int, 2 *grid_t::getNDims()> neighbors_
Auxiliar array which stores the neighbor of each iteration of the computeFM() function.
virtual void clear()
Clears the solver, it is not recommended to be used out of the destructor.
Definition: fmm.hpp:169
virtual double solveEikonal(const int &idx)
Solves nD Eikonal equation for cell idx. If heuristics are activated, it will add the estimated trave...
FMM(HeurStrategy h=NOHEUR)
Definition: fmm.hpp:67
static unsigned int absUI(int a)
An user-implemented absolute value function for integer values.
Definition: utils.h:38
grid_t * grid_
Grid container.
Definition: solver.hpp:219
static void info(const std::string &val)
virtual void precomputeDistances()
Computes euclidean distance between goal and rest of cells.
Definition: fmm.hpp:183
std::vector< unsigned int > init_points_
Initial index.
Definition: solver.hpp:228
std::string name_
Solver name.
Definition: solver.hpp:222
virtual void setup()
Executes EikonalSolver setup and sets maximum size for the narrow band.
Definition: fmm.hpp:79
virtual double getPrecomputedDistance(const unsigned int idx)
Extracts the euclidean distance calculated from precomputeDistances function distance between two pos...
Definition: fmm.hpp:204
void setHeuristics(HeurStrategy h)
Set heuristics flag. True is activated. It will precompute distances if not done already.
Definition: fmm.hpp:153
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
HeurStrategy heurStrategy_
Flag to activate heuristics and corresponding strategy.
Definition: fmm.hpp:242
bool setup_
Setup status.
Definition: solver.hpp:225
virtual void reset()
Clears temporal data, so it is ready to run again.
Definition: fmm.hpp:176
unsigned int goal_idx_
Goal index.
Definition: solver.hpp:231
static void warning(const std::string &val)
std::vector< double > distances_
Stores the precomputed heuristic distances.
Definition: fmm.hpp:245
HeurStrategy getHeuristics() const
Returns heuristics flag.
Definition: fmm.hpp:164
Implements the Fast Marching Method (FMM).
Definition: fmm.hpp:64
virtual void reset()
Clears temporal data, so it is ready to run again.
Definition: solver.hpp:176