//--------------------------------------------------------------------------- float Ionosphere::ElectronDensity(Rvector3 pos2, Rvector3 pos1) { // the fisrt position's latitude and longitude (unit: degree): //real latitude = (real)(GmatMathConstants::PI_OVER_TWO_DEG - acos(pos1.Get(2)/pos1.GetMagnitude())*GmatMathConstants::DEG_PER_RAD); // unit: degree real latitude = (real)(asin(pos1.Get(2)/pos1.GetMagnitude())*GmatMathConstants::DEG_PER_RAD); // unit: degree real longitude = (real)(atan2(pos1.Get(1),pos1.Get(0))*GmatMathConstants::DEG_PER_RAD); // unit: degree // mmag = 0 geographic =1 geomagnetic coordinates integer jmag = 0; // 1; // jf(1:30) =.true./.false. flags; explained in IRISUB.FOR logical jf[31]; for (int i=1; i <= 30; ++i) jf[i] = TRUE_; jf[5] = FALSE_; jf[6] = FALSE_; jf[23] = FALSE_; jf[29] = FALSE_; jf[30] = FALSE_; // jf[21] = FALSE_; // jf[28] = FALSE_; // iy,md date as yyyy and mmdd (or -ddd) // hour decimal hours LT (or UT+25) integer iy = (integer)yyyy; integer md = (integer)mmdd; real hour = (real)hours; // Upper and lower integration limits real hbeg = (real)(pos1.GetMagnitude() - earthRadius); // 0 real hend = hbeg; real hstp = 1.0; integer error = 0; real outf[20*501+1]; real oarr[51]; // iri_sub(&jf[1], &jmag, &latitude, &longitude, &iy, &md, &hour, // &hbeg, &hend, &hstp, &outf[21], &oarr[1], &error); integer ivar = 1; // get attitude result integer iut = 1; // 1 for universal time; 0 for local time # ifdef DEBUG_IONOSPHERE_ELECT_DENSITY MessageInterface::ShowMessage(" .At time = %lf A1Mjd:",epoch); MessageInterface::ShowMessage(" year = %d md = %d hour = %lf h, time type = %s,\n", iy, md, hour, (iut?"Universal":"Local")); MessageInterface::ShowMessage(" At position (x,y,z) = (%lf, %lf, %lf)km in Earth fixed coordinate system: ", pos1[0], pos1[1], pos1[2]); MessageInterface::ShowMessage("(latitude = %lf degree, longitude = %lf degree, attitude = %lf km, ", latitude, longitude, hbeg); MessageInterface::ShowMessage("coordinate system type = %s)\n",(jmag?"Geomagetic":"Geographic")); #endif iri_web(&jmag, &jf[1], &latitude, &longitude, &iy, &md, &iut, &hour, &hbeg, &hbeg, &ivar, &hbeg, &hend, &hstp, &outf[21], &oarr[1], &error); if (error != 0) { MessageInterface::ShowMessage("Ionosphere data files not found\n"); throw new MeasurementException("Ionosphere data files not found\n"); } real density = outf[20+1]; if (density < 0) density = 0; #ifdef DEBUG_IONOSPHERE_ELECT_DENSITY MessageInterface::ShowMessage(" Electron density at that time and location = %le electrons per m3.\n", density); #endif return density; //*(pos2-pos1).GetMagnitude(); }
//------------------------------------------------------------------------------ Integer CoordUtil::ComputeCartToKepl(Real grav, Real r[3], Real v[3], Real *tfp, Real elem[6], Real *ma) { #ifdef DEBUG_CART_TO_KEPL MessageInterface::ShowMessage(wxT("CoordUtil::ComputeCartToKepl called ... \n")); MessageInterface::ShowMessage(wxT(" grav = %12.10f\n"), grav); MessageInterface::ShowMessage(wxT(" KEP_ECC_TOL = %12.10f\n"), GmatOrbitConstants::KEP_ECC_TOL); #endif if (Abs(grav) < 1E-30) return(2); Rvector3 pos(r[0], r[1], r[2]); Rvector3 vel(v[0], v[1], v[2]); // eqn 4.1 Rvector3 angMomentum = Cross(pos, vel); // eqn 4.2 Real h = angMomentum.GetMagnitude(); #ifdef DEBUG_CART_TO_KEPL MessageInterface::ShowMessage( wxT(" in ComputeCartToKepl, pos = %12.10f %12.10f %12.10f \n"), pos[0], pos[1], pos[2]); MessageInterface::ShowMessage( wxT(" in ComputeCartToKepl, vel = %12.10f %12.10f %12.10f \n"), vel[0], vel[1], vel[2]); MessageInterface::ShowMessage( wxT(" in ComputeCartToKepl, angMomentum = %12.10f %12.10f %12.10f\n"), angMomentum[0], angMomentum[1], angMomentum[2]); MessageInterface::ShowMessage( wxT(" in ComputeCartToKepl, h = %12.10f\n"), h); #endif // if (h < 1E-30) // { // return 1; // } // eqn 4.3 Rvector3 nodeVec = Cross(Rvector3(0,0,1), angMomentum); // eqn 4.4 Real n = nodeVec.GetMagnitude(); // eqn 4.5 - 4.6 Real posMag = pos.GetMagnitude(); Real velMag = vel.GetMagnitude(); // eqn 4.7 - 4.8 Rvector3 eccVec = (1/grav)*((velMag*velMag - grav/posMag)*pos - (pos * vel) * vel); Real e = eccVec.GetMagnitude(); // eqn 4.9 Real zeta = 0.5*velMag*velMag - grav/posMag; #ifdef DEBUG_CART_TO_KEPL MessageInterface::ShowMessage( wxT(" in ComputeCartToKepl, nodeVec = %12.10f %12.10f %12.10f \n"), nodeVec[0], nodeVec[1], nodeVec[2]); MessageInterface::ShowMessage( wxT(" in ComputeCartToKepl, n = %12.10f\n"), n); MessageInterface::ShowMessage( wxT(" in ComputeCartToKepl, posMag = %12.10f\n"), posMag); MessageInterface::ShowMessage( wxT(" in ComputeCartToKepl, velMag = %12.10f\n"), velMag); MessageInterface::ShowMessage( wxT(" in ComputeCartToKepl, eccVec = %12.10f %12.10f %12.10f \n"), eccVec[0], eccVec[1], eccVec[2]); MessageInterface::ShowMessage( wxT(" in ComputeCartToKepl, e = %12.10f\n"), e); MessageInterface::ShowMessage( wxT(" in ComputeCartToKepl, zeta = %12.10f\n"), zeta); MessageInterface::ShowMessage( wxT(" in ComputeCartToKepl, Abs(1.0 - e) = %12.10f\n"), Abs(1.0 - e)); #endif if ((Abs(1.0 - e)) <= GmatOrbitConstants::KEP_ECC_TOL) { wxString errmsg = wxT("Error in conversion to Keplerian state: "); errmsg += wxT("The state results in an orbit that is nearly parabolic.\n"); throw UtilityException(errmsg); } // eqn 4.10 Real sma = -grav/(2*zeta); #ifdef DEBUG_CART_TO_KEPL MessageInterface::ShowMessage( wxT(" in ComputeCartToKepl, sma = %12.10f\n"), sma); #endif if (Abs(sma*(1 - e)) < .001) { throw UtilityException (wxT("Error in conversion from Cartesian to Keplerian state: ") wxT("The state results in a singular conic section with radius of periapsis less than 1 m.\n")); // (wxT("CoordUtil::CartesianToKeplerian() ") // wxT("Warning: A nearly singular conic section was encountered while ") // wxT("converting from the Cartesian state to the Keplerian elements. The radius of ") // wxT("periapsis must be greater than 1 meter.\n")); } // eqn 4.11 Real i = ACos( angMomentum.Get(2)/h ); if (i >= PI - GmatOrbitConstants::KEP_TOL) { throw UtilityException (wxT("Error in conversion to Keplerian state: ") wxT("GMAT does not currently support orbits with inclination of 180 degrees.\n")); } Real raan, argPeriapsis, trueAnom; raan=argPeriapsis=trueAnom=0; if ( e >= 1E-11 && i >= 1E-11 ) // CASE 1: Non-circular, Inclined Orbit { raan = ACos( nodeVec.Get(0)/n ); if (nodeVec.Get(1) < 0) raan = TWO_PI - raan; argPeriapsis = ACos( (nodeVec*eccVec)/(n*e) ); if (eccVec.Get(2) < 0) argPeriapsis = TWO_PI - argPeriapsis; trueAnom = ACos( (eccVec*pos)/(e*posMag) ); if (pos*vel < 0) trueAnom = TWO_PI - trueAnom; } if ( e >= 1E-11 && i < 1E-11 ) // CASE 2: Non-circular, Equatorial Orbit { raan = 0; argPeriapsis = ACos(eccVec.Get(0)/e); if (eccVec.Get(1) < 0) argPeriapsis = TWO_PI - argPeriapsis; trueAnom = ACos( (eccVec*pos)/(e*posMag) ); if (pos*vel < 0) trueAnom = TWO_PI - trueAnom; } if ( e < 1E-11 && i >= 1E-11 ) // CASE 3: Circular, Inclined Orbit { raan = ACos( nodeVec.Get(0)/n ); if (nodeVec.Get(1) < 0) raan = TWO_PI - raan; argPeriapsis = 0; trueAnom = ACos( (nodeVec*pos)/(n*posMag) ); if (pos.Get(2) < 0) trueAnom = TWO_PI - trueAnom; } if ( e < 1E-11 && i < 1E-11 ) // CASE 4: Circular, Equatorial Orbit { raan = 0; argPeriapsis = 0; trueAnom = ACos(pos.Get(0)/posMag); if (pos.Get(1) < 0) trueAnom = TWO_PI - trueAnom; } elem[0] = sma; elem[1] = e; elem[2] = i*DEG_PER_RAD; elem[3] = raan*DEG_PER_RAD; elem[4] = argPeriapsis*DEG_PER_RAD; elem[5] = trueAnom*DEG_PER_RAD; return 0; }