00001 #pragma ident "$Id: AtmosphericDrag.cpp 2457 2010-08-18 14:20:12Z coandrei $"
00002
00003
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "AtmosphericDrag.hpp"
00034 #include "ReferenceFrames.hpp"
00035
00036 namespace gpstk
00037 {
00038
00039 const double AtmosphericDrag::rho_0[CIRA_SIZE] =
00040 {
00041 1.057E-03, 3.206E-04, 8.770E-05, 1.905E-05, 3.396E-06, 5.297E-07,
00042 9.661E-08, 2.438E-08, 8.484E-09, 3.845E-09, 2.070E-09, 5.464E-10,
00043 2.789E-10, 7.248E-11, 2.418E-11, 9.158E-12, 3.725E-12, 1.585E-12,
00044 6.967E-13, 1.454E-13, 3.614E-14, 1.170E-14, 5.245E-15, 3.019E-15
00045 };
00046
00047 const double AtmosphericDrag::H[CIRA_SIZE] =
00048 {
00049 8.382, 7.714, 6.549, 5.799, 5.382, 5.877,
00050 7.263, 9.473, 12.636, 16.149, 22.523, 29.740,
00051 37.105, 45.546, 53.628, 53.298, 58.515, 60.828,
00052 63.822, 71.835, 88.667, 124.64, 181.05, 268.0
00053 };
00054
00055 const double AtmosphericDrag::h0[CIRA_SIZE] =
00056 {
00057 50, 60, 70, 80, 90, 100,
00058 110, 120, 130, 140, 150, 180,
00059 200, 250, 300, 350, 400, 450,
00060 500, 600, 700, 800, 900, 1000
00061 };
00062
00063
00064
00065 void AtmosphericDrag::doCompute(UTCTime utc, EarthBody& rb, Spacecraft& sc)
00066 {
00067
00068 double omega_e = 7.292115E-05;
00069
00070
00071 Vector<double> r = sc.R();
00072 Vector<double> v = sc.V();
00073
00074 const double cd = sc.getDragCoeff();
00075 const double area = sc.getDragArea();
00076 const double mass = sc.getDryMass();
00077
00078 double rmag = norm(r);
00079 double beta = cd * area / mass;
00080
00081
00082 double rho = computeDensity(utc, rb, r, v);
00083
00084
00085
00086
00087
00088 Vector<double> we(3,0.0);
00089 we(2)= omega_e;
00090
00091 Vector<double> wxr = cross(we,r);
00092 Vector<double> vr = v - wxr;
00093 double vrmag = norm(vr);
00094
00095
00096 double coeff = -0.5 * beta * rho;
00097 double coeff2 = coeff * vrmag;
00098
00099
00100 a = vr * coeff2;
00101
00102
00103
00104
00105
00106 Matrix<double> tr(3,1,0.0);
00107 tr(0,0)=vr(0);
00108 tr(1,0)=vr(1);
00109 tr(2,0)=vr(2);
00110
00111 Matrix<double> vrvrt = tr*transpose(tr);
00112 vrvrt = vrvrt / vrmag;
00113
00114 double eye3[3*3] = {1,0,0,0,1,0,0,0,1};
00115 Matrix<double> vrm(3,3,0.0);
00116 vrm = eye3;
00117
00118 vrm = vrm * vrmag;
00119 da_dv = (vrvrt + vrm) * coeff;
00120
00121
00122
00123 da_dr.resize(3,3,0.0);
00124
00125 Matrix<double> X(3,3,0.0);
00126 X(0,1) = -we(2);
00127 X(0,2) = +we(1);
00128 X(1,0) = +we(2);
00129 X(1,2) = -we(0);
00130 X(2,0) = -we(1);
00131 X(2,1) = +we(0);
00132
00133 Matrix<double> part1(3,3,0.0);
00134 Matrix<double> part2(3,3,0.0);
00135
00136
00137
00138 Matrix<double> N = ReferenceFrames::J2kToTODMatrix(utc);
00139
00140
00141 Vector<double> r_tod = N * r;
00142 Position geoidPos(r_tod(0),r_tod(1),r_tod(3));
00143
00144
00145 double height = geoidPos.getAltitude()/1000.0;
00146
00147 const int n = CIRA_SIZE; ;
00148
00149 int bracket = 0;
00150
00151 if (height >= h0[n-1])
00152 {
00153 bracket = n - 1;
00154 }
00155 else
00156 {
00157 for (int i = 0; i < (n-1); i++)
00158 {
00159 if ((height >= h0[i]) && (height < h0[i+1]))
00160 {
00161 bracket = i;
00162 }
00163 }
00164 }
00165
00166 double Hh = H[bracket];
00167 double coeff4 = -1.0 / (Hh * rmag);
00168
00169 Vector<double> drhodr = r*coeff4;
00170
00171 Matrix<double> tr2(3,1,0.0);
00172 tr2(0,0) = drhodr(0);
00173 tr2(1,0) = drhodr(1);
00174 tr2(2,0) = drhodr(2);
00175
00176 part1 = tr*transpose(tr2);
00177 part1 = part1*coeff2;
00178
00179
00180 part2 =-da_dv*X;
00181 da_dr = part1-part2;
00182
00183
00184 double coeff3 = coeff2 / cd;
00185 this->dadcd = vr*coeff3;
00186
00187 this->da_dcd(0,0) = dadcd(0);
00188 this->da_dcd(1,0) = dadcd(1);
00189 this->da_dcd(2,0) = dadcd(2);
00190
00191 }
00192
00193 }
00194
00195
00196