void Spice::ComputeSolarLongitude(double et) { NaifStatus::CheckErrors(); if (iString(Target()).UpCase() == "SKY") { p_solarLongitude = -999.0; return; } if (p_bodyRotation->IsCached()) return; double tipm[3][3], npole[3]; char frameName[32]; SpiceInt frameCode; SpiceBoolean found; cidfrm_c (p_spkBodyCode, sizeof(frameName), &frameCode, frameName, &found); if ( found ) { pxform_c("J2000",frameName,et,tipm); } else { tipbod_c("J2000",p_spkBodyCode,et,tipm); } for (int i=0; i<3; i++) { npole[i] = tipm[2][i]; } double state[6], lt; spkez_c(p_spkBodyCode,et,"J2000","NONE",10,state,<); double uavel[3]; ucrss_c(state,&state[3],uavel); double x[3], y[3], z[3]; vequ_c(uavel,z); ucrss_c(npole,z,x); ucrss_c(z,x,y); double trans[3][3]; for (int i=0; i<3; i++) { trans[0][i] = x[i]; trans[1][i] = y[i]; trans[2][i] = z[i]; } spkez_c(10,et,"J2000","LT+S",p_spkBodyCode,state,<); double pos[3]; mxv_c(trans,state,pos); double radius, ls, lat; reclat_c(pos,&radius,&ls,&lat); ls *= 180.0 / Isis::PI; if (ls < 0.0) ls += 360.0; else if (ls > 360.0) ls -= 360.0; p_solarLongitude = ls; NaifStatus::CheckErrors(); }
//function to find the body state vector at epoch int body::locate_body(const double& epoch, double* state, const bool& need_deriv, missionoptions* options) { double DT, n, M, E, V[6]; switch (body_ephemeris_source) { case 1: //SPICE double LT_dump; spkez_c(spice_ID, epoch - (51544.5 * 86400.0), "J2000", "NONE", this->central_body_spice_ID, state, <_dump); if (need_deriv) { double statepert[6]; spkez_c(spice_ID, epoch - (51544.5 * 86400.0) + 10.0, "J2000", "NONE", this->central_body_spice_ID, statepert, <_dump); state[6] = (statepert[3] - state[3]) / (10.0); state[7] = (statepert[4] - state[4]) / (10.0); state[8] = (statepert[5] - state[5]) / (10.0); } break; case 0: //static ephemeris //TODO static ephemeris is not ready! //note, always should give in Earth equatorial J2000 coordinates for internal processing DT = ( epoch - this->reference_epoch ); if (this->SMA > 0.0) n = sqrt(this->universe_mu / (this->SMA*this->SMA*this->SMA)); else n = sqrt(this->universe_mu / (-this->SMA*this->SMA*this->SMA)); M = this->MA + n*DT; M = fmod(M, 2 * EMTG::math::PI); E = Kepler::KeplerLaguerreConway(this->ECC, M); V[0] = this->SMA; V[1] = this->ECC; V[2] = this->INC; V[3] = this->RAAN; V[4] = this->AOP; true_anomaly = 2.0*atan(sqrt((1.0 + this->ECC) / (1.0 - this->ECC))*tan(E / 2.0)); V[5] = true_anomaly; COE2inertial(V, this->universe_mu, state); if (need_deriv) { double r = sqrt(state[0]*state[0] + state[1]*state[1] + state[2]*state[2]); double r3 = r*r*r; state[6] = -universe_mu/r3 * state[0]; state[7] = -universe_mu/r3 * state[1]; state[8] = -universe_mu/r3 * state[2]; } break; default: cout << "Invalid ephemeris source " << body_ephemeris_source << " for object " << name << endl; cout << "Program halted. Press enter to quit." << endl; #ifndef BACKGROUND_MODE cin.ignore(); #endif } return 0; }
//function to load new data into the body void body::load_body_data(const int& ibody_code, const string& iname, const string& ishortname, const int& ispice_ID, const double& imininum_altitude, const double& imass, const double& iradius, const double& iepoch, vector<double>& ireference_angles, vector<double>& iclassical_orbit_elements, const double& iuniverse_mu, const int& icentral_body_SPICE_ID, const string& icentral_body_name, const double& icentral_body_radius, missionoptions* options) { //copy information from the inputs into the body this->name = iname; this->short_name = ishortname; this->universe_mu = iuniverse_mu; this->body_code = ibody_code; this->central_body_spice_ID = icentral_body_SPICE_ID; this->central_body_name = icentral_body_name; this->central_body_radius = icentral_body_radius; this->spice_ID = ispice_ID; this->minimum_safe_flyby_altitude = imininum_altitude; this->mass = imass; this->radius = iradius; this->reference_epoch = iepoch; this->SMA = iclassical_orbit_elements[0]; this->ECC = iclassical_orbit_elements[1]; this->INC = iclassical_orbit_elements[2] * EMTG::math::PI / 180.0; this->RAAN = iclassical_orbit_elements[3] * EMTG::math::PI / 180.0; this->AOP = iclassical_orbit_elements[4] * EMTG::math::PI / 180.0; this->MA = iclassical_orbit_elements[5] * EMTG::math::PI / 180.0; //compute additional values mu = options->G * mass; if (ECC < 0.2) r_SOI = SMA * pow(mu / universe_mu, 0.4); else r_SOI = SMA * (1 - ECC) * pow(mu / (3.0 * universe_mu), 0.333333333333333333333333); //determine which ephemeris to draw from if (options->ephemeris_source == 0) { body_ephemeris_source = 0; //use static ephemeris ephemeris_start_date = -0; ephemeris_end_date = 1e+10; } else if (options->ephemeris_source == 1) { //first, check to see if the body exists in the currently loaded SPICE kernels double temp_state[6]; double LT_dump; spkez_c (spice_ID, reference_epoch - (51544.5 * 86400.0), "J2000", "NONE", central_body_spice_ID, temp_state, <_dump); if (failed_c()) reset_c(); if (fabs(temp_state[0]) > 1.0e-6 && fabs(temp_state[0]) < 1.0e+50) { body_ephemeris_source = 1; //body can be located using SPICE } else { cout << "Warning, body " << name << " does not have a SPICE ephemeris file." << endl; body_ephemeris_source = 0; //use static ephemeris ephemeris_start_date = 0; ephemeris_end_date = 1e+10; } } J2000_body_equatorial_frame.initialize(ireference_angles[0], ireference_angles[1], ireference_angles[2], ireference_angles[3], ireference_angles[4], ireference_angles[5]); }