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
00036
00037 #include <math.h>
00038 #include "constants.h"
00039 #include "geodesy.h"
00040 #include "navigation.h"
00041
00042 void NAVIGATION_ComputeDerivativesOf_Range_WithRespectTo_XYZ(
00043 const double x,
00044 const double y,
00045 const double z,
00046 const double satX,
00047 const double satY,
00048 const double satZ,
00049 double* dPdx,
00050 double* dPdy,
00051 double* dPdz,
00052 double* range )
00053 {
00054 double dx;
00055 double dy;
00056 double dz;
00057
00058 dx = satX - x;
00059 dy = satY - y;
00060 dz = satZ - z;
00061
00062 *range = sqrt( dx*dx + dy*dy + dz*dz );
00063
00064
00065 *dPdx = -dx / (*range);
00066 *dPdy = -dy / (*range);
00067 *dPdz = -dz / (*range);
00068 }
00069
00070
00071
00072
00073 void NAVIGATION_ComputeDerivativesOf_Range_WithRespectToLatitudeLongitudeHeight(
00074 const double latitude,
00075 const double longitude,
00076 const double height,
00077 const double satX,
00078 const double satY,
00079 const double satZ,
00080 double* dlat,
00081 double* dlon,
00082 double* dhgt,
00083 double* range )
00084 {
00085 double sinlat;
00086 double coslat;
00087 double sinlon;
00088 double coslon;
00089 double dx;
00090 double dy;
00091 double dz;
00092 double x;
00093 double y;
00094 double z;
00095
00096 sinlat = sin(latitude);
00097 coslat = cos(latitude);
00098 sinlon = sin(longitude);
00099 coslon = cos(longitude);
00100
00101 GEODESY_ConvertGeodeticCurvilinearToEarthFixedCartesianCoordinates(
00102 GEODESY_REFERENCE_ELLIPSE_WGS84,
00103 latitude,
00104 longitude,
00105 height,
00106 &x,
00107 &y,
00108 &z );
00109
00110 dx = satX - x;
00111 dy = satY - y;
00112 dz = satZ - z;
00113
00114
00115
00116 dx *= -1.0;
00117 dy *= -1.0;
00118 dz *= -1.0;
00119
00120 *range = sqrt( dx*dx + dy*dy + dz*dz );
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 *dlat = ( -dx*sinlat*coslon - dy*sinlat*sinlon + dz*coslat ) / (*range);
00140 *dlon = ( -dx*sinlon + dy*coslon ) / (*range);
00141 *dhgt = ( dx*coslat*coslon + dy*coslat*sinlon + dz*sinlat ) / (*range);
00142 }
00143
00144
00145
00146
00147
00148
00149
00150 int NAVIGATION_PerformClosedFormPositionSolution_FromPseuodrangeMeasurements(
00151 double p1,
00152 double p2,
00153 double p3,
00154 double p4,
00155 double prc_satclk1,
00156 double prc_satclk2,
00157 double prc_satclk3,
00158 double prc_satclk4,
00159 double x1,
00160 double x2,
00161 double x3,
00162 double x4,
00163 double y1,
00164 double y2,
00165 double y3,
00166 double y4,
00167 double z1,
00168 double z2,
00169 double z3,
00170 double z4,
00171 double* latitude,
00172 double* longitude,
00173 double* height,
00174 double* rx_clock_bias
00175 )
00176 {
00177
00178 double x12, x13, x14;
00179 double y12, y13, y14;
00180 double z12, z13, z14;
00181 double p21, p31, p41;
00182
00183 double k1, k2, k3;
00184 double c1, c2, c3;
00185 double f1, f2, f3;
00186 double m1, m2, m3;
00187
00188 double d1;
00189 double d2;
00190 double detA;
00191 double tmp1;
00192 double tmp2;
00193 double tmp3;
00194
00195 double A[3][3];
00196 double D[3][3];
00197
00198 typedef struct
00199 {
00200 double x;
00201 double y;
00202 double z;
00203 } struct_SOLN;
00204
00205 struct_SOLN s1;
00206 struct_SOLN s2;
00207
00208
00209 p1 = p1 + prc_satclk1;
00210 p2 = p2 + prc_satclk2;
00211 p3 = p3 + prc_satclk3;
00212 p4 = p4 + prc_satclk4;
00213
00214 x12 = x1 - x2;
00215 x13 = x1 - x3;
00216 x14 = x1 - x4;
00217
00218 y12 = y1 - y2;
00219 y13 = y1 - y3;
00220 y14 = y1 - y4;
00221
00222 z12 = z1 - z2;
00223 z13 = z1 - z3;
00224 z14 = z1 - z4;
00225
00226 p21 = p2 - p1;
00227 p31 = p3 - p1;
00228 p41 = p4 - p1;
00229
00230 k1 = x12*x12 + y12*y12 + z12*z12 - p21*p21;
00231 k2 = x13*x13 + y13*y13 + z13*z13 - p31*p31;
00232 k3 = x14*x14 + y14*y14 + z14*z14 - p41*p41;
00233
00234 A[0][0] = 2.0*x12;
00235 A[1][0] = 2.0*x13;
00236 A[2][0] = 2.0*x14;
00237
00238 A[0][1] = 2.0*y12;
00239 A[1][1] = 2.0*y13;
00240 A[2][1] = 2.0*y14;
00241
00242 A[0][2] = 2.0*z12;
00243 A[1][2] = 2.0*z13;
00244 A[2][2] = 2.0*z14;
00245
00246 tmp1 = A[1][1]*A[2][2] - A[2][1]*A[1][2];
00247 tmp2 = A[1][0]*A[2][2] - A[2][0]*A[1][2];
00248 tmp3 = A[1][0]*A[2][1] - A[2][0]*A[1][1];
00249
00250 detA = A[0][0]*tmp1 - A[0][1]*tmp2 + A[0][2]*tmp3;
00251
00252 D[0][0] = tmp1;
00253 D[1][0] = -tmp2;
00254 D[2][0] = tmp3;
00255
00256 D[0][1] = -A[0][1]*A[2][2] + A[2][1]*A[0][2];
00257 D[1][1] = A[0][0]*A[2][2] - A[2][0]*A[0][2];
00258 D[2][1] = -A[0][0]*A[2][1] + A[2][0]*A[0][1];
00259
00260 D[0][2] = A[0][1]*A[1][2] - A[1][1]*A[0][2];
00261 D[1][2] = -A[0][0]*A[1][2] + A[1][0]*A[0][2];
00262 D[2][2] = A[0][0]*A[1][1] - A[1][0]*A[0][1];
00263
00264 c1 = (D[0][0]*p21 + D[0][1]*p31 + D[0][2]*p41) * 2.0 / detA;
00265 c2 = (D[1][0]*p21 + D[1][1]*p31 + D[1][2]*p41) * 2.0 / detA;
00266 c3 = (D[2][0]*p21 + D[2][1]*p31 + D[2][2]*p41) * 2.0 / detA;
00267
00268 f1 = (D[0][0]*k1 + D[0][1]*k2 + D[0][2]*k3) / detA;
00269 f2 = (D[1][0]*k1 + D[1][1]*k2 + D[1][2]*k3) / detA;
00270 f3 = (D[2][0]*k1 + D[2][1]*k2 + D[2][2]*k3) / detA;
00271
00272 m1 = c1*c1 + c2*c2 + c3*c3 - 1.0;
00273 m2 = -2.0*( c1*f1 + c2*f2 + c3*f3 );
00274 m3 = f1*f1 + f2*f2 + f3*f3;
00275
00276 tmp1 = m2*m2 - 4.0*m1*m3;
00277 if( tmp1 < 0 )
00278 {
00279
00280 return FALSE;
00281 }
00282
00283 d1 = ( -m2 + sqrt( tmp1 ) ) * 0.5 / m1;
00284 d2 = ( -m2 - sqrt( tmp1 ) ) * 0.5 / m1;
00285
00286
00287 s1.x = c1*d1 - f1 + x1;
00288 s1.y = c2*d1 - f2 + y1;
00289 s1.z = c3*d1 - f3 + z1;
00290
00291 s2.x = c1*d2 - f1 + x1;
00292 s2.y = c2*d2 - f2 + y1;
00293 s2.z = c3*d2 - f3 + z1;
00294
00295 tmp1 = sqrt( s1.x*s1.x + s1.y*s1.y + s1.z*s1.z );
00296 tmp2 = sqrt( s2.x*s2.x + s2.y*s2.y + s2.z*s2.z );
00297
00298
00299
00300
00301 tmp1 = fabs( tmp1 - 6371000.0 );
00302 tmp2 = fabs( tmp2 - 6371000.0 );
00303
00304 if( tmp2 < tmp1 )
00305 {
00306 s1 = s2;
00307 d1 = d2;
00308 }
00309
00310 *rx_clock_bias = d1;
00311
00312 GEODESY_ConvertEarthFixedCartesianToGeodeticCurvilinearCoordinates(
00313 GEODESY_REFERENCE_ELLIPSE_WGS84,
00314 s1.x, s1.y, s1.z,
00315 latitude, longitude, height );
00316
00317 if( *height < -1500.0 || *height > 18000.0 )
00318 {
00319
00320 return FALSE;
00321 }
00322
00323 return TRUE;
00324 }
00325