| 1 |
kusanagi |
1.1 |
//
|
| 2 |
|
|
// cOrbit.cpp
|
| 3 |
|
|
//
|
| 4 |
|
|
// Copyright (c) 2002-2003 Michael F. Henry
|
| 5 |
|
|
//
|
| 6 |
|
|
// mfh 11/15/2003
|
| 7 |
|
|
//
|
| 8 |
|
|
#include "stdafx.h"
|
| 9 |
|
|
|
| 10 |
|
|
#include "cOrbit.h"
|
| 11 |
|
|
#include "math.h"
|
| 12 |
|
|
#include "time.h"
|
| 13 |
|
|
#include "cVector.h"
|
| 14 |
|
|
#include "cEci.h"
|
| 15 |
|
|
#include "coord.h"
|
| 16 |
|
|
#include "cJulian.h"
|
| 17 |
|
|
#include "cNoradSGP4.h"
|
| 18 |
|
|
#include "cNoradSDP4.h"
|
| 19 |
|
|
|
| 20 |
|
|
//////////////////////////////////////////////////////////////////////
|
| 21 |
|
|
cOrbit::cOrbit(const cTle &tle) :
|
| 22 |
|
|
m_tle(tle),
|
| 23 |
|
|
m_pNoradModel(NULL)
|
| 24 |
|
|
{
|
| 25 |
|
|
m_tle.Initialize();
|
| 26 |
|
|
|
| 27 |
|
|
int epochYear = (int)m_tle.getField(cTle::FLD_EPOCHYEAR);
|
| 28 |
|
|
double epochDay = m_tle.getField(cTle::FLD_EPOCHDAY );
|
| 29 |
|
|
|
| 30 |
|
|
if (epochYear < 57)
|
| 31 |
|
|
epochYear += 2000;
|
| 32 |
|
|
else
|
| 33 |
|
|
epochYear += 1900;
|
| 34 |
|
|
|
| 35 |
|
|
m_jdEpoch = cJulian(epochYear, epochDay);
|
| 36 |
|
|
|
| 37 |
|
|
m_secPeriod = -1.0;
|
| 38 |
|
|
|
| 39 |
|
|
// Recover the original mean motion and semimajor axis from the
|
| 40 |
|
|
// input elements.
|
| 41 |
|
|
double mm = mnMotion();
|
| 42 |
|
|
double rpmin = mm * 2 * PI / MIN_PER_DAY; // rads per minute
|
| 43 |
|
|
|
| 44 |
|
|
double a1 = pow(XKE / rpmin, TWOTHRD);
|
| 45 |
|
|
double e = Eccentricity();
|
| 46 |
|
|
double i = Inclination();
|
| 47 |
|
|
double temp = (1.5 * CK2 * (3.0 * sqr(cos(i)) - 1.0) /
|
| 48 |
|
|
pow(1.0 - e * e, 1.5));
|
| 49 |
|
|
double delta1 = temp / (a1 * a1);
|
| 50 |
|
|
double a0 = a1 *
|
| 51 |
|
|
(1.0 - delta1 *
|
| 52 |
|
|
((1.0 / 3.0) + delta1 *
|
| 53 |
|
|
(1.0 + 134.0 / 81.0 * delta1)));
|
| 54 |
|
|
|
| 55 |
|
|
double delta0 = temp / (a0 * a0);
|
| 56 |
|
|
|
| 57 |
|
|
m_mnMotionRec = rpmin / (1.0 + delta0);
|
| 58 |
|
|
m_aeAxisSemiMinorRec = a0 / (1.0 - delta0);
|
| 59 |
|
|
m_aeAxisSemiMajorRec = m_aeAxisSemiMinorRec / sqrt(1.0 - (e * e));
|
| 60 |
|
|
m_kmPerigeeRec = XKMPER_WGS72 * (m_aeAxisSemiMajorRec * (1.0 - e) - AE);
|
| 61 |
|
|
m_kmApogeeRec = XKMPER_WGS72 * (m_aeAxisSemiMajorRec * (1.0 + e) - AE);
|
| 62 |
|
|
|
| 63 |
|
|
if (2.0 * PI / m_mnMotionRec >= 225.0)
|
| 64 |
|
|
{
|
| 65 |
|
|
// SDP4 - period >= 225 minutes.
|
| 66 |
|
|
m_pNoradModel = new cNoradSDP4(*this);
|
| 67 |
|
|
}
|
| 68 |
|
|
else
|
| 69 |
|
|
{
|
| 70 |
|
|
// SGP4 - period < 225 minutes
|
| 71 |
|
|
m_pNoradModel = new cNoradSGP4(*this);
|
| 72 |
|
|
}
|
| 73 |
|
|
}
|
| 74 |
|
|
|
| 75 |
|
|
/////////////////////////////////////////////////////////////////////////////
|
| 76 |
|
|
cOrbit::~cOrbit()
|
| 77 |
|
|
{
|
| 78 |
|
|
delete m_pNoradModel;
|
| 79 |
|
|
}
|
| 80 |
|
|
|
| 81 |
|
|
//////////////////////////////////////////////////////////////////////////////
|
| 82 |
|
|
// Return the period in seconds
|
| 83 |
|
|
double cOrbit::Period() const
|
| 84 |
|
|
{
|
| 85 |
|
|
if (m_secPeriod < 0.0)
|
| 86 |
|
|
{
|
| 87 |
|
|
// Calculate the period using the recovered mean motion.
|
| 88 |
|
|
if (m_mnMotionRec == 0)
|
| 89 |
|
|
m_secPeriod = 0.0;
|
| 90 |
|
|
else
|
| 91 |
|
|
m_secPeriod = (2 * PI) / m_mnMotionRec * 60.0;
|
| 92 |
|
|
}
|
| 93 |
|
|
|
| 94 |
|
|
return m_secPeriod;
|
| 95 |
|
|
}
|
| 96 |
|
|
|
| 97 |
|
|
//////////////////////////////////////////////////////////////////////////////
|
| 98 |
|
|
// Returns elapsed number of seconds from epoch to given time.
|
| 99 |
|
|
// Note: "Predicted" TLEs can have epochs in the future.
|
| 100 |
|
|
double cOrbit::TPlusEpoch(const cJulian &gmt) const
|
| 101 |
|
|
{
|
| 102 |
|
|
return gmt.spanSec(Epoch());
|
| 103 |
|
|
}
|
| 104 |
|
|
|
| 105 |
|
|
//////////////////////////////////////////////////////////////////////////////
|
| 106 |
|
|
// Returns the mean anomaly in radians at given GMT.
|
| 107 |
|
|
// At epoch, the mean anomaly is given by the elements data.
|
| 108 |
|
|
double cOrbit::mnAnomaly(cJulian gmt) const
|
| 109 |
|
|
{
|
| 110 |
|
|
double span = TPlusEpoch(gmt);
|
| 111 |
|
|
double P = Period();
|
| 112 |
|
|
|
| 113 |
|
|
assert(P != 0.0);
|
| 114 |
|
|
|
| 115 |
|
|
return fmod(mnAnomaly() + (TWOPI * (span / P)), TWOPI);
|
| 116 |
|
|
}
|
| 117 |
|
|
|
| 118 |
|
|
//////////////////////////////////////////////////////////////////////////////
|
| 119 |
|
|
// getPosition()
|
| 120 |
|
|
// This procedure returns the ECI position and velocity for the satellite
|
| 121 |
|
|
// at "tsince" minutes from the (GMT) TLE epoch. The vectors returned in
|
| 122 |
|
|
// the ECI object are kilometer-based.
|
| 123 |
|
|
// tsince - Time in minutes since the TLE epoch (GMT).
|
| 124 |
|
|
bool cOrbit::getPosition(double tsince, cEci *pEci) const
|
| 125 |
|
|
{
|
| 126 |
|
|
bool rc;
|
| 127 |
|
|
|
| 128 |
|
|
rc = m_pNoradModel->getPosition(tsince, *pEci);
|
| 129 |
|
|
|
| 130 |
|
|
pEci->ae2km();
|
| 131 |
|
|
|
| 132 |
|
|
return rc;
|
| 133 |
|
|
}
|
| 134 |
|
|
|
| 135 |
|
|
//////////////////////////////////////////////////////////////////////////////
|
| 136 |
|
|
// SatName()
|
| 137 |
|
|
// Return the name of the satellite. If requested, the NORAD number is
|
| 138 |
|
|
// appended to the end of the name, i.e., "ISS (ZARYA) #25544".
|
| 139 |
|
|
// The name of the satellite with the NORAD number appended is important
|
| 140 |
|
|
// because many satellites, especially debris, have the same name and
|
| 141 |
|
|
// would otherwise appear to be the same satellite in ouput data.
|
| 142 |
|
|
string cOrbit::SatName(bool fAppendId /* = false */) const
|
| 143 |
|
|
{
|
| 144 |
|
|
string str = m_tle.getName();
|
| 145 |
|
|
|
| 146 |
|
|
if (fAppendId)
|
| 147 |
|
|
{
|
| 148 |
|
|
string strId;
|
| 149 |
|
|
|
| 150 |
|
|
m_tle.getField(cTle::FLD_NORADNUM, cTle::U_NATIVE, &strId);
|
| 151 |
|
|
str = str + " #" + strId;
|
| 152 |
|
|
}
|
| 153 |
|
|
|
| 154 |
|
|
return str;
|
| 155 |
|
|
}
|
| 156 |
|
|
|