Go to the documentation of this file.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 #ifndef DLUX_GLOBAL_PLANNER_KERNEL_FUNCTION_H
00036 #define DLUX_GLOBAL_PLANNER_KERNEL_FUNCTION_H
00037 
00038 #include <dlux_global_planner/potential.h>
00039 
00040 namespace dlux_global_planner
00041 {
00042 
00043 
00044 
00045 enum class CardinalDirection
00046 {
00047   STATIONARY = 0,  
00048   NORTH = 1,       
00049   SOUTH = 2,       
00050   WEST = 4,        
00051   NORTHWEST = 5,   
00052   SOUTHWEST = 6,   
00053   EAST = 8,        
00054   NORTHEAST = 9,   
00055   SOUTHEAST = 10   
00056 };
00057 
00058 inline CardinalDirection operator +(CardinalDirection a, CardinalDirection b)
00059 {
00060   return static_cast<CardinalDirection>(static_cast<int>(a) + static_cast<int>(b));
00061 }
00062 
00063 inline bool operator &(CardinalDirection a, CardinalDirection b)
00064 {
00065   return (static_cast<int>(a) & static_cast<int>(b)) > 0;
00066 }
00067 
00083 static float calculateKernel(const PotentialGrid& potential_grid, unsigned char cost, unsigned int x, unsigned int y,
00084                              CardinalDirection* upstream = nullptr)
00085 {
00086   
00087   
00088   float south_p = y > 0                              ? potential_grid(x, y - 1) : HIGH_POTENTIAL;
00089   float north_p = y < potential_grid.getHeight() - 1 ? potential_grid(x, y + 1) : HIGH_POTENTIAL;
00090   float west_p =  x > 0                              ? potential_grid(x - 1, y) : HIGH_POTENTIAL;
00091   float east_p =  x < potential_grid.getWidth() - 1  ? potential_grid(x + 1, y) : HIGH_POTENTIAL;
00092 
00093   
00094   
00095   
00096   float pa, pc;
00097   CardinalDirection xdir, ydir;
00098   if (north_p < south_p)
00099   {
00100     pa = north_p;
00101     ydir = CardinalDirection::NORTH;
00102   }
00103   else
00104   {
00105     pa = south_p;
00106     ydir = CardinalDirection::SOUTH;
00107   }
00108 
00109   if (west_p < east_p)
00110   {
00111     pc = west_p;
00112     xdir = CardinalDirection::WEST;
00113   }
00114   else
00115   {
00116     pc = east_p;
00117     xdir = CardinalDirection::EAST;
00118   }
00119 
00120   
00121   float dc = pc - pa;  
00122   CardinalDirection mindir;
00123 
00124   
00125   if (pa == HIGH_POTENTIAL || dc < 0)          
00126   {
00127     dc = -dc;
00128     pa = pc;
00129     mindir = xdir;
00130   }
00131   else
00132   {
00133     mindir = ydir;
00134   }
00135 
00136   
00137   if (std::isinf(pa))
00138   {
00139     if (upstream)
00140       *upstream = CardinalDirection::STATIONARY;
00141     return pa;
00142   }
00143 
00144   
00145   if (dc >= cost)
00146   {
00147     
00148     if (upstream)
00149       *upstream = mindir;
00150     return pa + cost;
00151   }
00152   else
00153   {
00154     
00155     float dx = dc / cost;
00156     float v = -0.2301 * dx * dx + 0.5307 * dx + 0.7040;
00157     if (upstream)
00158       *upstream = xdir + ydir;
00159     return pa + cost * v;
00160   }
00161 }
00162 
00163 
00164 }  
00165 
00166 #endif  // DLUX_GLOBAL_PLANNER_KERNEL_FUNCTION_H