00001
00012 #ifndef SPACEGRID_HPP_
00013 #define SPACEGRID_HPP_
00014
00015
00016 #include <vector>
00017 #include <map>
00018 #include "kernel/jafarDebug.hpp"
00019 #include "jmath/jblas.hpp"
00020 #include "jmath/misc.hpp"
00021 #include "jmath/angle.hpp"
00022
00023
00024 namespace jafar {
00025 namespace rtslam {
00026
00027
00028
00029
00030
00031
00032
00033
00034
00042 template<class Cell>
00043 class SphericalGrid
00044 {
00045 protected:
00046 struct Index
00047 {
00048 int theta, phi, r;
00049 Index(int theta, int phi, int r): theta(theta), phi(phi), r(r) {}
00050 bool operator<(Index const & a) const
00051 { return (theta == a.theta ? (phi == a.phi ? r < a.r : phi < a.phi) : theta < a.theta); }
00052 };
00053
00054 double angularRes;
00055 double distInit;
00056 double distFactor;
00057 int nDist;
00058 double phiFactor;
00059
00060 public:
00061 std::map<Index, Cell> map;
00062 typedef typename std::map<Index, Cell>::iterator iterator;
00063 public:
00064
00065 SphericalGrid(double angularRes, double distInit, double distFactor, int nDist, double phiFactor);
00066
00067 void rebuild(double angularRes, double distInit, double distFactor, int nDist, double phiFactor);
00068 Cell* getCell(jblas::vec3 pos, bool create = false);
00069 void downRes(double factor);
00070
00071 };
00072
00073
00074
00075
00076
00077
00078
00079
00080 template <class Cell>
00081 SphericalGrid<Cell>::SphericalGrid(double angularRes, double distInit, double distFactor, int nDist, double phiFactor)
00082 {
00083 rebuild(angularRes, distInit, distFactor, nDist, phiFactor);
00084 }
00085
00086
00087 template <class Cell>
00088 void SphericalGrid<Cell>::rebuild(double angularRes, double distInit, double distFactor, int nDist, double phiFactor)
00089 {
00090 this->angularRes = angularRes;
00091 this->distInit = distInit;
00092 this->distFactor = distFactor;
00093 this->nDist = nDist;
00094 this->phiFactor = phiFactor;
00095
00096
00097 }
00098
00099
00100 template <class Cell>
00101 Cell* SphericalGrid<Cell>::getCell(jblas::vec3 pos, bool create)
00102 {
00103 double theta = jmath::radToDeg(std::atan2(pos(0), pos(1)));
00104 double phi = jmath::radToDeg(std::atan2(pos(2), ublas::norm_2(ublas::subrange(pos,0,2))));
00105 double r = ublas::norm_2(pos);
00106
00107
00108 double ang_res = angularRes;
00109 int r_i = nDist-1;
00110 double dist = distInit;
00111 for(int i = 0; i < nDist-1; ++i) { if (r < dist) { r_i = i; break; } dist *= distFactor; ang_res *= phiFactor; }
00112
00113 int phi_size = jmath::round(180./ang_res);
00114 if (phi_size < 1) phi_size = 1;
00115 ang_res = 180./phi_size;
00116 int phi_i = (int)((phi+90.)/ang_res+0.5);
00117
00118 double phi1 = -90.+((double)(phi_size/2)-0.5)*ang_res;
00119 double phi2 = -90.+((double)(phi_size/2)+0.5)*ang_res;
00120 double ref_area = 2*M_PI*(sin(phi2*M_PI/180.)-sin(phi1*M_PI/180.)) / (phi_size*2);
00121 phi1 = (phi_i == 0 ? -90. : -90.+((double)(phi_i)-0.5)*ang_res);
00122 phi2 = (phi_i == phi_size ? 90. : -90.+((double)(phi_i)+0.5)*ang_res);
00123 int theta_size = jmath::round(2*M_PI*(sin(phi2*M_PI/180.)-sin(phi1*M_PI/180.)) / ref_area);
00124 if (theta_size < 1) theta_size = 1;
00125 ang_res = 360./theta_size;
00126 int theta_i = (int)((theta+180.-1e-6)/ang_res);
00127
00128
00129 JFR_ASSERT(r_i >= 0 && r_i < nDist, "r_i out of bounds " << r_i << " | " << nDist);
00130 JFR_ASSERT(phi_i >= 0 && phi_i < phi_size+1, "phi_i out of bounds " << phi_i << " | " << phi_size+1);
00131 JFR_ASSERT(theta_i >= 0 && theta_i < theta_size, "theta_i out of bounds " << theta_i << " | " << theta_size);
00132
00133 if (create)
00134 return &(map[Index(theta_i, phi_i, r_i)]);
00135 else
00136 {
00137 typename std::map<Index,Cell>::iterator it = map.find(Index(theta_i, phi_i, r_i));
00138 return (it == map.end() ? NULL : &(it->second));
00139 }
00140 }
00141
00142
00143 template <class Cell>
00144 void SphericalGrid<Cell>::downRes(double factor)
00145 {
00146 rebuild(angularRes*factor, distInit*factor, distFactor*factor, nDist, phiFactor*factor);
00147 }
00148
00149
00150 }}
00151
00152 #endif