419 lines
12 KiB
JavaScript
419 lines
12 KiB
JavaScript
/*!
|
|
* satellite-js v5.0.0
|
|
* (c) 2013 Shashwat Kandadai and UCSC
|
|
* https://github.com/shashwatak/satellite-js
|
|
* License: MIT
|
|
*/
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports["default"] = sgp4;
|
|
var _constants = require("../constants");
|
|
var _dpper = _interopRequireDefault(require("./dpper"));
|
|
var _dspace = _interopRequireDefault(require("./dspace"));
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
|
/*----------------------------------------------------------------------------
|
|
*
|
|
* procedure sgp4
|
|
*
|
|
* this procedure is the sgp4 prediction model from space command. this is an
|
|
* updated and combined version of sgp4 and sdp4, which were originally
|
|
* published separately in spacetrack report //3. this version follows the
|
|
* methodology from the aiaa paper (2006) describing the history and
|
|
* development of the code.
|
|
*
|
|
* author : david vallado 719-573-2600 28 jun 2005
|
|
*
|
|
* inputs :
|
|
* satrec - initialised structure from sgp4init() call.
|
|
* tsince - time since epoch (minutes)
|
|
*
|
|
* outputs :
|
|
* r - position vector km
|
|
* v - velocity km/sec
|
|
* return code - non-zero on error.
|
|
* 1 - mean elements, ecc >= 1.0 or ecc < -0.001 or a < 0.95 er
|
|
* 2 - mean motion less than 0.0
|
|
* 3 - pert elements, ecc < 0.0 or ecc > 1.0
|
|
* 4 - semi-latus rectum < 0.0
|
|
* 5 - epoch elements are sub-orbital
|
|
* 6 - satellite has decayed
|
|
*
|
|
* locals :
|
|
* am -
|
|
* axnl, aynl -
|
|
* betal -
|
|
* cosim , sinim , cosomm , sinomm , cnod , snod , cos2u ,
|
|
* sin2u , coseo1 , sineo1 , cosi , sini , cosip , sinip ,
|
|
* cosisq , cossu , sinsu , cosu , sinu
|
|
* delm -
|
|
* delomg -
|
|
* dndt -
|
|
* eccm -
|
|
* emsq -
|
|
* ecose -
|
|
* el2 -
|
|
* eo1 -
|
|
* eccp -
|
|
* esine -
|
|
* argpm -
|
|
* argpp -
|
|
* omgadf -
|
|
* pl -
|
|
* r -
|
|
* rtemsq -
|
|
* rdotl -
|
|
* rl -
|
|
* rvdot -
|
|
* rvdotl -
|
|
* su -
|
|
* t2 , t3 , t4 , tc
|
|
* tem5, temp , temp1 , temp2 , tempa , tempe , templ
|
|
* u , ux , uy , uz , vx , vy , vz
|
|
* inclm - inclination
|
|
* mm - mean anomaly
|
|
* nm - mean motion
|
|
* nodem - right asc of ascending node
|
|
* xinc -
|
|
* xincp -
|
|
* xl -
|
|
* xlm -
|
|
* mp -
|
|
* xmdf -
|
|
* xmx -
|
|
* xmy -
|
|
* nodedf -
|
|
* xnode -
|
|
* nodep -
|
|
* np -
|
|
*
|
|
* coupling :
|
|
* getgravconst-
|
|
* dpper
|
|
* dspace
|
|
*
|
|
* references :
|
|
* hoots, roehrich, norad spacetrack report //3 1980
|
|
* hoots, norad spacetrack report //6 1986
|
|
* hoots, schumacher and glover 2004
|
|
* vallado, crawford, hujsak, kelso 2006
|
|
----------------------------------------------------------------------------*/
|
|
function sgp4(satrec, tsince) {
|
|
/* eslint-disable no-param-reassign */
|
|
|
|
var coseo1;
|
|
var sineo1;
|
|
var cosip;
|
|
var sinip;
|
|
var cosisq;
|
|
var delm;
|
|
var delomg;
|
|
var eo1;
|
|
var argpm;
|
|
var argpp;
|
|
var su;
|
|
var t3;
|
|
var t4;
|
|
var tc;
|
|
var tem5;
|
|
var temp;
|
|
var tempa;
|
|
var tempe;
|
|
var templ;
|
|
var inclm;
|
|
var mm;
|
|
var nm;
|
|
var nodem;
|
|
var xincp;
|
|
var xlm;
|
|
var mp;
|
|
var nodep;
|
|
|
|
/* ------------------ set mathematical constants --------------- */
|
|
// sgp4fix divisor for divide by zero check on inclination
|
|
// the old check used 1.0 + cos(pi-1.0e-9), but then compared it to
|
|
// 1.5 e-12, so the threshold was changed to 1.5e-12 for consistency
|
|
|
|
var temp4 = 1.5e-12;
|
|
|
|
// --------------------- clear sgp4 error flag -----------------
|
|
satrec.t = tsince;
|
|
satrec.error = 0;
|
|
|
|
// ------- update for secular gravity and atmospheric drag -----
|
|
var xmdf = satrec.mo + satrec.mdot * satrec.t;
|
|
var argpdf = satrec.argpo + satrec.argpdot * satrec.t;
|
|
var nodedf = satrec.nodeo + satrec.nodedot * satrec.t;
|
|
argpm = argpdf;
|
|
mm = xmdf;
|
|
var t2 = satrec.t * satrec.t;
|
|
nodem = nodedf + satrec.nodecf * t2;
|
|
tempa = 1.0 - satrec.cc1 * satrec.t;
|
|
tempe = satrec.bstar * satrec.cc4 * satrec.t;
|
|
templ = satrec.t2cof * t2;
|
|
if (satrec.isimp !== 1) {
|
|
delomg = satrec.omgcof * satrec.t;
|
|
// sgp4fix use mutliply for speed instead of pow
|
|
var delmtemp = 1.0 + satrec.eta * Math.cos(xmdf);
|
|
delm = satrec.xmcof * (delmtemp * delmtemp * delmtemp - satrec.delmo);
|
|
temp = delomg + delm;
|
|
mm = xmdf + temp;
|
|
argpm = argpdf - temp;
|
|
t3 = t2 * satrec.t;
|
|
t4 = t3 * satrec.t;
|
|
tempa = tempa - satrec.d2 * t2 - satrec.d3 * t3 - satrec.d4 * t4;
|
|
tempe += satrec.bstar * satrec.cc5 * (Math.sin(mm) - satrec.sinmao);
|
|
templ = templ + satrec.t3cof * t3 + t4 * (satrec.t4cof + satrec.t * satrec.t5cof);
|
|
}
|
|
nm = satrec.no;
|
|
var em = satrec.ecco;
|
|
inclm = satrec.inclo;
|
|
if (satrec.method === 'd') {
|
|
tc = satrec.t;
|
|
var dspaceOptions = {
|
|
irez: satrec.irez,
|
|
d2201: satrec.d2201,
|
|
d2211: satrec.d2211,
|
|
d3210: satrec.d3210,
|
|
d3222: satrec.d3222,
|
|
d4410: satrec.d4410,
|
|
d4422: satrec.d4422,
|
|
d5220: satrec.d5220,
|
|
d5232: satrec.d5232,
|
|
d5421: satrec.d5421,
|
|
d5433: satrec.d5433,
|
|
dedt: satrec.dedt,
|
|
del1: satrec.del1,
|
|
del2: satrec.del2,
|
|
del3: satrec.del3,
|
|
didt: satrec.didt,
|
|
dmdt: satrec.dmdt,
|
|
dnodt: satrec.dnodt,
|
|
domdt: satrec.domdt,
|
|
argpo: satrec.argpo,
|
|
argpdot: satrec.argpdot,
|
|
t: satrec.t,
|
|
tc: tc,
|
|
gsto: satrec.gsto,
|
|
xfact: satrec.xfact,
|
|
xlamo: satrec.xlamo,
|
|
no: satrec.no,
|
|
atime: satrec.atime,
|
|
em: em,
|
|
argpm: argpm,
|
|
inclm: inclm,
|
|
xli: satrec.xli,
|
|
mm: mm,
|
|
xni: satrec.xni,
|
|
nodem: nodem,
|
|
nm: nm
|
|
};
|
|
var dspaceResult = (0, _dspace["default"])(dspaceOptions);
|
|
em = dspaceResult.em;
|
|
argpm = dspaceResult.argpm;
|
|
inclm = dspaceResult.inclm;
|
|
mm = dspaceResult.mm;
|
|
nodem = dspaceResult.nodem;
|
|
nm = dspaceResult.nm;
|
|
}
|
|
if (nm <= 0.0) {
|
|
// printf("// error nm %f\n", nm);
|
|
satrec.error = 2;
|
|
// sgp4fix add return
|
|
return [false, false];
|
|
}
|
|
var am = Math.pow(_constants.xke / nm, _constants.x2o3) * tempa * tempa;
|
|
nm = _constants.xke / Math.pow(am, 1.5);
|
|
em -= tempe;
|
|
|
|
// fix tolerance for error recognition
|
|
// sgp4fix am is fixed from the previous nm check
|
|
if (em >= 1.0 || em < -0.001) {
|
|
// || (am < 0.95)
|
|
// printf("// error em %f\n", em);
|
|
satrec.error = 1;
|
|
// sgp4fix to return if there is an error in eccentricity
|
|
return [false, false];
|
|
}
|
|
|
|
// sgp4fix fix tolerance to avoid a divide by zero
|
|
if (em < 1.0e-6) {
|
|
em = 1.0e-6;
|
|
}
|
|
mm += satrec.no * templ;
|
|
xlm = mm + argpm + nodem;
|
|
nodem %= _constants.twoPi;
|
|
argpm %= _constants.twoPi;
|
|
xlm %= _constants.twoPi;
|
|
mm = (xlm - argpm - nodem) % _constants.twoPi;
|
|
|
|
// ----------------- compute extra mean quantities -------------
|
|
var sinim = Math.sin(inclm);
|
|
var cosim = Math.cos(inclm);
|
|
|
|
// -------------------- add lunar-solar periodics --------------
|
|
var ep = em;
|
|
xincp = inclm;
|
|
argpp = argpm;
|
|
nodep = nodem;
|
|
mp = mm;
|
|
sinip = sinim;
|
|
cosip = cosim;
|
|
if (satrec.method === 'd') {
|
|
var dpperParameters = {
|
|
inclo: satrec.inclo,
|
|
init: 'n',
|
|
ep: ep,
|
|
inclp: xincp,
|
|
nodep: nodep,
|
|
argpp: argpp,
|
|
mp: mp,
|
|
opsmode: satrec.operationmode
|
|
};
|
|
var dpperResult = (0, _dpper["default"])(satrec, dpperParameters);
|
|
ep = dpperResult.ep;
|
|
nodep = dpperResult.nodep;
|
|
argpp = dpperResult.argpp;
|
|
mp = dpperResult.mp;
|
|
xincp = dpperResult.inclp;
|
|
if (xincp < 0.0) {
|
|
xincp = -xincp;
|
|
nodep += _constants.pi;
|
|
argpp -= _constants.pi;
|
|
}
|
|
if (ep < 0.0 || ep > 1.0) {
|
|
// printf("// error ep %f\n", ep);
|
|
satrec.error = 3;
|
|
// sgp4fix add return
|
|
return [false, false];
|
|
}
|
|
}
|
|
|
|
// -------------------- long period periodics ------------------
|
|
if (satrec.method === 'd') {
|
|
sinip = Math.sin(xincp);
|
|
cosip = Math.cos(xincp);
|
|
satrec.aycof = -0.5 * _constants.j3oj2 * sinip;
|
|
|
|
// sgp4fix for divide by zero for xincp = 180 deg
|
|
if (Math.abs(cosip + 1.0) > 1.5e-12) {
|
|
satrec.xlcof = -0.25 * _constants.j3oj2 * sinip * (3.0 + 5.0 * cosip) / (1.0 + cosip);
|
|
} else {
|
|
satrec.xlcof = -0.25 * _constants.j3oj2 * sinip * (3.0 + 5.0 * cosip) / temp4;
|
|
}
|
|
}
|
|
var axnl = ep * Math.cos(argpp);
|
|
temp = 1.0 / (am * (1.0 - ep * ep));
|
|
var aynl = ep * Math.sin(argpp) + temp * satrec.aycof;
|
|
var xl = mp + argpp + nodep + temp * satrec.xlcof * axnl;
|
|
|
|
// --------------------- solve kepler's equation ---------------
|
|
var u = (xl - nodep) % _constants.twoPi;
|
|
eo1 = u;
|
|
tem5 = 9999.9;
|
|
var ktr = 1;
|
|
|
|
// sgp4fix for kepler iteration
|
|
// the following iteration needs better limits on corrections
|
|
while (Math.abs(tem5) >= 1.0e-12 && ktr <= 10) {
|
|
sineo1 = Math.sin(eo1);
|
|
coseo1 = Math.cos(eo1);
|
|
tem5 = 1.0 - coseo1 * axnl - sineo1 * aynl;
|
|
tem5 = (u - aynl * coseo1 + axnl * sineo1 - eo1) / tem5;
|
|
if (Math.abs(tem5) >= 0.95) {
|
|
if (tem5 > 0.0) {
|
|
tem5 = 0.95;
|
|
} else {
|
|
tem5 = -0.95;
|
|
}
|
|
}
|
|
eo1 += tem5;
|
|
ktr += 1;
|
|
}
|
|
|
|
// ------------- short period preliminary quantities -----------
|
|
var ecose = axnl * coseo1 + aynl * sineo1;
|
|
var esine = axnl * sineo1 - aynl * coseo1;
|
|
var el2 = axnl * axnl + aynl * aynl;
|
|
var pl = am * (1.0 - el2);
|
|
if (pl < 0.0) {
|
|
// printf("// error pl %f\n", pl);
|
|
satrec.error = 4;
|
|
// sgp4fix add return
|
|
return [false, false];
|
|
}
|
|
var rl = am * (1.0 - ecose);
|
|
var rdotl = Math.sqrt(am) * esine / rl;
|
|
var rvdotl = Math.sqrt(pl) / rl;
|
|
var betal = Math.sqrt(1.0 - el2);
|
|
temp = esine / (1.0 + betal);
|
|
var sinu = am / rl * (sineo1 - aynl - axnl * temp);
|
|
var cosu = am / rl * (coseo1 - axnl + aynl * temp);
|
|
su = Math.atan2(sinu, cosu);
|
|
var sin2u = (cosu + cosu) * sinu;
|
|
var cos2u = 1.0 - 2.0 * sinu * sinu;
|
|
temp = 1.0 / pl;
|
|
var temp1 = 0.5 * _constants.j2 * temp;
|
|
var temp2 = temp1 * temp;
|
|
|
|
// -------------- update for short period periodics ------------
|
|
if (satrec.method === 'd') {
|
|
cosisq = cosip * cosip;
|
|
satrec.con41 = 3.0 * cosisq - 1.0;
|
|
satrec.x1mth2 = 1.0 - cosisq;
|
|
satrec.x7thm1 = 7.0 * cosisq - 1.0;
|
|
}
|
|
var mrt = rl * (1.0 - 1.5 * temp2 * betal * satrec.con41) + 0.5 * temp1 * satrec.x1mth2 * cos2u;
|
|
|
|
// sgp4fix for decaying satellites
|
|
if (mrt < 1.0) {
|
|
// printf("// decay condition %11.6f \n",mrt);
|
|
satrec.error = 6;
|
|
return {
|
|
position: false,
|
|
velocity: false
|
|
};
|
|
}
|
|
su -= 0.25 * temp2 * satrec.x7thm1 * sin2u;
|
|
var xnode = nodep + 1.5 * temp2 * cosip * sin2u;
|
|
var xinc = xincp + 1.5 * temp2 * cosip * sinip * cos2u;
|
|
var mvt = rdotl - nm * temp1 * satrec.x1mth2 * sin2u / _constants.xke;
|
|
var rvdot = rvdotl + nm * temp1 * (satrec.x1mth2 * cos2u + 1.5 * satrec.con41) / _constants.xke;
|
|
|
|
// --------------------- orientation vectors -------------------
|
|
var sinsu = Math.sin(su);
|
|
var cossu = Math.cos(su);
|
|
var snod = Math.sin(xnode);
|
|
var cnod = Math.cos(xnode);
|
|
var sini = Math.sin(xinc);
|
|
var cosi = Math.cos(xinc);
|
|
var xmx = -snod * cosi;
|
|
var xmy = cnod * cosi;
|
|
var ux = xmx * sinsu + cnod * cossu;
|
|
var uy = xmy * sinsu + snod * cossu;
|
|
var uz = sini * sinsu;
|
|
var vx = xmx * cossu - cnod * sinsu;
|
|
var vy = xmy * cossu - snod * sinsu;
|
|
var vz = sini * cossu;
|
|
|
|
// --------- position and velocity (in km and km/sec) ----------
|
|
var r = {
|
|
x: mrt * ux * _constants.earthRadius,
|
|
y: mrt * uy * _constants.earthRadius,
|
|
z: mrt * uz * _constants.earthRadius
|
|
};
|
|
var v = {
|
|
x: (mvt * ux + rvdot * vx) * _constants.vkmpersec,
|
|
y: (mvt * uy + rvdot * vy) * _constants.vkmpersec,
|
|
z: (mvt * uz + rvdot * vz) * _constants.vkmpersec
|
|
};
|
|
return {
|
|
position: r,
|
|
velocity: v
|
|
};
|
|
|
|
/* eslint-enable no-param-reassign */
|
|
} |