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 #ifndef GEOUTILITIES_HPP_
00035 #define GEOUTILITIES_HPP_
00036 #define _USE_MATH_DEFINES
00037 #include <utility>
00038 #include <math.h>
00039 #include <Eigen/Dense>
00040
00041 namespace labust
00042 {
00046 namespace tools
00047 {
00049 static const double deg2rad = M_PI/180;
00050 static const double rad2deg = 180/M_PI;
00051 static const double radius = 6378137;
00052 static const double ratio = 0.99664719;
00053
00059 inline double mpdlat(double lat)
00060 {
00061 return (111132.954 - 559.822*cos(2*lat*deg2rad) + 1.175*cos(4*lat*deg2rad));
00062 };
00068 inline double mpdlon(double lat)
00069 {
00070 return (radius*cos(atan(ratio*tan(lat*deg2rad)))*deg2rad);
00071 };
00081 inline std::pair<double,double> deg2meter(double difflat, double difflon, double lat)
00082 {
00083 return std::pair<double,double>(difflat*mpdlat(lat),difflon*mpdlon(lat));
00084 }
00094 inline std::pair<double,double> meter2deg(double x, double y, double lat)
00095 {
00096 return std::pair<double,double>(x/mpdlat(lat),y/mpdlon(lat));
00097 };
00098
00099
00100
00111
00112 static const double a = 6378137;
00114 static const double f = 1/298.257223563;
00116 static const double b = a*(1-f);
00118 static const double esq = 2*f-f*f;
00120 static const double ecsq = (a*a - b*b)/(b*b);
00121
00122
00129 inline Eigen::Vector3d geodetic2ecef(const Eigen::Vector3d& geo)
00130 {
00131 enum {lon=0, lat, alt};
00132 double rlat(geo(lat)*M_PI/180);
00133 double rlon(geo(lon)*M_PI/180);
00134 double R = a/sqrt(1-esq*sin(rlat)*sin(rlat));
00135
00136 return Eigen::Vector3d(
00137 (R+geo(alt))*cos(rlat)*cos(rlon),
00138 (R+geo(alt))*cos(rlat)*sin(rlon),
00139 (R+geo(alt) - esq*R)*sin(rlat));
00140 }
00141
00149 inline Eigen::Vector3d ecef2geodetic(const Eigen::Vector3d& xyz)
00150 {
00151 double x(xyz(0)), y(xyz(1)), z(xyz(2));
00152
00153 double r = sqrt(x*x + y*y);
00154 double F = 54*(b*b)*(z*z);
00155 double G = r*r + (1-esq)*z*z - esq*(a*a - b*b);
00156 double c = esq*esq*F*r*r/(G*G*G);
00157 double s = cbrt(1+c+sqrt(c*c+2*c));
00158 double P = F/(3*(s+1/s+1)*(s+1/s+1)*G*G);
00159 double Q = sqrt(1+2*esq*esq*P);
00160 double r0 = -P*esq*r/(1+Q) + sqrt(0.5*a*a*(1+1/Q)
00161 - P*(1-esq)*z*z/(Q*(1+Q)) - 0.5*P*r*r);
00162 double re = r-esq*r0;
00163 double U = sqrt(re*re + z*z);
00164 double V = sqrt(re*re + (1-esq)*z*z);
00165 double z0 = b*b*z/(a*V);
00166
00167 return Eigen::Vector3d(
00168 atan2(y,x)*180/M_PI,
00169 atan((z+ecsq*z0)/r)*180/M_PI,
00170 U*(1-b*b/(a*V)));
00171 }
00172
00174 inline Eigen::Matrix3d nedrot(const Eigen::Vector3d& geo)
00175 {
00176 enum {lon=0, lat, alt};
00177 double rlat(geo(lat)*M_PI/180);
00178 double rlon(geo(lon)*M_PI/180);
00179
00180
00181
00182
00183
00184
00185 double pitch = M_PI/2 + rlat;
00186 double yaw = -rlon;
00187
00188 Eigen::Matrix3d rz, ry;
00189 rz << cos(yaw), sin(yaw),0,
00190 -sin(yaw), cos(yaw), 0,
00191 0, 0, 1;
00192 ry << cos(pitch), 0, -sin(pitch),
00193 0,1,0,
00194 sin(pitch), 0, cos(pitch);
00195
00196
00197 return rz*ry;
00198 }
00199
00201 inline Eigen::Matrix3d nwurot(const Eigen::Vector3d& geo)
00202 {
00203 enum {lon=0, lat, alt};
00204 double rlat(geo(lat)*M_PI/180);
00205 double rlon(geo(lon)*M_PI/180);
00206
00207
00208
00209
00210
00211
00212 double roll = M_PI/2 - rlat;
00213 double yaw = M_PI+rlon;
00214
00215 Eigen::Matrix3d rz, rx;
00216 rz << cos(yaw), sin(yaw),0,
00217 -sin(yaw), cos(yaw), 0,
00218 0, 0, 1;
00219 rx << 1, 0 ,0,
00220 0, cos(roll), sin(roll),
00221 0, -sin(roll),cos(roll);
00222
00223
00224 return rz*rx;
00225 }
00226
00230 inline Eigen::Vector3d ecef2ned(const Eigen::Vector3d& xyz, const Eigen::Vector3d& geo)
00231 {
00232 Eigen::Vector3d xyz0 = geodetic2ecef(geo);
00233 Eigen::Matrix3d mrot = nedrot(geo);
00234 return mrot.transpose() * (xyz - xyz0);
00235 }
00236
00240 inline Eigen::Vector3d ned2ecef(const Eigen::Vector3d& ned, const Eigen::Vector3d& geo)
00241 {
00242 Eigen::Vector3d xyz0 = geodetic2ecef(geo);
00243 Eigen::Matrix3d mrot = nedrot(geo);
00244 return mrot * ned + xyz0;
00245 }
00246 }
00247 }
00248
00249 #endif