kernel_function.h
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2018, Locus Robotics
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of the copyright holder nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
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   Flag Mask Values such that NORTH + WEST = NORTHWEST
00044 */
00045 enum class CardinalDirection
00046 {
00047   STATIONARY = 0,  // 0000
00048   NORTH = 1,       // 0001
00049   SOUTH = 2,       // 0010
00050   WEST = 4,        // 0100
00051   NORTHWEST = 5,   // 0101
00052   SOUTHWEST = 6,   // 0110
00053   EAST = 8,        // 1000
00054   NORTHEAST = 9,   // 1001
00055   SOUTHEAST = 10   // 1010
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   // See README.md for more about this calculation
00087   // get neighboring potential values
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   // Find the lowest neighbor on each axis
00094   // pa = min(P(A), P(B)) (aka north_p and south_p)
00095   // pc = min(P(C), P(D)) (aka west_p and east_p)
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   // cost was originally notated hf, h in the README
00121   float dc = pc - pa;  // relative cost between pa, pc
00122   CardinalDirection mindir;
00123 
00124   // In our calculation, we assume P(A) <= P(C), so we flip as needed
00125   if (pa == HIGH_POTENTIAL || dc < 0)          // pc is lowest
00126   {
00127     dc = -dc;
00128     pa = pc;
00129     mindir = xdir;
00130   }
00131   else
00132   {
00133     mindir = ydir;
00134   }
00135 
00136   // If pa is lower and STILL infinite, then we can't calculate a good potential here
00137   if (std::isinf(pa))
00138   {
00139     if (upstream)
00140       *upstream = CardinalDirection::STATIONARY;
00141     return pa;
00142   }
00143 
00144   // calculate new potential
00145   if (dc >= cost)
00146   {
00147     // if the difference is too large, use the "straightforward" calculation
00148     if (upstream)
00149       *upstream = mindir;
00150     return pa + cost;
00151   }
00152   else
00153   {
00154     // Otherwise, interpolate from both neighbors
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 }  // namespace dlux_global_planner
00165 
00166 #endif  // DLUX_GLOBAL_PLANNER_KERNEL_FUNCTION_H


dlux_global_planner
Author(s):
autogenerated on Wed Jun 26 2019 20:09:53