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 #include "space/satellite_element_propagator.hpp"
00035 #include "data/list.hpp"
00036 #include "math/units.hpp"
00037 
00038 #include <cmath>
00039 
00040 using namespace gsgl;
00041 using namespace gsgl::data;
00042 using namespace gsgl::math;
00043 
00044 
00045 namespace periapsis
00046 {
00047 
00048     namespace space
00049     {
00050 
00051         BROKER_DEFINE_CREATOR(periapsis::space::satellite_element_propagator);
00052 
00053         satellite_element_propagator::satellite_element_propagator(const config_record & obj_config)
00054             : propagator(obj_config), has_data(false)
00055         {
00056             get_elements(obj_config[L"satellite_elements"]);
00057         } 
00058 
00059 
00060         satellite_element_propagator::~satellite_element_propagator()
00061         {
00062         } 
00063 
00064 
00065         void satellite_element_propagator::get_elements(const string & str)
00066         {
00067             for (int i = 0; i < 13; ++i)
00068                 data[i] = 0;
00069 
00070             
00071             list<string> tokens = str.split(L" \t");
00072 
00073             int index = 0;
00074             for (list<string>::iterator i = tokens.iter(); i.is_valid(); ++i)
00075             {
00076                 if (!i->is_empty() && index < 13)
00077                 {
00078                     data[index++] = i->to_double();
00079                 }
00080             }
00081 
00082             
00083             if ((has_data = (index == 10 || index == 13)))
00084             {
00085                 for (int i = 2; i < 7; ++i)
00086                 {
00087                     data[i] *= math::DEG2RAD;
00088                 }
00089             }
00090         } 
00091 
00092 
00093         static double calc_E(const double M, const double e_star, const double e)
00094         {
00095             double E_zero = M + e_star * ::sin(M);
00096 
00097             double delta_M;
00098             double delta_E;
00099             double E_old;
00100             double E_new = E_zero;
00101             double tol = 1.0e-6;
00102 
00103             do
00104             {
00105                 E_old = E_new;
00106                 delta_M = M - (E_old - e_star * ::sin(E_old));
00107                 delta_E = delta_M / (1.0 - e * ::cos(E_old));
00108                 E_new = E_old + delta_E;
00109             }
00110             while (delta_E > tol);
00111 
00112             return E_new;
00113         } 
00114 
00115 
00116         
00117         
00118         
00119         
00120         
00121         
00122         
00123 
00124 
00125         
00126         
00127         
00128         
00129         
00130         
00131         
00132         
00133         
00134         
00135         
00136 
00137         
00138         
00139         
00140 
00141 
00142 
00143 
00144         void satellite_element_propagator::update(const double jdn, vector & position, vector & velocity)
00145         {
00146             if (!has_data)
00147                 return;
00148 
00149             
00150             double sats[6];
00151             double days_since_epoch = jdn - 2451545.0;
00152 
00153             for (int i = 0; i < 6; ++i)
00154                 sats[i] = data[i];
00155 
00156             sats[5] += data[6] * days_since_epoch;
00157 
00158             
00159             double cur_elements[6];
00160 
00161             cur_elements[0] = sats[0];                     
00162             cur_elements[1] = sats[1];                     
00163             cur_elements[2] = sats[4];                     
00164             cur_elements[3] = sats[3] + sats[5] + sats[2]; 
00165             cur_elements[4] = sats[5] + sats[2];           
00166             cur_elements[5] = sats[5];                     
00167 
00168             
00169 
00170             
00171             double omega = sats[2]; 
00172             double M = sats[3]; 
00173 
00174             double M_plus = M + math::PI;
00175             
00176             while (M_plus < 0.0)
00177                 M_plus += math::PI * 2.0;
00178             while (M_plus > math::PI * 2.0)
00179                 M_plus -= math::PI * 2.0;
00180 
00181             M = M_plus - math::PI;
00182 
00183             
00184             double n = (cur_elements[3] - (data[3] + data[5] + data[2])) / days_since_epoch;
00185 
00186             
00187             double E = calc_E(M, cur_elements[1] * math::DEG2RAD, cur_elements[1]);
00188 
00189             
00190             double E_dot = n / (1.0f - cur_elements[1] * ::cos(E));
00191 
00192             
00193             double x_prime = cur_elements[0] * (::cos(E) - cur_elements[1]);
00194             double y_prime = cur_elements[0] * (::sqrt(1.0f - cur_elements[1]*cur_elements[1]) * ::sin(E));
00195             double z_prime = 0.0f;
00196 
00197             
00198             double x_dot_prime = cur_elements[0] * ( -::sin(E) * E_dot );
00199             double y_dot_prime = cur_elements[0] * (::sqrt(1.0f - cur_elements[1]*cur_elements[1]) * ::cos(E) * E_dot);
00200 
00201             
00202             double cos_o = ::cos(omega);
00203             double cos_O = ::cos(cur_elements[5]);
00204             double cos_I = ::cos(cur_elements[2]);
00205             double sin_o = ::sin(omega);
00206             double sin_O = ::sin(cur_elements[5]);
00207             double sin_I = ::sin(cur_elements[2]);
00208 
00209             double x = (cos_o*cos_O - sin_o*sin_O*cos_I) * x_prime + (-sin_o*cos_O - cos_o*sin_O*cos_I) * y_prime;
00210             double y = (cos_o*sin_O + sin_o*cos_O*cos_I) * x_prime + (-sin_o*sin_O + cos_o*cos_O*cos_I) * y_prime;
00211             double z = (sin_o*sin_I)*x_prime + (cos_o*sin_I)*y_prime;
00212 
00213             
00214             double x_dot = (cos_o*cos_O - sin_o*sin_O*cos_I) * x_dot_prime + (-sin_o*cos_O - cos_o*sin_O*cos_I) * y_dot_prime;
00215             double y_dot = (cos_o*sin_O + sin_o*cos_O*cos_I) * x_dot_prime + (-sin_o*sin_O + cos_o*cos_O*cos_I) * y_dot_prime;
00216             double z_dot = (sin_o*sin_I)*x_dot_prime + (cos_o*sin_I)*y_dot_prime;
00217 
00218             
00219             x *= units::METERS_PER_KILOMETER;
00220             y *= units::METERS_PER_KILOMETER;
00221             z *= units::METERS_PER_KILOMETER;
00222 
00223             
00224             x_dot *= units::METERS_PER_KILOMETER / units::SECONDS_PER_DAY;
00225             y_dot *= units::METERS_PER_KILOMETER / units::SECONDS_PER_DAY;
00226             z_dot *= units::METERS_PER_KILOMETER / units::SECONDS_PER_DAY;
00227 
00228             
00229             position.get_x() = static_cast<gsgl::real_t>(x);
00230             position.get_y() = static_cast<gsgl::real_t>(y);
00231             position.get_z() = static_cast<gsgl::real_t>(z);
00232             position.get_w() = 1;
00233 
00234             velocity.get_x() = static_cast<gsgl::real_t>(x_dot);
00235             velocity.get_y() = static_cast<gsgl::real_t>(y_dot);
00236             velocity.get_z() = static_cast<gsgl::real_t>(z_dot);
00237             velocity.get_w() = 1;
00238         } 
00239 
00240     } 
00241 
00242 }