From 5032f03fc11cd231decd2d7cfd5dd3576a7e45ea Mon Sep 17 00:00:00 2001 From: Jogi Hofmüller Date: Tue, 23 Aug 2011 16:59:29 +0000 Subject: - created tracker.wsgi as wsgi app - imported updated javascript libraries git-svn-id: https://svn.spreadspace.org/mur.sat@147 7de4ea59-55d0-425e-a1af-a3118ea81d4c --- tools/mmd/MmdLocation.py | 5 + tools/mmd/MmdWidgets.py | 133 ++-- tools/mmd/mmd.css | 39 + tools/mmd/orbtrak.js | 298 +++++++ tools/mmd/predictlib.js | 1916 ++++++++++++++++++++++++++++++++++++++++++++++ tools/mmd/tracker.wsgi | 106 +++ 6 files changed, 2438 insertions(+), 59 deletions(-) create mode 100644 tools/mmd/orbtrak.js create mode 100644 tools/mmd/predictlib.js create mode 100644 tools/mmd/tracker.wsgi (limited to 'tools') diff --git a/tools/mmd/MmdLocation.py b/tools/mmd/MmdLocation.py index a31ff67..e50360f 100644 --- a/tools/mmd/MmdLocation.py +++ b/tools/mmd/MmdLocation.py @@ -43,6 +43,10 @@ class Location: self.longitude = 15.44226 if not self.latitude: self.latitude = 47.06576 + if not self.altitude: + self.altitude = 376 + if not self.name: + self.name = 'Graz/Austria' self.location_id = hashlib.sha1 ('{0}{1}{2}'.format (user_id, self.longitude, self.latitude)).hexdigest () return self.db.locationCreate ( @@ -73,6 +77,7 @@ class Location: self.name = l['name'] self.longitude = float (l['longitude']) self.latitude = float (l['latitude']) + self.altitude = float (l['altitude']) self.is_default = l['is_default'] self.user_id = l['user_id'] return True diff --git a/tools/mmd/MmdWidgets.py b/tools/mmd/MmdWidgets.py index e245397..4cdedef 100644 --- a/tools/mmd/MmdWidgets.py +++ b/tools/mmd/MmdWidgets.py @@ -295,73 +295,88 @@ def osmWidget (session): user_location = session.user.getDefaultLocation () if not user_location: user_location = Location () - minutes_preview = 180 - html = ''' -
- - -
- The map shows the satellite's expected ground track for the next {5} minutes. -
+ '''.format ( - session.satellite.longitude, - session.satellite.latitude, + user_location.name, user_location.longitude, user_location.latitude, - session.satellite.getTrajectoryAsJavaArray ('curves', minutes_preview), - minutes_preview + user_location.altitude ) return html +# def osmWidget (session): +# user_location = session.user.getDefaultLocation () +# if not user_location: +# user_location = Location () +# minutes_preview = 180 +# +# html = ''' +#
+# +# +#
+# The map shows the satellite's expected ground track for the next {5} minutes. +#
+# '''.format ( +# session.satellite.longitude, +# session.satellite.latitude, +# user_location.longitude, +# user_location.latitude, +# session.satellite.getTrajectoryAsJavaArray ('curves', minutes_preview), +# minutes_preview +# ) +# +# return html + def statusWidget (session): if session.status == 'auth': inout = '''Status: logged in as {0}. logout'''.format (session.user.email) diff --git a/tools/mmd/mmd.css b/tools/mmd/mmd.css index 43c17c6..609ea5e 100644 --- a/tools/mmd/mmd.css +++ b/tools/mmd/mmd.css @@ -129,3 +129,42 @@ em float: left; width: 1em; } + +.telemetry +{ + font: 10pt courier, monospace; + color: white; +} + +.groundstation +{ + font: 10pt courier, monospace; + color: yellow; +} + +select.telemetry, +input.telemetry +{ + border: 1px solid #ffffff; + background: #003366; +} + +td.telemetry, +th.telemetry, +th.telemetry +{ + font: 10pt courier, monospace; + color: white; + border: 1px solid white; +} + +th.telemetry +{ + font-weight: bold; +} + +table.current +{ + border: 1px solid white; +} + diff --git a/tools/mmd/orbtrak.js b/tools/mmd/orbtrak.js new file mode 100644 index 0000000..c2582bd --- /dev/null +++ b/tools/mmd/orbtrak.js @@ -0,0 +1,298 @@ +/**************************************************************************** +* OrbTrak: A satellite orbit visualization library * +* Copyright Andrew T. West, 2008 * +* Last update: 07-Jun-2008 * +***************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify it * +* under the terms of the GNU General Public License as published by the * +* Free Software Foundation; either version 2 of the License or any later * +* version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +* General Public License for more details. * +* * +*****************************************************************************/ + +// orbtrak.js and predictlib.js both work for one satellite now +// Jogi, 2011-08-22 + +var Orb = + { + satelliteMarkers: new Array(), + satellitePoint: new Object (), + satLayer: new OpenLayers.Layer.Vector ("satLayer"), + homeLayer: new OpenLayers.Layer.Vector ("homeLayer"), + trackLayer: new OpenLayers.Layer.Vector ("trackLayer"), + track: new Array (), + from: new OpenLayers.Projection ("EPSG:4326"), + to: new OpenLayers.Projection ("EPSG:900913"), + + startOSMTracking: function (minutes, longitude, latitude, altitude, name) + { + PLib.InitializeData(); + PLib.configureGroundStation(latitude, longitude, altitude, name); + document.getElementById ("gsName").innerHTML = name; + document.getElementById ("gsLongitude").innerHTML = longitude; + document.getElementById ("gsLatitude").innerHTML = latitude; + document.getElementById ("gsAltitude").innerHTML = altitude; + Orb.createOSMSatellite (); + + var map = new OpenLayers.Map ("osm"); + map.addLayers ([new OpenLayers.Layer.OSM (), Orb.trackLayer, Orb.satLayer, Orb.homeLayer]); + map.zoomTo (1); + + var satStyle = {fillColor: "#FFED00", pointRadius: 3, stroke: false}; + var homeStyle = {fillColor: "#00ff00", pointRadius: 3, stroke: false}; + var home = new OpenLayers.LonLat (longitude, latitude).transform (Orb.from, Orb.to); + + Orb.createSatelliteTrack (minutes); + Orb.homeLayer.addFeatures ([ + new OpenLayers.Feature.Vector ( + new OpenLayers.Geometry.Point (home.lon, home.lat), + null, homeStyle)]); + // map.zoomToMaxExtent (); + Orb.satLayer.addFeatures ([ + new OpenLayers.Feature.Vector (Orb.satellitePoint, + null, satStyle)]); + setTimeout ("Orb.updateOSMSatellite ()", document.getElementById ("refresh").value); + }, + + createSatelliteTrack: function (minutes) + { + if (document.getElementById ("previewMinutes") != null) + minutes = document.getElementById ("previewMinutes").value; + Orb.trackLayer.destroyFeatures (); + var curve = new Array (); + var points = new Array (); + var track = PLib.calculateTrack (minutes); + var lineStyle = {strokeColor: '#003366', strokeOpacity: 1, strokeWidth: 1}; + var last = "east"; + + for (var i = 0; i < track.length; i++) + { + var lonlat = new OpenLayers.LonLat (track[i][0], track[i][1]).transform (Orb.from, Orb.to); + var lon = "" + track[i][0]; + if (lon.substring (0, 1) == "-") + { + if (last == "east") + { + curve.push (new OpenLayers.Feature.Vector (new OpenLayers.Geometry.LineString (points), null, lineStyle)) + points = new Array (); + } + last = "west"; + } + else + last = "east"; + points.push (new OpenLayers.Geometry.Point (lonlat.lon, lonlat.lat)); + } + curve.push (new OpenLayers.Feature.Vector (new OpenLayers.Geometry.LineString (points), null, lineStyle)) + Orb.trackLayer.addFeatures (curve); + }, + + updateOSMSatellite: function () + { + var satInfo; + var satellites = Orb.satLayer.features; + + satInfo = PLib.QuickFind (PLib.sat.name); + var pos = new OpenLayers.LonLat (satInfo.longitude, satInfo.latitude).transform (Orb.from, Orb.to); + satellites[0].move (pos); + Orb.printSatellite (satInfo); + setTimeout ("Orb.updateOSMSatellite ()", document.getElementById ("refresh").value); + }, + + createOSMSatellite: function () + { + var satInfo; + satInfo = PLib.QuickFind (PLib.sat.name); + var pos = new OpenLayers.LonLat (satInfo.longitude, satInfo.latitude).transform (Orb.from, Orb.to); + Orb.satellitePoint = new OpenLayers.Geometry.Point (pos.lon, pos.lat); + }, + + startTracking: function(map, homeLat, homeLng) + { + Orb.map = map; + Orb.crossBrowserSetStyle(map, "background-image: url(orbimages/world.jpg); overflow: hidden;", true); + + var frag = document.createDocumentFragment(); + var div = document.createElement("div"); + div.id = "home"; + Orb.crossBrowserSetStyle(div, "position:relative; width: 24px; height: 24px; background-image: url(orbimages/home.gif);", false); + frag.appendChild(div); + Orb.map.appendChild(frag); + Orb.home = document.getElementById("home"); + + PLib.InitializeData(); + Orb.setHomeCoordinates(homeLat, homeLng); + Orb.createSatelliteMarkers(); + Orb.updateSatellites(); + }, + + setHomeCoordinates: function(homeLat, homeLng) + { + PLib.configureGroundStation(homeLat, homeLng); + + Orb.home.style.top = ((-homeLat + 90) * 1.5 - 12.0) + "px"; + Orb.home.style.left = ((parseInt(homeLng) + 180) * 1.5 - 12.0) + "px"; + }, + + crossBrowserSetStyle: function(element, css, append) + { + var obj, attributeName; + var useStyleObject = element.style.setAttribute; + + obj = useStyleObject ? element.style : element; + attributeName = useStyleObject ? "cssText" : "style"; + + if (append) + css += obj.getAttribute(attributeName); + + obj.setAttribute(attributeName, css); + }, + + createOneMarker: function(txt) + { + var frag = document.createDocumentFragment(); + var markerCount = Orb.satelliteMarkers.length; + + var div = document.createElement("div"); + div.id = "satelliteMarker" + markerCount; + Orb.crossBrowserSetStyle(div, "position:absolute; width: 24px; height: 24px; background-image: url(orbimages/saticon.gif);", false); + var innerDiv = document.createElement("div"); + Orb.crossBrowserSetStyle(innerDiv, "position:absolute; left: 7px; top: 5px;"); + var txt = document.createTextNode(txt); + + innerDiv.appendChild(txt); + div.appendChild(innerDiv); + frag.appendChild(div); + Orb.map.appendChild(frag); + + Orb.satelliteMarkers[markerCount] = document.getElementById(div.id) + }, + + createSatelliteMarkers: function() + { + for (var i = 1; i <= PLib.sat.length; i++) + Orb.createOneMarker(i); + }, + + updateSatellites: function() + { + var satInfo; + + for (var i = 0; i < PLib.sat.length; i++) + { + satInfo = PLib.QuickFind(PLib.sat[i].name); + + Orb.satelliteMarkers[i].style.top = ((-satInfo.latitude + 90) * 1.5 - 12.0) + "px"; + Orb.satelliteMarkers[i].style.left = ((satInfo.longitude + 180) * 1.5 - 12.0) + "px"; + Orb.printSatellite (satInfo); + } + + setTimeout("Orb.updateSatellites()", 1000); + }, + + // added by Jogi + // 2011-08-21 + printSatellite: function (satInfo) + { + document.getElementById ("longitude").innerHTML = satInfo.longitude; + document.getElementById ("latitude").innerHTML = satInfo.latitude; + document.getElementById ("elevation").innerHTML = satInfo.elevation; + document.getElementById ("azimuth").innerHTML = satInfo.azimuth; + document.getElementById ("altitude").innerHTML = satInfo.altitude; + }, + + createCell: function(tr, className, txt) + { + var td = document.createElement("td"); + td.className = className; + txt = document.createTextNode(txt); + td.appendChild(txt); + tr.appendChild(td); + }, + + createHeaderColumn: function(tr, txt) + { + var th = document.createElement("th"); + th.className = "orb-header"; + txt = document.createTextNode(txt); + th.appendChild(txt); + tr.appendChild(th); + }, + + generateTable: function(divTable) + { + var tr, visibilityText, detailClassName; + var frag = document.createDocumentFragment(); + var satInfoColl = PLib.getTodaysPasses(); + + while (divTable.childNodes.length > 0) + { + divTable.removeChild(divTable.firstChild); + } + + var tbl = document.createElement("table"); + Orb.crossBrowserSetStyle(tbl, "border-collapse: collapse; margin-left: auto; margin-right: auto;", false); + + var thead = document.createElement("thead"); + tr = document.createElement("tr"); + + Orb.createHeaderColumn(tr, '# on Map'); + Orb.createHeaderColumn(tr, 'Name'); + Orb.createHeaderColumn(tr, 'Pass #'); + Orb.createHeaderColumn(tr, 'Date'); + Orb.createHeaderColumn(tr, 'Local Time'); + Orb.createHeaderColumn(tr, 'Peak Elev.'); + Orb.createHeaderColumn(tr, 'Azimuth'); + Orb.createHeaderColumn(tr, 'Range (km)'); + Orb.createHeaderColumn(tr, 'Visibility'); + + thead.appendChild(tr); + tbl.appendChild(thead); + + var tbody = document.createElement("tbody"); + + for (var i = 0; i < satInfoColl.length; i++) + { + tr = document.createElement("tr"); + + detailClassName = satInfoColl[i].visibility == "+" ? "orb-detailVisible" : "orb-detail"; + + Orb.createCell(tr, detailClassName, satInfoColl[i].number); + Orb.createCell(tr, detailClassName, satInfoColl[i].name); + Orb.createCell(tr, detailClassName, satInfoColl[i].passNo); + Orb.createCell(tr, detailClassName, PLib.formatDateOnly(satInfoColl[i].dateTimeStart)); + Orb.createCell(tr, detailClassName, PLib.formatTimeOnly(satInfoColl[i].dateTimeStart) + " - " + PLib.formatTimeOnly(satInfoColl[i].dateTimeEnd)); + Orb.createCell(tr, detailClassName, satInfoColl[i].peakElevation + "\u00B0"); + Orb.createCell(tr, detailClassName, satInfoColl[i].riseAzimuth + ", " + satInfoColl[i].peakAzimuth + ", " + satInfoColl[i].decayAzimuth); + Orb.createCell(tr, detailClassName, satInfoColl[i].riseRange + ", " + satInfoColl[i].peakRange + ", " + satInfoColl[i].decayRange); + + switch(satInfoColl[i].visibility) + { + case "+": + visibilityText = 'Visible'; + break; + case "*": + visibilityText = 'Not Visible'; + break; + default: + visibilityText = 'Eclipsed'; + } + + Orb.createCell(tr, detailClassName, visibilityText); + + tbody.appendChild(tr); + } + + tbl.appendChild(tbody); + frag.appendChild(tbl); + divTable.appendChild(frag); + } + } + +// vim: ts=2 tw=0 expandtab +// EOF diff --git a/tools/mmd/predictlib.js b/tools/mmd/predictlib.js new file mode 100644 index 0000000..574bd3f --- /dev/null +++ b/tools/mmd/predictlib.js @@ -0,0 +1,1916 @@ +/**************************************************************************** +* PredictLib: A satellite tracking/orbital prediction library * +* Copyright Andrew T. West, 2008 * +* Based on PREDICT, Copyright John A. Magliacane, KD2BD 1991-2002 * +* Last update: 07-Jun-2008 * +***************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify it * +* under the terms of the GNU General Public License as published by the * +* Free Software Foundation; either version 2 of the License or any later * +* version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +* General Public License for more details. * +* * +*****************************************************************************/ + +var PLib = + { + deg2rad: 1.745329251994330E-2, + pi: 3.14159265358979323846, pio2: 1.57079632679489656, twopi: 6.28318530717958623, + e6a: 1.0E-6, + tothrd: 6.6666666666666666E-1, + xj3: -2.53881E-6, xke: 7.43669161E-2, xkmper: 6.378137E3, xmnpda: 1.44E3, + ae: 1.0, + ck2: 5.413079E-4, ck4: 6.209887E-7, + f: 3.35281066474748E-3, s: 1.012229, + qoms2t: 1.880279E-09, + secday: 8.6400E4, + omega_E: 1.00273790934, + zns: 1.19459E-5, c1ss: 2.9864797E-6, zes: 1.675E-2, znl: 1.5835218E-4, c1l: 4.7968065E-7, zel: 5.490E-2, + zcosis: 9.1744867E-1, zsinis: 3.9785416E-1, zsings: -9.8088458E-1, zcosgs: 1.945905E-1, + q22: 1.7891679E-6, q31: 2.1460748E-6, q33: 2.2123015E-7, + g22: 5.7686396, g32: 9.5240898E-1, g44: 1.8014998, g52: 1.0508330, g54: 4.4108898, + root22: 1.7891679E-6, root32: 3.7393792E-7, root44: 7.3636953E-9, root52: 1.1428639E-7, root54: 2.1765803E-9, + thdt: 4.3752691E-3, + mfactor: 7.292115E-5, + sr: 6.96000E5, + AU: 1.49597870691E8, + + dpinit: 1, dpsec: 2, dpper: 3, + + ALL_FLAGS: -1, + SGP4_INITIALIZED_FLAG: 0x000002, + SDP4_INITIALIZED_FLAG: 0x000004, + SIMPLE_FLAG: 0x000020, + DEEP_SPACE_EPHEM_FLAG: 0x000040, + LUNAR_TERMS_DONE_FLAG: 0x000080, + DO_LOOP_FLAG: 0x000200, + RESONANCE_FLAG: 0x000400, + SYNCHRONOUS_FLAG: 0x000800, + EPOCH_RESTART_FLAG: 0x001000, + VISIBLE_FLAG: 0x002000, + SAT_ECLIPSED_FLAG: 0x004000, + + sat_t: function() + { + this.line1 = ""; + this.line2 = ""; + this.name = ""; + this.catnum = 0; + this.setnum = 0; + this.designator = ""; + this.year = 0; + this.refepoch = 0.0; + this.incl = 0.0; + this.raan = 0.0; + this.eccn = 0.0; + this.argper = 0.0; + this.meanan = 0.0; + this.meanmo = 0.0; + this.drag = 0.0; + this.nddot6 = 0.0; + this.bstar = 0.0; + this.orbitnum = 0.0; + this.refepoch = 0; + }, + + // sat: new Array(), + sat: "", + + qth: + { + callsign: "HOME", + name: "", + stnlat: 0.0, + stnlong: 0.0, + stnalt: 1000, + utc_offset: new Date().getTimezoneOffset() / 60 + }, + + tempstr: "", output: "", + + tsince: 0.0, jul_epoch: 0.0, jul_utc: 0.0, eclipse_depth: 0.0, + sat_azi: 0.0, sat_ele: 0.0, sat_range: 0.0, sat_range_rate: 0.0, + sat_lat: 0.0, sat_lon: 0.0, sat_alt: 0.0, sat_vel: 0.0, phase: 0.0, + sun_azi: 0.0, sun_ele: 0.0, daynum: 0.0, fm: 0.0, fk: 0.0, age: 0.0, aostime: 0.0, + lostime: 0.0, ax: 0.0, ay: 0.0, az: 0.0, rx: 0.0, ry: 0.0, rz: 0.0, squint: 0.0, alat: 0.0, alon: 0.0, + + ephem: "", sat_sun_status: "", findsun: "", + + indx: 0, iaz: 0, iel: 0, ma256: 0, isplat: 0, isplong: 0, Flags: 0, + + rv: 0, irk: 0, + + tle_t: function() + { + this.epoch = 0.0; + this.xndt2o = 0.0; + this.xndd6o = 0.0; + this.bstar = 0.0; + this.xincl = 0.0; + this.xnodeo = 0.0; + this.eo = 0.0; + this.omegao = 0.0; + this.xmo = 0.0; + this.xno = 0.0; + this.catnr = 0; + this.elset = 0; + this.revnum = 0; + this.sat_name = ""; + this.idesg = ""; + }, + + geodetic_t: function() + { + this.lat = 0.0; + this.lon = 0.0; + this.alt = 0.0; + this.theta = 0.0; + }, + + vector_t: function() + { + this.x = 0.0; + this.y = 0.0; + this.z = 0.0; + this.w = 0.0; + }, + + deep_arg_t: function() + { + this.eosq = 0.0; + this.sinio = 0.0; + this.cosio = 0.0; + this.betao = 0.0; + this.aodp = 0.0; + this.theta2 = 0.0; + this.sing = 0.0; + this.cosg = 0.0; + this.betao2 = 0.0; + this.xmdot = 0.0; + this.omgdot = 0.0; + this.xnodot = 0.0; + this.xnodp = 0.0; + this.xll = 0.0; + this.omgadf = 0.0; + this.xnode = 0.0; + this.em = 0.0; + this.xinc = 0.0; + this.xn = 0.0; + this.t = 0.0; + this.ds50 = 0.0; + }, + + obs_geodetic: new Object(), + tle: new Object(), + tleData: new Array(), + + isFlagSet: function(flag) + { + return (PLib.Flags & flag); + }, + + isFlagClear: function(flag) + { + return (~PLib.Flags & flag); + }, + + SetFlag: function(flag) + { + PLib.Flags |= flag; + }, + + ClearFlag: function (flag) + { + PLib.Flags &= ~flag; + }, + + Sqr: function(arg) + { + return (arg * arg); + }, + + Radians: function(arg) + { + return (arg * PLib.deg2rad); + }, + + Degrees: function(arg) + { + return (arg / PLib.deg2rad); + }, + + Magnitude: function(v) + { + v.w = Math.sqrt(PLib.Sqr(v.x) + PLib.Sqr(v.y) + PLib.Sqr(v.z)); + }, + + Vec_Sub: function(v1, v2, v3) + { + v3.x = v1.x - v2.x; + v3.y = v1.y - v2.y; + v3.z = v1.z - v2.z; + PLib.Magnitude(v3); + }, + + Scalar_Multiply: function(k, v1, v2) + { + v2.x = k * v1.x; + v2.y = k * v1.y; + v2.z = k * v1.z; + v2.w = Math.abs(k) * v1.w; + }, + + Scale_Vector: function(k, v) + { + v.x *= k; + v.y *= k; + v.z *= k; + PLib.Magnitude(v); + }, + + Dot: function(v1, v2) + { + return (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z); + }, + + Angle: function(v1, v2) + { + PLib.Magnitude(v1); + PLib.Magnitude(v2); + return (Math.acos(PLib.Dot(v1, v2) / (v1.w * v2.w))); + }, + + FMod2p: function(x) + { + var i = 0; + var ret_val = 0.0; + + ret_val = x; + i = parseInt(ret_val / PLib.twopi); + ret_val -= i * PLib.twopi; + + if (ret_val < 0.0) + ret_val += PLib.twopi; + + return ret_val; + }, + + Modulus: function(arg1, arg2) + { + return arg1 - (parseInt(arg1 / arg2)) * arg2; + }, + + Frac: function(arg) + { + return(arg - Math.floor(arg)); + }, + + Convert_Sat_State: function(pos, vel) + { + PLib.Scale_Vector(PLib.xkmper, pos); + PLib.Scale_Vector(PLib.xkmper * PLib.xmnpda / PLib.secday, vel); + }, + + Julian_Date_of_Year: function(year) + { + var A = 0, B = 0, i = 0; + var jdoy = 0.0; + + year = year - 1; + i = parseInt(year / 100); + A = i; + i = parseInt(A / 4); + B = 2 - A + i; + i = parseInt(365.25 * year); + i += parseInt(30.6001 * 14); + jdoy = i + 1720994.5 + B; + + return jdoy; + }, + + Julian_Date_of_Epoch: function(epoch) + { + var year = 0.0, day = 0.0; + + year = parseInt(epoch * 1E-3); + day = ((epoch * 1E-3) - year) * 1E3; + + if (year < 57) + year = year + 2000; + else + year = year + 1900; + + return (PLib.Julian_Date_of_Year(year) + day); + }, + + Delta_ET: function(year) + { + var delta_et = 0.0; + + delta_et = 26.465 + 0.747622 * (year - 1950) + 1.886913 * Math.sin(PLib.twopi * (year - 1975) / 33); + + return delta_et; + }, + + ThetaG: function(epoch, deep_arg) + { + var year = 0.0, day = 0.0, UT = 0.0, jd = 0.0, TU = 0.0, GMST = 0.0, ThetaG = 0.0; + + year = parseInt(epoch * 1E-3); + day = ((epoch * 1E-3) - year) * 1E3; + + if (year < 57) + year += 2000; + else + year += 1900; + + UT = (day - parseInt(day)); + day = parseInt(day); + jd = PLib.Julian_Date_of_Year(year) + day; + TU = (jd - 2451545.0) / 36525; + GMST = 24110.54841 + TU * (8640184.812866 + TU * (0.093104 - TU * 6.2E-6)); + GMST = PLib.Modulus(GMST + PLib.secday * PLib.omega_E * UT, PLib.secday); + ThetaG = twopi * GMST / PLib.secday; + deep_arg.ds50 = jd - 2433281.5 + UT; + ThetaG = PLib.FMod2p(6.3003880987 * deep_arg.ds50 + 1.72944494); + + return ThetaG; + }, + + ThetaG_JD: function(jd) + { + var UT = 0.0, TU = 0.0, GMST = 0.0; + + UT = PLib.Frac(jd + 0.5); + jd = jd - UT; + TU = (jd - 2451545.0) / 36525; + GMST = 24110.54841 + TU * (8640184.812866 + TU * (0.093104 - TU * 6.2E-6)); + GMST = PLib.Modulus(GMST + PLib.secday * PLib.omega_E * UT, PLib.secday); + + return (PLib.twopi * GMST / PLib.secday); + }, + + Calculate_Solar_Position: function(time, solar_vector) + { + var mjd = 0.0, year = 0.0, T = 0.0, M = 0.0, L = 0.0, e = 0.0, C = 0.0, O = 0.0, Lsa = 0.0, nu = 0.0, R = 0.0, eps = 0.0; + + mjd = time - 2415020.0; + year = 1900 + mjd / 365.25; + T = (mjd + PLib.Delta_ET(year) / PLib.secday) / 36525.0; + M = PLib.Radians(PLib.Modulus(358.47583 + PLib.Modulus(35999.04975 * T, 360.0) - (0.000150 + 0.0000033 * T) * PLib.Sqr(T), 360.0)); + L = PLib.Radians(PLib.Modulus(279.69668 + PLib.Modulus(36000.76892 * T, 360.0) + 0.0003025 * PLib.Sqr(T),360.0)); + e = 0.01675104 - (0.0000418 + 0.000000126 * T) * T; + C = PLib.Radians((1.919460 - (0.004789 + 0.000014 * T) * T) * Math.sin(M) + (0.020094 - 0.000100 * T) * Math.sin(2 * M) + 0.000293 * Math.sin(3 * M)); + O = PLib.Radians(PLib.Modulus(259.18-1934.142 * T, 360.0)); + Lsa = PLib.Modulus(L + C - PLib.Radians(0.00569-0.00479 * Math.sin(O)), PLib.twopi); + nu = PLib.Modulus(M + C, PLib.twopi); + R = 1.0000002 * (1.0 - PLib.Sqr(e)) / (1.0 + e * Math.cos(nu)); + eps = PLib.Radians(23.452294 - (0.0130125 + (0.00000164 - 0.000000503 * T) * T) * T + 0.00256 * Math.cos(O)); + R = PLib.AU * R; + solar_vector.x = R * Math.cos(Lsa); + solar_vector.y = R * Math.sin(Lsa) * Math.cos(eps); + solar_vector.z = R * Math.sin(Lsa) * Math.sin(eps); + solar_vector.w = R; + }, + + Sat_Eclipsed: function(pos, sol) + { + var sd_sun = 0.0, sd_earth = 0.0, delta = 0.0; + var Rho = new PLib.vector_t(); + var earth = new PLib.vector_t();; + + sd_earth = Math.asin(PLib.xkmper / pos.w); + PLib.Vec_Sub(sol, pos, Rho); + sd_sun = Math.asin(PLib.sr / Rho.w); + PLib.Scalar_Multiply(-1, pos, earth); + delta = PLib.Angle(sol, earth); + PLib.eclipse_depth = sd_earth - sd_sun - delta; + + if (sd_earth < sd_sun) + return 0; + else + if (PLib.eclipse_depth >= 0) + return 1; + else + return 0; + }, + + select_ephemeris: function(tle) + { + var ao = 0.0, xnodp = 0.0, dd1 = 0.0, dd2 = 0.0, delo = 0.0, temp = 0.0, a1 = 0.0, del1 = 0.0, r1 = 0.0; + + tle.xnodeo *= PLib.deg2rad; + tle.omegao *= PLib.deg2rad; + tle.xmo *= PLib.deg2rad; + tle.xincl *= PLib.deg2rad; + temp = PLib.twopi / PLib.xmnpda / PLib.xmnpda; + tle.xno = tle.xno * temp * PLib.xmnpda; + tle.xndt2o *= temp; + tle.xndd6o = tle.xndd6o * temp / PLib.xmnpda; + tle.bstar /= PLib.ae; + + dd1 = (PLib.xke / tle.xno); + dd2 = PLib.tothrd; + a1 = Math.pow(dd1, dd2); + r1 = Math.cos(tle.xincl); + dd1 = (1.0 - tle.eo * tle.eo); + temp = PLib.ck2 * 1.5 * (r1 * r1 * 3.0 - 1.0) / Math.pow(dd1, 1.5); + del1 = temp / (a1 * a1); + ao = a1 * (1.0 - del1 * (PLib.tothrd * 0.5 + del1 * (del1 * 1.654320987654321 + 1.0))); + delo = temp / (ao * ao); + xnodp = tle.xno / (delo + 1.0); + + if (PLib.twopi / PLib.xnodp / PLib.xmnpda >= 0.15625) + PLib.SetFlag(PLib.DEEP_SPACE_EPHEM_FLAG); + else + PLib.ClearFlag(PLib.DEEP_SPACE_EPHEM_FLAG); + }, + + SGP4: function(tsince, tle, pos, vel) + { + var cosuk = 0.0, sinuk = 0.0, rfdotk = 0.0, vx = 0.0, vy = 0.0, vz = 0.0, ux = 0.0, uy = 0.0, uz = 0.0, xmy = 0.0, xmx = 0.0, cosnok = 0.0, + sinnok = 0.0, cosik = 0.0, sinik = 0.0, rdotk = 0.0, xinck = 0.0, xnodek = 0.0, uk = 0.0, rk = 0.0, cos2u = 0.0, sin2u = 0.0, + u = 0.0, sinu = 0.0, cosu = 0.0, betal = 0.0, rfdot = 0.0, rdot = 0.0, r = 0.0, pl = 0.0, elsq = 0.0, esine = 0.0, ecose = 0.0, epw = 0.0, + cosepw = 0.0, x1m5th = 0.0, xhdot1 = 0.0, tfour = 0.0, sinepw = 0.0, capu = 0.0, ayn = 0.0, xlt = 0.0, aynl = 0.0, xll = 0.0, + axn = 0.0, xn = 0.0, beta = 0.0, xl = 0.0, e = 0.0, a = 0.0, tcube = 0.0, delm = 0.0, delomg = 0.0, templ = 0.0, tempe = 0.0, tempa = 0.0, + xnode = 0.0, tsq = 0.0, xmp = 0.0, omega = 0.0, xnoddf = 0.0, omgadf = 0.0, xmdf = 0.0, a1 = 0.0, a3ovk2 = 0.0, ao = 0.0, + betao = 0.0, betao2 = 0.0, c1sq = 0.0, c2 = 0.0, c3 = 0.0, coef = 0.0, coef1 = 0.0, del1 = 0.0, delo = 0.0, eeta = 0.0, eosq = 0.0, + etasq = 0.0, perigee = 0.0, pinvsq = 0.0, psisq = 0.0, qoms24 = 0.0, s4 = 0.0, temp = 0.0, temp1 = 0.0, temp2 = 0.0, + temp3 = 0.0, temp4 = 0.0, temp5 = 0.0, temp6 = 0.0, theta2 = 0.0, theta4 = 0.0, tsi = 0.0; + + var i = 0; + + if (PLib.isFlagClear(PLib.SGP4_INITIALIZED_FLAG)) + { + PLib.SetFlag(PLib.SGP4_INITIALIZED_FLAG); + + a1 = Math.pow(PLib.xke / tle.xno, PLib.tothrd); + PLib.SGP4.cosio = Math.cos(tle.xincl); + theta2 = PLib.SGP4.cosio * PLib.SGP4.cosio; + PLib.SGP4.x3thm1 = 3 * theta2 - 1.0; + eosq = tle.eo * tle.eo; + betao2 = 1.0 - eosq; + betao = Math.sqrt(betao2); + del1 = 1.5 * PLib.ck2 * PLib.SGP4.x3thm1 / (a1 * a1 * betao * betao2); + ao = a1 * (1.0 - del1 * (0.5 * PLib.tothrd + del1 * (1.0 + 134.0 / 81.0 * del1))); + delo = 1.5 * PLib.ck2 * PLib.SGP4.x3thm1 / (ao * ao * betao * betao2); + PLib.SGP4.xnodp = tle.xno / (1.0 + delo); + PLib.SGP4.aodp = ao / (1.0 - delo); + + if ((PLib.SGP4.aodp * (1 - tle.eo) / PLib.ae) < (220 / PLib.xkmper + PLib.ae)) + PLib.SetFlag(PLib.SIMPLE_FLAG); + else + PLib.ClearFlag(PLib.SIMPLE_FLAG); + + s4 = PLib.s; + PLib.qoms24 = PLib.qoms2t; + PLib.perigee = (PLib.SGP4.aodp * (1 - tle.eo) - PLib.ae) * PLib.xkmper; + + if (PLib.perigee < 156.0) + { + if (PLib.perigee <= 98.0) + s4 = 20; + else + s4 = PLib.perigee - 78.0; + + PLib.qoms24 = Math.pow((120 - s4) * PLib.ae / PLib.xkmper, 4); + s4 = s4 / PLib.xkmper + PLib.ae; + } + + pinvsq = 1 / (PLib.SGP4.aodp * PLib.SGP4.aodp * betao2 * betao2); + tsi = 1 / (PLib.SGP4.aodp - s4); + PLib.SGP4.eta = PLib.SGP4.aodp * tle.eo * tsi; + etasq = PLib.SGP4.eta * PLib.SGP4.eta; + eeta = tle.eo * PLib.SGP4.eta; + psisq = Math.abs(1 - etasq); + coef = qoms24 * Math.pow(tsi, 4); + coef1 = coef / Math.pow(psisq, 3.5); + c2 = coef1 * PLib.SGP4.xnodp * (PLib.SGP4.aodp * (1 + 1.5 * etasq + eeta * (4 + etasq)) + 0.75 * PLib.ck2 * tsi / psisq * PLib.SGP4.x3thm1 * (8 + 3 * etasq * (8 + etasq))); + PLib.SGP4.c1 = tle.bstar * c2; + PLib.SGP4.sinio = Math.sin(tle.xincl); + a3ovk2 = -PLib.xj3 / PLib.ck2 * Math.pow(PLib.ae, 3); + c3 = coef * tsi * a3ovk2 * PLib.SGP4.xnodp * PLib.ae * PLib.SGP4.sinio / tle.eo; + PLib.SGP4.x1mth2 = 1 - theta2; + + PLib.SGP4.c4 = 2 * PLib.SGP4.xnodp * coef1 * PLib.SGP4.aodp * betao2 * (PLib.SGP4.eta * (2 + 0.5 * etasq)+tle.eo * (0.5 + 2 * etasq) - 2 * PLib.ck2 * tsi / (PLib.SGP4.aodp * psisq) * (-3 * PLib.SGP4.x3thm1 * (1 - 2 * eeta + etasq * (1.5 - 0.5 * eeta)) + 0.75 * PLib.SGP4.x1mth2 * (2 * etasq-eeta * (1 + etasq)) * Math.cos(2 * tle.omegao))); + PLib.SGP4.c5 = 2 * coef1 * PLib.SGP4.aodp * betao2 * (1 + 2.75 * (etasq + eeta) + eeta * etasq); + + theta4 = theta2 * theta2; + temp1 = 3 * PLib.ck2 * pinvsq * PLib.SGP4.xnodp; + temp2 = temp1 * PLib.ck2 * pinvsq; + temp3 = 1.25 * PLib.ck4 * pinvsq * pinvsq * PLib.SGP4.xnodp; + PLib.SGP4.xmdot = PLib.SGP4.xnodp + 0.5 * temp1 * betao * PLib.SGP4.x3thm1 + 0.0625 * temp2 * betao * (13 - 78 * theta2 + 137 * theta4); + x1m5th = 1 - 5 * theta2; + PLib.SGP4.omgdot = -0.5 * temp1 * x1m5th + 0.0625 * temp2 * (7 - 114 * theta2 + 395 * theta4) + temp3 * (3 - 36 * theta2 + 49 * theta4); + xhdot1 = -temp1 * PLib.SGP4.cosio; + PLib.SGP4.xnodot = xhdot1 + (0.5 * temp2 * (4 - 19 * theta2) + 2 * temp3 * (3 - 7 * theta2)) * PLib.SGP4.cosio; + PLib.SGP4.omgcof = tle.bstar * c3 * Math.cos(tle.omegao); + PLib.SGP4.xmcof = -PLib.tothrd * coef * tle.bstar * PLib.ae / eeta; + PLib.SGP4.xnodcf = 3.5 * betao2 * xhdot1 * PLib.SGP4.c1; + PLib.SGP4.t2cof = 1.5 * PLib.SGP4.c1; + PLib.SGP4.xlcof = 0.125 * a3ovk2 * PLib.SGP4.sinio * (3 + 5 * PLib.SGP4.cosio) / (1 + PLib.SGP4.cosio); + PLib.SGP4.aycof = 0.25 * a3ovk2 * PLib.SGP4.sinio; + PLib.SGP4.delmo = Math.pow(1 + PLib.SGP4.eta * Math.cos(tle.xmo), 3); + PLib.SGP4.sinmo = Math.sin(tle.xmo); + PLib.SGP4.x7thm1 = 7 * theta2 - 1; + + if (PLib.isFlagClear(PLib.SIMPLE_FLAG)) + { + c1sq = PLib.SGP4.c1 * PLib.SGP4.c1; + PLib.SGP4.d2 = 4 * PLib.SGP4.aodp * tsi * c1sq; + temp = PLib.SGP4.d2 * tsi * PLib.SGP4.c1/3; + PLib.SGP4.d3 = (17 * PLib.SGP4.aodp + s4) * temp; + PLib.SGP4.d4 = 0.5 * temp * PLib.SGP4.aodp * tsi * (221 * PLib.SGP4.aodp + 31 * s4) * PLib.SGP4.c1; + PLib.SGP4.t3cof = PLib.SGP4.d2 + 2 * c1sq; + PLib.SGP4.t4cof = 0.25 * (3 * PLib.SGP4.d3 + PLib.SGP4.c1 * (12 * PLib.SGP4.d2 + 10 * c1sq)); + PLib.SGP4.t5cof = 0.2 * (3 * PLib.SGP4.d4 + 12 * PLib.SGP4.c1 * PLib.SGP4.d3 + 6 * PLib.SGP4.d2 * PLib.SGP4.d2 + 15 * c1sq * (2 * PLib.SGP4.d2 + c1sq)); + } + } + + xmdf = tle.xmo + PLib.SGP4.xmdot * tsince; + omgadf = tle.omegao + PLib.SGP4.omgdot * tsince; + xnoddf = tle.xnodeo + PLib.SGP4.xnodot * tsince; + omega = omgadf; + xmp = xmdf; + tsq = tsince * tsince; + xnode = xnoddf + PLib.SGP4.xnodcf * tsq; + tempa = 1 - PLib.SGP4.c1 * tsince; + tempe = tle.bstar * PLib.SGP4.c4 * tsince; + templ = PLib.SGP4.t2cof * tsq; + + if (PLib.isFlagClear(PLib.SIMPLE_FLAG)) + { + delomg = PLib.SGP4.omgcof * tsince; + delm = PLib.SGP4.xmcof * (Math.pow(1 + PLib.SGP4.eta * Math.cos(xmdf), 3) - PLib.SGP4.delmo); + temp = delomg + delm; + xmp = xmdf + temp; + omega = omgadf - temp; + tcube = tsq * tsince; + tfour = tsince * tcube; + tempa = tempa - PLib.SGP4.d2 * tsq - PLib.SGP4.d3 * tcube - PLib.SGP4.d4 * tfour; + tempe = tempe + tle.bstar * PLib.SGP4.c5 * (Math.sin(xmp) - PLib.SGP4.sinmo); + templ = templ + PLib.SGP4.t3cof * tcube + tfour * (PLib.SGP4.t4cof + tsince * PLib.SGP4.t5cof); + } + + a = PLib.SGP4.aodp * Math.pow(tempa, 2); + e = tle.eo - tempe; + xl = xmp + omega + xnode + PLib.SGP4.xnodp * templ; + beta = Math.sqrt(1 - e * e); + xn = PLib.xke / Math.pow(a, 1.5); + + axn = e * Math.cos(omega); + temp = 1 / (a * beta * beta); + xll = temp * PLib.SGP4.xlcof * axn; + aynl = temp * PLib.SGP4.aycof; + xlt = xl + xll; + ayn = e * Math.sin(omega) + aynl; + + capu = PLib.FMod2p(xlt - xnode); + temp2 = capu; + i = 0; + + do + { + sinepw = Math.sin(temp2); + cosepw = Math.cos(temp2); + temp3 = axn * sinepw; + temp4 = ayn * cosepw; + temp5 = axn * cosepw; + temp6 = ayn * sinepw; + epw = (capu - temp4 + temp3 - temp2) / (1 - temp5 - temp6) + temp2; + + if (Math.abs(epw - temp2) <= PLib.e6a) + break; + + temp2 = epw; + } while (i++ < 10); + + ecose = temp5 + temp6; + esine = temp3 - temp4; + elsq = axn * axn + ayn * ayn; + temp = 1 - elsq; + pl = a * temp; + r = a * (1 - ecose); + temp1 = 1 / r; + rdot = PLib.xke * Math.sqrt(a) * esine * temp1; + rfdot = PLib.xke * Math.sqrt(pl) * temp1; + temp2 = a * temp1; + betal = Math.sqrt(temp); + temp3 = 1 / (1 + betal); + cosu = temp2 * (cosepw - axn + ayn * esine * temp3); + sinu = temp2 * (sinepw - ayn - axn * esine * temp3); + u = Math.atan2(sinu, cosu); + sin2u = 2 * sinu * cosu; + cos2u = 2 * cosu * cosu - 1; + temp = 1 / pl; + temp1 = PLib.ck2 * temp; + temp2 = temp1 * temp; + + rk = r * (1 - 1.5 * temp2 * betal * PLib.SGP4.x3thm1) + 0.5 * temp1 * PLib.SGP4.x1mth2 * cos2u; + uk = u - 0.25 * temp2 * PLib.SGP4.x7thm1 * sin2u; + xnodek = xnode + 1.5 * temp2 * PLib.SGP4.cosio * sin2u; + xinck = tle.xincl + 1.5 * temp2 * PLib.SGP4.cosio * PLib.SGP4.sinio * cos2u; + rdotk = rdot - xn * temp1 * PLib.SGP4.x1mth2 * sin2u; + rfdotk = rfdot + xn * temp1 * (PLib.SGP4.x1mth2 * cos2u + 1.5 * PLib.SGP4.x3thm1); + + sinuk = Math.sin(uk); + cosuk = Math.cos(uk); + sinik = Math.sin(xinck); + cosik = Math.cos(xinck); + sinnok = Math.sin(xnodek); + cosnok = Math.cos(xnodek); + xmx = -sinnok * cosik; + xmy = cosnok * cosik; + ux = xmx * sinuk+cosnok * cosuk; + uy = xmy * sinuk+sinnok * cosuk; + uz = sinik * sinuk; + vx = xmx * cosuk-cosnok * sinuk; + vy = xmy * cosuk-sinnok * sinuk; + vz = sinik * cosuk; + + pos.x = rk * ux; + pos.y = rk * uy; + pos.z = rk * uz; + vel.x = rdotk * ux + rfdotk * vx; + vel.y = rdotk * uy + rfdotk * vy; + vel.z = rdotk * uz + rfdotk * vz; + + PLib.phase = xlt - xnode - omgadf + PLib.twopi; + + if (PLib.phase < 0.0) + PLib.phase += PLib.twopi; + + PLib.phase = PLib.FMod2p(PLib.phase); + }, + + Deep: function(ientry, tle, deep_arg) + { + var a1 = 0.0, a2 = 0.0, a3 = 0.0, a4 = 0.0, a5 = 0.0, a6 = 0.0, a7 = 0.0, a8 = 0.0, a9 = 0.0, a10 = 0.0, ainv2 = 0.0, alfdp = 0.0, aqnv = 0.0, + sgh = 0.0, sini2 = 0.0, sinis = 0.0, sinok = 0.0, sh = 0.0, si = 0.0, sil = 0.0, day = 0.0, betdp = 0.0, dalf = 0.0, bfact = 0.0, c = 0.0, + cc = 0.0, cosis = 0.0, cosok = 0.0, cosq = 0.0, ctem = 0.0, f322 = 0.0, zx = 0.0, zy = 0.0, dbet = 0.0, dls = 0.0, eoc = 0.0, eq = 0.0, f2 = 0.0, + f220 = 0.0, f221 = 0.0, f3 = 0.0, f311 = 0.0, f321 = 0.0, xnoh = 0.0, f330 = 0.0, f441 = 0.0, f442 = 0.0, f522 = 0.0, f523 = 0.0, + f542 = 0.0, f543 = 0.0, g200 = 0.0, g201 = 0.0, g211 = 0.0, pgh = 0.0, ph = 0.0, s1 = 0.0, s2 = 0.0, s3 = 0.0, s4 = 0.0, s5 = 0.0, s6 = 0.0, s7 = 0.0, + se = 0.0, sel = 0.0, ses = 0.0, xls = 0.0, g300 = 0.0, g310 = 0.0, g322 = 0.0, g410 = 0.0, g422 = 0.0, g520 = 0.0, g521 = 0.0, g532 = 0.0, + g533 = 0.0, gam = 0.0, sinq = 0.0, sinzf = 0.0, sis = 0.0, sl = 0.0, sll = 0.0, sls = 0.0, stem = 0.0, temp = 0.0, temp1 = 0.0, x1 = 0.0, + x2 = 0.0, x2li = 0.0, x2omi = 0.0, x3 = 0.0, x4 = 0.0, x5 = 0.0, x6 = 0.0, x7 = 0.0, x8 = 0.0, xl = 0.0, xldot = 0.0, xmao = 0.0, xnddt = 0.0, + xndot = 0.0, xno2 = 0.0, xnodce = 0.0, xnoi = 0.0, xomi = 0.0, xpidot = 0.0, z1 = 0.0, z11 = 0.0, z12 = 0.0, z13 = 0.0, z2 = 0.0, + z21 = 0.0, z22 = 0.0, z23 = 0.0, z3 = 0.0, z31 = 0.0, z32 = 0.0, z33 = 0.0, ze = 0.0, zf = 0.0, zm = 0.0, zmo = 0.0, zn = 0.0, zsing = 0.0, + zsinh = 0.0, zsini = 0.0, zcosg = 0.0, zcosh = 0.0, zcosi = 0.0, delt = 0.0, ft = 0.0; + + switch (ientry) + { + case dpinit: + PLib.Deep.thgr = PLib.ThetaG(tle.epoch, deep_arg); + eq = tle.eo; + PLib.Deep.xnq = deep_arg.xnodp; + aqnv = 1 / deep_arg.aodp; + PLib.Deep.xqncl = tle.xincl; + xmao = tle.xmo; + xpidot = deep_arg.omgdot + deep_arg.xnodot; + sinq = Math.sin(tle.xnodeo); + cosq = Math.cos(tle.xnodeo); + PLib.Deep.omegaq = tle.omegao; + + day = deep_arg.ds50 + 18261.5; + + if (day != PLib.Deep.preep) + { + PLib.Deep.preep = day; + xnodce = 4.5236020 - 9.2422029E-4 * day; + stem = Math.sin(xnodce); + ctem = Math.cos(xnodce); + PLib.Deep.zcosil = 0.91375164 - 0.03568096 * ctem; + PLib.Deep.zsinil = Math.sqrt(1 - PLib.Deep.zcosil * PLib.Deep.zcosil); + PLib.Deep.zsinhl = 0.089683511 * stem / PLib.Deep.zsinil; + PLib.Deep.zcoshl = Math.sqrt(1 - PLib.Deep.zsinhl * PLib.Deep.zsinhl); + c = 4.7199672 + 0.22997150 * day; + gam = 5.8351514 + 0.0019443680 * day; + PLib.Deep.zmol = PLib.FMod2p(c - gam); + zx = 0.39785416 * stem / PLib.Deep.zsinil; + zy = PLib.Deep.zcoshl * ctem + 0.91744867 * PLib.Deep.zsinhl * stem; + zx = Math.atan2(zx, zy); + zx = gam + zx - xnodce; + PLib.Deep.zcosgl = Math.cos(zx); + PLib.Deep.zsingl = Math.sin(zx); + PLib.Deep.zmos = 6.2565837 + 0.017201977 * day; + PLib.Deep.zmos = PLib.FMod2p(PLib.Deep.zmos); + } + + PLib.Deep.savtsn = 1E20; + zcosg = PLib.zcosgs; + zsing = PLib.zsings; + zcosi = PLib.zcosis; + zsini = PLib.zsinis; + zcosh = cosq; + zsinh = sinq; + cc = PLib.c1ss; + zn = PLib.zns; + ze = PLib.zes; + zmo = PLib.Deep.zmos; + xnoi = 1 / PLib.Deep.xnq; + + for (;;) + { + a1 = zcosg * zcosh + zsing * zcosi * zsinh; + a3 = -zsing * zcosh + zcosg * zcosi * zsinh; + a7 = -zcosg * zsinh + zsing * zcosi * zcosh; + a8 = zsing * zsini; + a9 = zsing * zsinh + zcosg * zcosi * zcosh; + a10 = zcosg * zsini; + a2 = deep_arg.cosio * a7 + deep_arg.sinio * a8; + a4 = deep_arg.cosio * a9 + deep_arg.sinio * a10; + a5 = -deep_arg.sinio * a7 + deep_arg.cosio * a8; + a6 = -deep_arg.sinio * a9 + deep_arg.cosio * a10; + x1 = a1 * deep_arg.cosg + a2 * deep_arg.sing; + x2 = a3 * deep_arg.cosg + a4 * deep_arg.sing; + x3 = -a1 * deep_arg.sing + a2 * deep_arg.cosg; + x4 = -a3 * deep_arg.sing + a4 * deep_arg.cosg; + x5 = a5 * deep_arg.sing; + x6 = a6 * deep_arg.sing; + x7 = a5 * deep_arg.cosg; + x8 = a6 * deep_arg.cosg; + z31 = 12 * x1 * x1 - 3 * x3 * x3; + z32 = 24 * x1 * x2 - 6 * x3 * x4; + z33 = 12 * x2 * x2 - 3 * x4 * x4; + z1 = 3 * (a1 * a1 + a2 * a2) + z31 * deep_arg.eosq; + z2 = 6 * (a1 * a3 + a2 * a4) + z32 * deep_arg.eosq; + z3 = 3 * (a3 * a3 + a4 * a4) + z33 * deep_arg.eosq; + z11 = -6 * a1 * a5 + deep_arg.eosq * (-24 * x1 * x7 - 6 * x3 * x5); + z12 = -6 * (a1 * a6 + a3 * a5) + deep_arg.eosq * (-24 * (x2 * x7 + x1 * x8) - 6 * (x3 * x6 + x4 * x5)); + z13 = -6 * a3 * a6 + deep_arg.eosq * (-24 * x2 * x8 - 6 * x4 * x6); + z21 = 6 * a2 * a5 + deep_arg.eosq * (24 * x1 * x5 - 6 * x3 * x7); + z22 = 6 * (a4 * a5 + a2 * a6) + deep_arg.eosq * (24 * (x2 * x5 + x1 * x6) - 6 * (x4 * x7 + x3 * x8)); + z23 = 6 * a4 * a6 + deep_arg.eosq * (24 * x2 * x6 - 6 * x4 * x8); + z1 = z1 + z1 + deep_arg.betao2 * z31; + z2 = z2 + z2 + deep_arg.betao2 * z32; + z3 = z3 + z3 + deep_arg.betao2 * z33; + s3 = cc * xnoi; + s2 = -0.5 * s3 / deep_arg.betao; + s4 = s3 * deep_arg.betao; + s1 = -15 * eq * s4; + s5 = x1 * x3 + x2 * x4; + s6 = x2 * x3 + x1 * x4; + s7 = x2 * x4 - x1 * x3; + se = s1 * zn * s5; + si = s2 * zn * (z11 + z13); + sl = -zn * s3 * (z1 + z3 - 14 - 6 * deep_arg.eosq); + sgh = s4 * zn * (z31 + z33 - 6); + sh = -zn * s2 * (z21 + z23); + + if (PLib.Deep.xqncl < 5.2359877E-2) + sh = 0; + + PLib.Deep.ee2 = 2 * s1 * s6; + PLib.Deep.e3 = 2 * s1 * s7; + PLib.Deep.xi2 = 2 * s2 * z12; + PLib.Deep.xi3 = 2 * s2 * (z13 - z11); + PLib.Deep.xl2 = -2 * s3 * z2; + PLib.Deep.xl3 = -2 * s3 * (z3 - z1); + PLib.Deep.xl4 = -2 * s3 * (-21 - 9 * deep_arg.eosq) * ze; + PLib.Deep.xgh2 = 2 * s4 * z32; + PLib.Deep.xgh3 = 2 * s4 * (z33 - z31); + PLib.Deep.xgh4 = -18 * s4 * ze; + PLib.Deep.xh2 = -2 * s2 * z22; + PLib.Deep.xh3 = -2 * s2 * (z23 - z21); + + if (PLib.isFlagSet(PLib.LUNAR_TERMS_DONE_FLAG)) + break; + + PLib.Deep.sse = se; + PLib.Deep.ssi = si; + PLib.Deep.ssl = sl; + PLib.Deep.ssh = sh / deep_arg.sinio; + PLib.Deep.ssg = sgh - deep_arg.cosio * PLib.Deep.ssh; + PLib.Deep.se2 = PLib.Deep.ee2; + PLib.Deep.si2 = PLib.Deep.xi2; + PLib.Deep.sl2 = PLib.Deep.xl2; + PLib.Deep.sgh2 = PLib.Deep.xgh2; + PLib.Deep.sh2 = PLib.Deep.xh2; + PLib.Deep.se3 = PLib.Deep.e3; + PLib.Deep.si3 = PLib.Deep.xi3; + PLib.Deep.sl3 = PLib.Deep.xl3; + PLib.Deep.sgh3 = PLib.Deep.xgh3; + PLib.Deep.sh3 = PLib.Deep.xh3; + PLib.Deep.sl4 = PLib.Deep.xl4; + PLib.Deep.sgh4 = PLib.Deep.xgh4; + zcosg = PLib.Deep.zcosgl; + zsing = PLib.Deep.zsingl; + zcosi = PLib.Deep.zcosil; + zsini = PLib.Deep.zsinil; + zcosh = PLib.Deep.zcoshl * cosq + PLib.Deep.zsinhl * sinq; + zsinh = sinq * PLib.Deep.zcoshl - cosq * PLib.Deep.zsinhl; + zn = PLib.znl; + cc = PLib.c1l; + ze = PLib.zel; + zmo = PLib.Deep.zmol; + PLib.SetFlag(PLib.LUNAR_TERMS_DONE_FLAG); + } + + PLib.Deep.sse = PLib.Deep.sse + se; + PLib.Deep.ssi = PLib.Deep.ssi + si; + PLib.Deep.ssl = PLib.Deep.ssl + sl; + PLib.Deep.ssg = PLib.Deep.ssg + sgh - deep_arg.cosio / deep_arg.sinio * sh; + PLib.Deep.ssh = PLib.Deep.ssh + sh / deep_arg.sinio; + + PLib.ClearFlag(PLib.RESONANCE_FLAG); + PLib.ClearFlag(PLib.SYNCHRONOUS_FLAG); + + if (!((PLib.Deep.xnq < 0.0052359877) && (PLib.Deep.xnq > 0.0034906585))) + { + if ((PLib.Deep.xnq < 0.00826) || (PLib.Deep.xnq > 0.00924)) + return; + + if (eq < 0.5) + return; + + PLib.SetFlag(PLib.RESONANCE_FLAG); + eoc = eq * deep_arg.eosq; + g201 = -0.306 - (eq - 0.64) * 0.440; + + if (eq <= 0.65) + { + g211 = 3.616 - 13.247 * eq + 16.290 * deep_arg.eosq; + g310 = -19.302 + 117.390 * eq - 228.419 * deep_arg.eosq + 156.591 * eoc; + g322 = -18.9068 + 109.7927 * eq - 214.6334 * deep_arg.eosq + 146.5816 * eoc; + g410 = -41.122 + 242.694 * eq - 471.094 * deep_arg.eosq + 313.953 * eoc; + g422 = -146.407 + 841.880 * eq - 1629.014 * deep_arg.eosq + 1083.435 * eoc; + g520 = -532.114 + 3017.977 * eq - 5740 * deep_arg.eosq + 3708.276 * eoc; + } + + else + { + g211 = -72.099 + 331.819 * eq - 508.738 * deep_arg.eosq + 266.724 * eoc; + g310 = -346.844 + 1582.851 * eq - 2415.925 * deep_arg.eosq + 1246.113 * eoc; + g322 = -342.585 + 1554.908 * eq - 2366.899 * deep_arg.eosq + 1215.972 * eoc; + g410 = -1052.797 + 4758.686 * eq - 7193.992 * deep_arg.eosq + 3651.957 * eoc; + g422 = -3581.69 + 16178.11 * eq - 24462.77 * deep_arg.eosq + 12422.52 * eoc; + + if (eq <= 0.715) + g520 = 1464.74 - 4664.75 * eq + 3763.64 * deep_arg.eosq; + + else + g520 = -5149.66 + 29936.92 * eq - 54087.36 * deep_arg.eosq + 31324.56 * eoc; + } + + if (eq < 0.7) + { + g533 = -919.2277 + 4988.61 * eq - 9064.77 * deep_arg.eosq + 5542.21 * eoc; + g521 = -822.71072 + 4568.6173 * eq - 8491.4146 * deep_arg.eosq + 5337.524 * eoc; + g532 = -853.666 + 4690.25 * eq - 8624.77 * deep_arg.eosq + 5341.4 * eoc; + } + + else + { + g533 = -37995.78 + 161616.52 * eq - 229838.2 * deep_arg.eosq + 109377.94 * eoc; + g521 = -51752.104 + 218913.95 * eq - 309468.16 * deep_arg.eosq + 146349.42 * eoc; + g532 = -40023.88 + 170470.89 * eq - 242699.48 * deep_arg.eosq + 115605.82 * eoc; + } + + sini2 = deep_arg.sinio * deep_arg.sinio; + f220 = 0.75 * (1 + 2 * deep_arg.cosio + deep_arg.theta2); + f221 = 1.5 * sini2; + f321 = 1.875 * deep_arg.sinio * (1 - 2 * deep_arg.cosio - 3 * deep_arg.theta2); + f322 = -1.875 * deep_arg.sinio * (1 + 2 * deep_arg.cosio - 3 * deep_arg.theta2); + f441 = 35 * sini2 * f220; + f442 = 39.3750 * sini2 * sini2; + f522 = 9.84375 * deep_arg.sinio * (sini2 * (1 - 2 * deep_arg.cosio - 5 * deep_arg.theta2) + 0.33333333 * (-2 + 4 * deep_arg.cosio + 6 * deep_arg.theta2)); + f523 = deep_arg.sinio * (4.92187512 * sini2 * (-2 - 4 * deep_arg.cosio + 10 * deep_arg.theta2) + 6.56250012 * (1 + 2 * deep_arg.cosio-3 * deep_arg.theta2)); + f542 = 29.53125 * deep_arg.sinio * (2 - 8 * deep_arg.cosio + deep_arg.theta2 * (-12 + 8 * deep_arg.cosio+10 * deep_arg.theta2)); + f543 = 29.53125 * deep_arg.sinio * (-2 - 8 * deep_arg.cosio + deep_arg.theta2 * (12 + 8 * deep_arg.cosio-10 * deep_arg.theta2)); + xno2 = PLib.Deep.xnq * PLib.Deep.xnq; + ainv2 = aqnv * aqnv; + temp1 = 3 * xno2 * ainv2; + temp = temp1 * PLib.root22; + PLib.Deep.d2201 = temp * f220 * g201; + PLib.Deep.d2211 = temp * f221 * g211; + temp1 = temp1 * aqnv; + temp = temp1 * PLib.root32; + PLib.Deep.d3210 = temp * f321 * g310; + PLib.Deep.d3222 = temp * f322 * g322; + temp1 = temp1 * aqnv; + temp = 2 * temp1 * PLib.root44; + PLib.Deep.d4410 = temp * f441 * g410; + PLib.Deep.d4422 = temp * f442 * g422; + temp1 = temp1 * aqnv; + temp = temp1 * PLib.root52; + PLib.Deep.d5220 = temp * f522 * g520; + PLib.Deep.d5232 = temp * f523 * g532; + temp = 2 * temp1 * PLib.root54; + PLib.Deep.d5421 = temp * f542 * g521; + PLib.Deep.d5433 = temp * f543 * g533; + PLib.Deep.xlamo = xmao + tle.xnodeo + tle.xnodeo - PLib.Deep.thgr - PLib.Deep.thgr; + bfact = deep_arg.xmdot + deep_arg.xnodot + deep_arg.xnodot - PLib.thdt - PLib.thdt; + bfact = bfact + PLib.Deep.ssl + PLib.Deep.ssh + PLib.Deep.ssh; + } + + else + { + PLib.SetFlag(PLib.RESONANCE_FLAG); + PLib.SetFlag(PLib.SYNCHRONOUS_FLAG); + + g200 = 1 + deep_arg.eosq * (-2.5 + 0.8125 * deep_arg.eosq); + g310 = 1 + 2 * deep_arg.eosq; + g300 = 1 + deep_arg.eosq * (-6 + 6.60937 * deep_arg.eosq); + f220 = 0.75 * (1 + deep_arg.cosio) * (1 + deep_arg.cosio); + f311 = 0.9375 * deep_arg.sinio * deep_arg.sinio * (1 + 3 * deep_arg.cosio) - 0.75 * (1 + deep_arg.cosio); + f330 = 1 + deep_arg.cosio; + f330 = 1.875 * f330 * f330 * f330; + PLib.Deep.del1 = 3 * PLib.Deep.xnq * PLib.Deep.xnq * aqnv * aqnv; + PLib.Deep.del2 = 2 * PLib.Deep.del1 * f220 * g200 * q22; + PLib.Deep.del3 = 3 * PLib.Deep.del1 * f330 * g300 * q33 * aqnv; + PLib.Deep.del1 = PLib.Deep.del1 * f311 * g310 * q31 * aqnv; + PLib.Deep.fasx2 = 0.13130908; + PLib.Deep.fasx4 = 2.8843198; + PLib.Deep.fasx6 = 0.37448087; + PLib.Deep.xlamo = xmao + tle.xnodeo + tle.omegao - PLib.Deep.thgr; + bfact = deep_arg.xmdot + xpidot - PLib.thdt; + bfact = bfact + PLib.Deep.ssl + PLib.Deep.ssg + PLib.Deep.ssh; + } + + PLib.Deep.xfact = bfact - PLib.Deep.xnq; + + PLib.Deep.xli = PLib.Deep.xlamo; + PLib.Deep.xni = PLib.Deep.xnq; + PLib.Deep.atime = 0; + PLib.Deep.stepp = 720; + PLib.Deep.stepn = -720; + PLib.Deep.step2 = 259200; + + return; + + case dpsec: /* Entrance for deep space secular effects */ + deep_arg.xll = deep_arg.xll + PLib.Deep.ssl * deep_arg.t; + deep_arg.omgadf = deep_arg.omgadf + PLib.Deep.ssg * deep_arg.t; + deep_arg.xnode = deep_arg.xnode + PLib.Deep.ssh * deep_arg.t; + deep_arg.em = tle.eo + PLib.Deep.sse * deep_arg.t; + deep_arg.xinc = tle.xincl + PLib.Deep.ssi * deep_arg.t; + + if (deep_arg.xinc < 0) + { + deep_arg.xinc = -deep_arg.xinc; + deep_arg.xnode = deep_arg.xnode + pi; + deep_arg.omgadf = deep_arg.omgadf - pi; + } + + if (PLib.isFlagClear(PLib.RESONANCE_FLAG)) + return; + + do + { + if ((PLib.Deep.atime == 0) || ((deep_arg.t >= 0) && (PLib.Deep.atime < 0)) || ((deep_arg.t < 0) && (PLib.Deep.atime >= 0))) + { + if (deep_arg.t >= 0) + delt = PLib.Deep.stepp; + else + delt = PLib.Deep.stepn; + + PLib.Deep.atime = 0; + PLib.Deep.xni = PLib.Deep.xnq; + PLib.Deep.xli = PLib.Deep.xlamo; + } + + else + { + if (Math.abs(deep_arg.t) >= Math.abs(PLib.Deep.atime)) + { + if (deep_arg.t > 0) + delt = PLib.Deep.stepp; + else + delt = PLib.Deep.stepn; + } + } + + do + { + if (Math.abs(deep_arg.t - PLib.Deep.atime) >= PLib.Deep.stepp) + { + PLib.SetFlag(PLib.DO_LOOP_FLAG); + PLib.ClearFlag(PLib.EPOCH_RESTART_FLAG); + } + + else + { + ft = deep_arg.t - PLib.Deep.atime; + PLib.ClearFlag(PLib.DO_LOOP_FLAG); + } + + if (Math.abs(deep_arg.t) < Math.abs(PLib.Deep.atime)) + { + if (deep_arg.t >= 0) + delt = PLib.Deep.stepn; + else + delt = PLib.Deep.stepp; + + PLib.SetFlag(PLib.DO_LOOP_FLAG | PLib.EPOCH_RESTART_FLAG); + } + + if (PLib.isFlagSet(PLib.SYNCHRONOUS_FLAG)) + { + xndot = PLib.Deep.del1 * Math.sin(PLib.Deep.xli - PLib.Deep.fasx2) + PLib.Deep.del2 * Math.sin(2 * (PLib.Deep.xli - PLib.Deep.fasx4)) + PLib.Deep.del3 * Math.sin(3 * (PLib.Deep.xli - PLib.Deep.fasx6)); + xnddt = PLib.Deep.del1 * Math.cos(PLib.Deep.xli - PLib.Deep.fasx2) + 2 * PLib.Deep.del2 * Math.cos(2 * (PLib.Deep.xli - PLib.Deep.fasx4)) + 3 * PLib.Deep.del3 * Math.cos(3 * (PLib.Deep.xli - PLib.Deep.fasx6)); + } + + else + { + xomi = PLib.Deep.omegaq + deep_arg.omgdot * PLib.Deep.atime; + x2omi = xomi + xomi; + x2li = PLib.Deep.xli + PLib.Deep.xli; + xndot = PLib.Deep.d2201 * Math.sin(x2omi + PLib.Deep.xli - g22) + PLib.Deep.d2211 * Math.sin(PLib.Deep.xli - g22) + PLib.Deep.d3210 * Math.sin(xomi + PLib.Deep.xli - g32) + PLib.Deep.d3222 * Math.sin(-xomi + PLib.Deep.xli - g32) + PLib.Deep.d4410 * sin(x2omi + x2li - g44) + PLib.Deep.d4422 * sin(x2li - g44) + PLib.Deep.d5220 * sin(xomi + PLib.Deep.xli - g52) + PLib.Deep.d5232 * sin(-xomi + PLib.Deep.xli - g52) + PLib.Deep.d5421 * sin(xomi + x2li - g54) + PLib.Deep.d5433 * sin(-xomi + x2li - g54); + xnddt = PLib.Deep.d2201 * Math.cos(x2omi + PLib.Deep.xli - g22) + PLib.Deep.d2211 * Math.cos(PLib.Deep.xli - g22) + PLib.Deep.d3210 * Math.cos(xomi + PLib.Deep.xli - g32) + PLib.Deep.d3222 * Math.cos(-xomi + PLib.Deep.xli - g32) + PLib.Deep.d5220 * cos(xomi + PLib.Deep.xli - g52) + PLib.Deep.d5232 * cos(-xomi + PLib.Deep.xli - g52) + 2 * (PLib.Deep.d4410 * cos(x2omi + x2li - g44) + PLib.Deep.d4422 * cos(x2li - g44) + PLib.Deep.d5421 * cos(xomi + x2li - g54) + PLib.Deep.d5433 * cos(-xomi + x2li - g54)); + } + + xldot = PLib.Deep.xni + PLib.Deep.xfact; + xnddt = xnddt * xldot; + + if (PLib.isFlagSet(PLib.DO_LOOP_FLAG)) + { + PLib.Deep.xli = PLib.Deep.xli + xldot * delt + xndot * PLib.Deep.step2; + PLib.Deep.xni = PLib.Deep.xni + xndot * delt + xnddt * PLib.Deep.step2; + PLib.Deep.atime = PLib.Deep.atime + delt; + } + } while (PLib.isFlagSet(PLib.DO_LOOP_FLAG) && PLib.isFlagClear(PLib.EPOCH_RESTART_FLAG)); + } while (PLib.isFlagSet(PLib.DO_LOOP_FLAG) && PLib.isFlagSet(PLib.EPOCH_RESTART_FLAG)); + + deep_arg.xn = PLib.Deep.xni + xndot * ft + xnddt * ft * ft * 0.5; + xl = PLib.Deep.xli + xldot * ft + xndot * ft * ft * 0.5; + temp = -deep_arg.xnode + PLib.Deep.thgr + deep_arg.t * PLib.thdt; + + if (PLib.isFlagClear(PLib.SYNCHRONOUS_FLAG)) + deep_arg.xll = xl + temp + temp; + else + deep_arg.xll = xl - deep_arg.omgadf + temp; + + return; + + case dpper: + sinis = Math.sin(deep_arg.xinc); + cosis = Math.cos(deep_arg.xinc); + + if (Math.abs(PLib.Deep.savtsn - deep_arg.t) >= 30) + { + PLib.Deep.savtsn = deep_arg.t; + zm = PLib.Deep.zmos + PLib.zns * deep_arg.t; + zf = zm + 2 * PLib.zes * Math.sin(zm); + sinzf = Math.sin(zf); + f2 = 0.5 * sinzf * sinzf-0.25; + f3 = -0.5 * sinzf * Math.cos(zf); + ses = PLib.Deep.se2 * f2 + PLib.Deep.se3 * f3; + sis = PLib.Deep.si2 * f2 + PLib.Deep.si3 * f3; + sls = PLib.Deep.sl2 * f2 + PLib.Deep.sl3 * f3 + PLib.Deep.sl4 * sinzf; + PLib.Deep.sghs = PLib.Deep.sgh2 * f2 + PLib.Deep.sgh3 * f3 + PLib.Deep.sgh4 * sinzf; + PLib.Deep.shs = PLib.Deep.sh2 * f2 + PLib.Deep.sh3 * f3; + zm = PLib.Deep.zmol + PLib.znl * deep_arg.t; + zf = zm + 2 * zel * Math.sin(zm); + sinzf = Math.sin(zf); + f2 = 0.5 * sinzf * sinzf - 0.25; + f3 = -0.5 * sinzf * Math.cos(zf); + sel = PLib.Deep.ee2 * f2 + PLib.Deep.e3 * f3; + sil = PLib.Deep.xi2 * f2 + PLib.Deep.xi3 * f3; + sll = PLib.Deep.xl2 * f2 + PLib.Deep.xl3 * f3 + PLib.Deep.xl4 * sinzf; + PLib.Deep.sghl = PLib.Deep.xgh2 * f2 + PLib.Deep.xgh3 * f3 + PLib.Deep.xgh4 * sinzf; + PLib.Deep.sh1 = PLib.Deep.xh2 * f2 + PLib.Deep.xh3 * f3; + PLib.Deep.pe = ses + sel; + PLib.Deep.pinc = sis + sil; + PLib.Deep.pl = sls + sll; + } + + pgh = PLib.Deep.sghs + PLib.Deep.sghl; + ph = PLib.Deep.shs + PLib.Deep.sh1; + deep_arg.xinc = deep_arg.xinc + PLib.Deep.pinc; + deep_arg.em = deep_arg.em + PLib.Deep.pe; + + if (PLib.Deep.xqncl >= 0.2) + { + ph = ph / deep_arg.sinio; + pgh = pgh - deep_arg.cosio * ph; + deep_arg.omgadf = deep_arg.omgadf + pgh; + deep_arg.xnode = deep_arg.xnode + ph; + deep_arg.xll = deep_arg.xll + PLib.Deep.pl; + } + + else + { + sinok = Math.sin(deep_arg.xnode); + cosok = Math.cos(deep_arg.xnode); + alfdp = sinis * sinok; + betdp = sinis * cosok; + dalf = ph * cosok + PLib.Deep.pinc * cosis * sinok; + dbet = -ph * sinok + PLib.Deep.pinc * cosis * cosok; + alfdp = alfdp + dalf; + betdp = betdp + dbet; + deep_arg.xnode = FMod2p(deep_arg.xnode); + xls = deep_arg.xll + deep_arg.omgadf + cosis * deep_arg.xnode; + dls = PLib.Deep.pl + pgh - PLib.Deep.pinc * deep_arg.xnode * sinis; + xls = xls + dls; + xnoh = deep_arg.xnode; + deep_arg.xnode = Math.atan2(alfdp, betdp); + + if (Math.abs(xnoh - deep_arg.xnode) > PLib.pi) + { + if (deep_arg.xnode < xnoh) + deep_arg.xnode += PLib.twopi; + else + deep_arg.xnode -= PLib.twopi; + } + + deep_arg.xll = deep_arg.xll + PLib.Deep.pl; + deep_arg.omgadf = xls - deep_arg.xll - Math.cos(deep_arg.xinc) * deep_arg.xnode; + } + return; + } + }, + + SDP4: function(tsince, tle, pos, vel) + { + var i = 0; + + var a = 0.0, axn = 0.0, ayn = 0.0, aynl = 0.0, beta = 0.0, betal = 0.0, capu = 0.0, cos2u = 0.0, cosepw = 0.0, cosik = 0.0, + cosnok = 0.0, cosu = 0.0, cosuk = 0.0, ecose = 0.0, elsq = 0.0, epw = 0.0, esine = 0.0, pl = 0.0, theta4 = 0.0, rdot = 0.0, + rdotk = 0.0, rfdot = 0.0, rfdotk = 0.0, rk = 0.0, sin2u = 0.0, sinepw = 0.0, sinik = 0.0, sinnok = 0.0, sinu = 0.0, + sinuk = 0.0, tempe = 0.0, templ = 0.0, tsq = 0.0, u = 0.0, uk = 0.0, ux = 0.0, uy = 0.0, uz = 0.0, vx = 0.0, vy = 0.0, vz = 0.0, xinck = 0.0, xl = 0.0, + xlt = 0.0, xmam = 0.0, xmdf = 0.0, xmx = 0.0, xmy = 0.0, xnoddf = 0.0, xnodek = 0.0, xll = 0.0, a1 = 0.0, a3ovk2 = 0.0, ao = 0.0, c2 = 0.0, + coef = 0.0, coef1 = 0.0, x1m5th = 0.0, xhdot1 = 0.0, del1 = 0.0, r = 0.0, delo = 0.0, eeta = 0.0, eta = 0.0, etasq = 0.0, + perigee = 0.0, psisq = 0.0, tsi = 0.0, qoms24 = 0.0, s4 = 0.0, pinvsq = 0.0, temp = 0.0, tempa = 0.0, temp1 = 0.0, + temp2 = 0.0, temp3 = 0.0, temp4 = 0.0, temp5 = 0.0, temp6 = 0.0, bx = 0.0, by = 0.0, bz = 0.0, cx = 0.0, cy = 0.0, cz = 0.0; + + PLib.SDP4.deep_arg = PLib.SDP4.deep_arg || new PLib.deep_arg_t(); + + if (PLib.isFlagClear(PLib.SDP4_INITIALIZED_FLAG)) + { + PLib.SetFlag(PLib.SDP4_INITIALIZED_FLAG); + + a1 = Math.pow(PLib.xke / tle.xno, PLib.tothrd); + PLib.SDP4.deep_arg.cosio = Math.cos(tle.xincl); + PLib.SDP4.deep_arg.theta2 = PLib.SDP4.deep_arg.cosio * PLib.SDP4.deep_arg.cosio; + PLib.SDP4.x3thm1 = 3 * PLib.SDP4.deep_arg.theta2 - 1; + PLib.SDP4.deep_arg.eosq = tle.eo * tle.eo; + PLib.SDP4.deep_arg.betao2 = 1 - PLib.SDP4.deep_arg.eosq; + PLib.SDP4.deep_arg.betao = Math.sqrt(PLib.SDP4.deep_arg.betao2); + del1 = 1.5 * PLib.ck2 * PLib.SDP4.x3thm1 / (a1 * a1 * PLib.SDP4.deep_arg.betao * PLib.SDP4.deep_arg.betao2); + ao = a1 * (1 - del1 * (0.5 * PLib.tothrd + del1 * (1 + 134 / 81 * del1))); + delo = 1.5 * PLib.ck2 * PLib.SDP4.x3thm1 / (ao * ao * PLib.SDP4.deep_arg.betao * PLib.SDP4.deep_arg.betao2); + PLib.SDP4.deep_arg.xnodp = tle.xno / (1 + delo); + PLib.SDP4.deep_arg.aodp = ao / (1 - delo); + + s4 = s; + qoms24 = PLib.qoms2t; + perigee = (PLib.SDP4.deep_arg.aodp * (1 - tle.eo) - PLib.ae) * PLib.xkmper; + + if (perigee < 156.0) + { + if (perigee <= 98.0) + s4 = 20.0; + else + s4 = perigee - 78.0; + + qoms24 = Math.pow((120 - s4) * PLib.ae / xkmper,4); + s4 = s4 / PLib.xkmper + PLib.ae; + } + + pinvsq = 1 / (PLib.SDP4.deep_arg.aodp * PLib.SDP4.deep_arg.aodp * PLib.SDP4.deep_arg.betao2 * PLib.SDP4.deep_arg.betao2); + PLib.SDP4.deep_arg.sing = Math.sin(tle.omegao); + PLib.SDP4.deep_arg.cosg = Math.cos(tle.omegao); + tsi = 1 / (PLib.SDP4.deep_arg.aodp - s4); + eta = PLib.SDP4.deep_arg.aodp * tle.eo * tsi; + etasq = eta * eta; + eeta = tle.eo * eta; + psisq = Math.abs(1 - etasq); + coef = qoms24 * Math.pow(tsi, 4); + coef1 = coef / Math.pow(psisq, 3.5); + c2 = coef1 * PLib.SDP4.deep_arg.xnodp * (PLib.SDP4.deep_arg.aodp * (1 + 1.5 * etasq + eeta * (4 + etasq)) + 0.75 * PLib.ck2 * tsi / psisq * PLib.SDP4.x3thm1 * (8 + 3 * etasq * (8 + etasq))); + PLib.SDP4.c1 = tle.bstar * c2; + PLib.SDP4.deep_arg.sinio = Math.sin(tle.xincl); + a3ovk2 = -xj3 / ck2 * Math.pow(ae, 3); + PLib.SDP4.x1mth2 = 1 -PLib.SDP4.deep_arg.theta2; + PLib.SDP4.c4 = 2 * PLib.SDP4.deep_arg.xnodp * coef1 * PLib.SDP4.deep_arg.aodp * PLib.SDP4.deep_arg.betao2 * (eta * (2 + 0.5 * etasq) + tle.eo * (0.5 + 2 * etasq) - 2 * PLib.ck2 * tsi / (PLib.SDP4.deep_arg.aodp * psisq) * (-3 * PLib.SDP4.x3thm1 * (1 - 2 * eeta + etasq * (1.5 - 0.5 * eeta)) + 0.75 * PLib.SDP4.x1mth2 * (2 * etasq - eeta * (1 + etasq)) * Math.cos(2 * tle.omegao))); + theta4 = PLib.SDP4.deep_arg.theta2 * PLib.SDP4.deep_arg.theta2; + temp1 = 3 * PLib.ck2 * pinvsq * PLib.SDP4.deep_arg.xnodp; + temp2 = temp1 * PLib.ck2 * pinvsq; + temp3 = 1.25 * PLib.ck4 * pinvsq * pinvsq * PLib.SDP4.deep_arg.xnodp; + PLib.SDP4.deep_arg.xmdot = PLib.SDP4.deep_arg.xnodp + 0.5 * temp1 * PLib.SDP4.deep_arg.betao * PLib.SDP4.x3thm1 + 0.0625 * temp2 * PLib.SDP4.deep_arg.betao * (13 - 78 * PLib.SDP4.deep_arg.theta2 + 137 * theta4); + x1m5th = 1 - 5 * PLib.SDP4.deep_arg.theta2; + PLib.SDP4.deep_arg.omgdot = -0.5 * temp1 * x1m5th + 0.0625 * temp2 * (7 - 114 * PLib.SDP4.deep_arg.theta2 + 395 * theta4) + temp3 * (3 - 36 * PLib.SDP4.deep_arg.theta2 + 49 * theta4); + xhdot1 = -temp1 * PLib.SDP4.deep_arg.cosio; + PLib.SDP4.deep_arg.xnodot = xhdot1 + (0.5 * temp2 * (4 - 19 * PLib.SDP4.deep_arg.theta2) + 2 * temp3 * (3 - 7 * PLib.SDP4.deep_arg.theta2)) * PLib.SDP4.deep_arg.cosio; + PLib.SDP4.xnodcf = 3.5 * PLib.SDP4.deep_arg.betao2 * xhdot1 * PLib.SDP4.c1; + PLib.SDP4.t2cof = 1.5 * PLib.SDP4.c1; + PLib.SDP4.xlcof = 0.125 * a3ovk2 * PLib.SDP4.deep_arg.sinio * (3 + 5 * PLib.SDP4.deep_arg.cosio) / (1 + PLib.SDP4.deep_arg.cosio); + PLib.SDP4.aycof = 0.25 * a3ovk2 * PLib.SDP4.deep_arg.sinio; + PLib.SDP4.x7thm1 = 7 * PLib.SDP4.deep_arg.theta2 - 1; + + Deep(dpinit, tle, PLib.SDP4.deep_arg); + } + + xmdf = tle.xmo + PLib.SDP4.deep_arg.xmdot * tsince; + PLib.SDP4.deep_arg.omgadf = tle.omegao + PLib.SDP4.deep_arg.omgdot * tsince; + xnoddf = tle.xnodeo + PLib.SDP4.deep_arg.xnodot * tsince; + tsq = tsince * tsince; + PLib.SDP4.deep_arg.xnode = xnoddf + PLib.SDP4.xnodcf * tsq; + tempa = 1 - PLib.SDP4.c1 * tsince; + tempe = tle.bstar * PLib.SDP4.c4 * tsince; + templ = PLib.SDP4.t2cof * tsq; + PLib.SDP4.deep_arg.xn = PLib.SDP4.deep_arg.xnodp; + + PLib.SDP4.deep_arg.xll = xmdf; + PLib.SDP4.deep_arg.t = tsince; + + Deep(dpsec, tle, PLib.SDP4.deep_arg); + + xmdf = PLib.SDP4.deep_arg.xll; + a = Math.pow(PLib.xke / PLib.SDP4.deep_arg.xn, PLib.tothrd) * tempa * tempa; + PLib.SDP4.deep_arg.em = PLib.SDP4.deep_arg.em - tempe; + xmam = xmdf + PLib.SDP4.deep_arg.xnodp * templ; + + PLib.SDP4.deep_arg.xll = xmam; + + Deep(PLib.dpper, tle, PLib.SDP4.deep_arg); + + xmam = PLib.SDP4.deep_arg.xll; + xl = xmam + PLib.SDP4.deep_arg.omgadf + PLib.SDP4.deep_arg.xnode; + beta = Math.sqrt(1 - PLib.SDP4.deep_arg.em * PLib.SDP4.deep_arg.em); + PLib.SDP4.deep_arg.xn = PLib.xke / Math.pow(a, 1.5); + + axn = PLib.SDP4.deep_arg.em * Math.cos(PLib.SDP4.deep_arg.omgadf); + temp = 1 / (a * beta * beta); + xll = temp * PLib.SDP4.xlcof * axn; + aynl = temp * PLib.SDP4.aycof; + xlt = xl + xll; + ayn = PLib.SDP4.deep_arg.em * Math.sin(PLib.SDP4.deep_arg.omgadf) + aynl; + + capu = FMod2p(xlt - PLib.SDP4.deep_arg.xnode); + temp2 = capu; + i = 0; + + do + { + sinepw = Math.sin(temp2); + cosepw = Math.cos(temp2); + temp3 = axn * sinepw; + temp4 = ayn * cosepw; + temp5 = axn * cosepw; + temp6 = ayn * sinepw; + epw = (capu - temp4 + temp3 - temp2) / (1 - temp5 - temp6) + temp2; + + if (Math.abs(epw - temp2) <= e6a) + break; + + temp2 = epw; + + } while (i++ < 10); + + ecose = temp5 + temp6; + esine = temp3 - temp4; + elsq = axn * axn + ayn * ayn; + temp = 1 - elsq; + pl = a * temp; + r = a * (1 - ecose); + temp1 = 1 / r; + rdot = PLib.xke * Math.sqrt(a) * esine * temp1; + rfdot = PLib.xke * Math.sqrt(pl) * temp1; + temp2 = a * temp1; + betal = Math.sqrt(temp); + temp3 = 1 / (1 + betal); + cosu = temp2 * (cosepw - axn + ayn * esine * temp3); + sinu = temp2 * (sinepw - ayn - axn * esine * temp3); + u = Math.atan2(sinu, cosu); + sin2u = 2 * sinu * cosu; + cos2u = 2 * cosu * cosu - 1; + temp = 1 / pl; + temp1 = PLib.ck2 * temp; + temp2 = temp1 * temp; + + rk = r * (1 - 1.5 * temp2 * betal * PLib.SDP4.x3thm1) + 0.5 * temp1 * PLib.SDP4.x1mth2 * cos2u; + uk = u - 0.25 * temp2 * PLib.SDP4.x7thm1 * sin2u; + xnodek = PLib.SDP4.deep_arg.xnode + 1.5 * temp2 * PLib.SDP4.deep_arg.cosio * sin2u; + xinck = PLib.SDP4.deep_arg.xinc + 1.5 * temp2 * PLib.SDP4.deep_arg.cosio * PLib.SDP4.deep_arg.sinio * cos2u; + rdotk = rdot - PLib.SDP4.deep_arg.xn * temp1 * PLib.SDP4.x1mth2 * sin2u; + rfdotk = rfdot + PLib.SDP4.deep_arg.xn * temp1 * (PLib.SDP4.x1mth2 * cos2u + 1.5 * PLib.SDP4.x3thm1); + + sinuk = Math.sin(uk); + cosuk = Math.cos(uk); + sinik = Math.sin(xinck); + cosik = Math.cos(xinck); + sinnok = Math.sin(xnodek); + cosnok = Math.cos(xnodek); + xmx = -sinnok * cosik; + xmy = cosnok * cosik; + ux = xmx * sinuk + cosnok * cosuk; + uy = xmy * sinuk + sinnok * cosuk; + uz = sinik * sinuk; + vx = xmx * cosuk - cosnok * sinuk; + vy = xmy * cosuk - sinnok * sinuk; + vz = sinik * cosuk; + + pos.x = rk * ux; + pos.y = rk * uy; + pos.z = rk * uz; + vel.x = rdotk * ux + rfdotk * vx; + vel.y = rdotk * uy + rfdotk * vy; + vel.z = rdotk * uz + rfdotk * vz; + + PLib.phase = xlt - PLib.SDP4.deep_arg.xnode - PLib.SDP4.deep_arg.omgadf + PLib.twopi; + + if (PLib.phase < 0.0) + PLib.phase += PLib.twopi; + + PLib.phase = PLib.FMod2p(PLib.phase); + }, + + Calculate_User_PosVel: function(time, geodetic, obs_pos, obs_vel) + { + var c = 0.0, sq = 0.0, achcp = 0.0; + + geodetic.theta = PLib.FMod2p(PLib.ThetaG_JD(time) + geodetic.lon); + c = 1 / Math.sqrt(1 + PLib.f * (PLib.f - 2) * PLib.Sqr(Math.sin(geodetic.lat))); + sq = PLib.Sqr(1 - PLib.f) * c; + achcp = (PLib.xkmper * c + geodetic.alt) * Math.cos(geodetic.lat); + obs_pos.x = achcp * Math.cos(geodetic.theta); + obs_pos.y = achcp * Math.sin(geodetic.theta); + obs_pos.z = (PLib.xkmper * sq + geodetic.alt) * Math.sin(geodetic.lat); + obs_vel.x = -PLib.mfactor * obs_pos.y; + obs_vel.y = PLib.mfactor * obs_pos.x; + obs_vel.z = 0; + PLib.Magnitude(obs_pos); + PLib.Magnitude(obs_vel); + }, + + Calculate_LatLonAlt: function(time, pos, geodetic) + { + var r = 0.0, e2 = 0.0, phi = 0.0, c = 0.0; + + geodetic.theta = Math.atan2(pos.y, pos.x); + geodetic.lon = PLib.FMod2p(geodetic.theta - PLib.ThetaG_JD(time)); + r = Math.sqrt(PLib.Sqr(pos.x) + PLib.Sqr(pos.y)); + e2 = PLib.f * (2 - PLib.f); + geodetic.lat = Math.atan2(pos.z, r); + + do + { + phi = geodetic.lat; + c = 1 / Math.sqrt(1 - e2 * PLib.Sqr(Math.sin(phi))); + geodetic.lat = Math.atan2(pos.z + PLib.xkmper * c * e2 * Math.sin(phi), r); + + } while (Math.abs(geodetic.lat - phi) >= 1E-10); + + geodetic.alt = r / Math.cos(geodetic.lat) - PLib.xkmper * c; + + if (geodetic.lat > PLib.pio2) + geodetic.lat -= PLib.twopi; + }, + + Calculate_Obs: function(time, pos, vel, geodetic, obs_set) + { + var sin_lat = 0.0, cos_lat = 0.0, sin_theta = 0.0, cos_theta = 0.0, el = 0.0, azim = 0.0, top_s = 0.0, top_e = 0.0, top_z = 0.0; + + var obs_pos = new PLib.vector_t(); + var obs_vel = new PLib.vector_t(); + var range = new PLib.vector_t(); + var rgvel = new PLib.vector_t(); + + PLib.Calculate_User_PosVel(time, geodetic, obs_pos, obs_vel); + + range.x = pos.x - obs_pos.x; + range.y = pos.y - obs_pos.y; + range.z = pos.z - obs_pos.z; + + rx = range.x; + ry = range.y; + rz = range.z; + + rgvel.x = vel.x - obs_vel.x; + rgvel.y = vel.y - obs_vel.y; + rgvel.z = vel.z - obs_vel.z; + + PLib.Magnitude(range); + + sin_lat = Math.sin(geodetic.lat); + cos_lat = Math.cos(geodetic.lat); + sin_theta = Math.sin(geodetic.theta); + cos_theta = Math.cos(geodetic.theta); + top_s = sin_lat * cos_theta * range.x + sin_lat * sin_theta * range.y - cos_lat * range.z; + top_e = -sin_theta * range.x + cos_theta * range.y; + top_z = cos_lat * cos_theta * range.x+cos_lat * sin_theta * range.y + sin_lat * range.z; + azim = Math.atan(-top_e / top_s); + + if (top_s > 0.0) + azim = azim + PLib.pi; + + if (azim < 0.0) + azim = azim + PLib.twopi; + + el = Math.asin(top_z / range.w); + obs_set.x = azim; + obs_set.y = el; + obs_set.z = range.w; + + obs_set.w = PLib.Dot(range, rgvel) / range.w; + + obs_set.y = el; + + if (obs_set.y >= 0.0) + PLib.SetFlag(PLib.VISIBLE_FLAG); + else + { + obs_set.y = el; + PLib.ClearFlag(PLib.VISIBLE_FLAG); + } + }, + + InternalUpdate: function() + { + var tempnum; + + PLib.sat.designator = PLib.sat.line1.substring(9, 17); + PLib.sat.catnum = PLib.sat.line1.substring(2, 7); + PLib.sat.year = PLib.sat.line1.substring(18, 20); + PLib.sat.refepoch = PLib.sat.line1.substring(20, 32); + tempnum = 1.0e-5 * PLib.sat.line1.substring(44, 50); + PLib.sat.nddot6 = tempnum / Math.pow(10.0, PLib.sat.line1.charAt(51)); + tempnum = 1.0e-5 * PLib.sat.line1.substring(53, 59); + PLib.sat.bstar = tempnum / Math.pow(10.0, PLib.sat.line1.charAt(60)); + PLib.sat.setnum = PLib.sat.line1.substring(64, 68); + PLib.sat.incl = PLib.sat.line2.substring(8, 16); + PLib.sat.raan = PLib.sat.line2.substring(17, 25); + PLib.sat.eccn = 1.0e-07 * PLib.sat.line2.substring(26,33); + PLib.sat.argper = PLib.sat.line2.substring(34, 42); + PLib.sat.meanan = PLib.sat.line2.substring(43, 51); + PLib.sat.meanmo = PLib.sat.line2.substring(52, 63); + PLib.sat.drag = PLib.sat.line1.substring(33, 43); + PLib.sat.orbitnum = PLib.sat.line2.substring(63, 68); + }, + + InitializeData: function() + { + PLib.sat = new PLib.sat_t(); + PLib.sat.name = PLib.tleData[0]; + PLib.sat.line1 = PLib.tleData[1]; + PLib.sat.line2 = PLib.tleData[2]; + PLib.InternalUpdate(); + }, + + DayNum: function(m, d, y) + { + var dn = 0; + var mm = 0.0, yy = 0.0; + + if (m < 3) + { + y--; + m += 12; + } + + if (y <= 50) + y += 100; + + yy = y; + mm = m; + dn = (Math.floor(365.25 * (yy - 80.0)) - Math.floor(19.0 + yy / 100.0) + Math.floor(4.75 + yy / 400.0) - 16.0); + dn += d + 30 * m + Math.floor(0.6 * mm - 0.3); + + return dn; + }, + + CurrentDaynum: function() + { + var d = new Date(); + return (d.getTime() - 315446400000) / 86400000; + }, + + FutureDaynum: function (minutes) + { + var d = new Date (); + return (d.getTime() - 315446400000 + minutes * 1000 * 60) / 86400000; + }, + + Daynum2Date: function(daynum) + { + var d = new Date(); + d.setTime(daynum * 86400000 + 315446400000); + var x = d + 1; + return d; + }, + + PreCalc: function() + { + PLib.tle.sat_name = PLib.sat.name + PLib.tle.idesg = PLib.sat.designator; + PLib.tle.catnr = PLib.sat.catnum; + PLib.tle.epoch = (1000.0 * PLib.sat.year) + PLib.sat.refepoch * 1; + PLib.tle.xndt2o = PLib.sat.drag; + PLib.tle.xndd6o = PLib.sat.nddot6; + PLib.tle.bstar = PLib.sat.bstar; + PLib.tle.xincl = PLib.sat.incl; + PLib.tle.xnodeo = PLib.sat.raan; + PLib.tle.eo = PLib.sat.eccn; + PLib.tle.omegao = PLib.sat.argper; + PLib.tle.xmo = PLib.sat.meanan; + PLib.tle.xno = PLib.sat.meanmo; + PLib.tle.revnum = PLib.sat.orbitnum; + + PLib.ClearFlag(PLib.ALL_FLAGS); + PLib.select_ephemeris(PLib.tle); + }, + + Calc: function() + { + var zero_vector = new PLib.vector_t(); + var vel = new PLib.vector_t(); + var pos = new PLib.vector_t(); + var obs_set = new PLib.vector_t(); + var solar_vector = new PLib.vector_t(); + var solar_set = new PLib.vector_t(); + + var sat_geodetic = new PLib.geodetic_t(); + + PLib.jul_utc = PLib.daynum + 2444238.5; + + PLib.jul_epoch = PLib.Julian_Date_of_Epoch(PLib.tle.epoch); + PLib.tsince = (PLib.jul_utc - PLib.jul_epoch) * PLib.xmnpda; + PLib.age = PLib.jul_utc - PLib.jul_epoch; + + if (PLib.isFlagSet(PLib.DEEP_SPACE_EPHEM_FLAG)) + PLib.ephem = "SDP4"; + else + PLib.ephem = "SGP4"; + + if (PLib.isFlagSet(PLib.DEEP_SPACE_EPHEM_FLAG)) + PLib.SDP4(PLib.tsince, PLib.tle, pos, vel); + else + PLib.SGP4(PLib.tsince, PLib.tle, pos, vel); + + PLib.Convert_Sat_State(pos, vel); + + PLib.Magnitude(vel); + PLib.sat_vel = vel.w; + + PLib.Calculate_Obs(PLib.jul_utc, pos, vel, PLib.obs_geodetic, obs_set); + + PLib.Calculate_LatLonAlt(PLib.jul_utc, pos, sat_geodetic); + + PLib.Calculate_Solar_Position(PLib.jul_utc, solar_vector); + PLib.Calculate_Obs(PLib.jul_utc, solar_vector, zero_vector, PLib.obs_geodetic, solar_set); + + if (PLib.Sat_Eclipsed(pos, solar_vector)) + PLib.SetFlag(PLib.SAT_ECLIPSED_FLAG); + else + PLib.ClearFlag(PLib.SAT_ECLIPSED_FLAG); + + if (PLib.isFlagSet(PLib.SAT_ECLIPSED_FLAG)) + PLib.sat_sun_status = 0; + else + PLib.sat_sun_status = 1; + + PLib.sat_azi = PLib.Degrees(obs_set.x); + PLib.sat_ele = PLib.Degrees(obs_set.y); + PLib.sat_range = obs_set.z; + PLib.sat_range_rate = obs_set.w; + PLib.sat_lat = PLib.Degrees(sat_geodetic.lat); + PLib.sat_lon = PLib.Degrees(sat_geodetic.lon); + PLib.sat_alt = sat_geodetic.alt; + + PLib.fk = 12756.33 * Math.acos(PLib.xkmper / (PLib.xkmper + PLib.sat_alt)); + PLib.fm = PLib.fk / 1.609344; + + PLib.rv = Math.floor((PLib.tle.xno * PLib.xmnpda / PLib.twopi + PLib.age * PLib.tle.bstar * PLib.ae) * PLib.age + PLib.tle.xmo / PLib.twopi) + parseInt(PLib.tle.revnum); + + PLib.sun_azi = PLib.Degrees(solar_set.x); + PLib.sun_ele = PLib.Degrees(solar_set.y); + + PLib.irk = PLib.roundTo (PLib.sat_range, 2); + PLib.isplat = PLib.roundTo (PLib.sat_lat, 2); + PLib.isplong = PLib.roundTo (360.0 - PLib.sat_lon, 2); + PLib.iaz = PLib.roundTo (PLib.sat_azi, 2); + PLib.iel = PLib.roundTo (PLib.sat_ele, 2); + PLib.ma256 = Math.round(256.0 * (PLib.phase / PLib.twopi)); + + if (PLib.sat_sun_status) + { + if (PLib.sun_ele <= -12.0 && PLib.sat_ele >= 0.0) + PLib.findsun = '+'; + else + PLib.findsun = '*'; + } + else + PLib.findsun = ' '; + }, + + AosHappens: function() + { + var lin = 0.0, sma = 0.0, apogee = 0.0; + + if (PLib.sat.meanmo == 0.0) + return 0; + else + { + lin = PLib.sat.incl; + + if (lin >= 90.0) + lin = 180.0 - lin; + + sma = 331.25 * Math.exp(Math.log(1440.0 / PLib.sat.meanmo) * (2.0 / 3.0)); + apogee = sma * (1.0 + PLib.sat.eccn) - PLib.xkmper; + + if ((Math.acos(PLib.xkmper / (apogee + PLib.xkmper)) + (lin * PLib.deg2rad)) > Math.abs(PLib.qth.stnlat * PLib.deg2rad)) + return 1; + else + return 0; + } + }, + + Decayed: function(time) + { + var satepoch = 0.0; + + if (time == 0.0) + time = PLib.CurrentDaynum(); + + satepoch = PLib.DayNum(1, 0, PLib.sat.year) + PLib.sat.refepoch; + + if (satepoch + ((16.666666 - PLib.sat.meanmo) / (10.0 * Math.abs(PLib.sat.drag))) < time) + return 1; + else + return 0; + }, + + Geostationary: function() + { + if (Math.abs(PLib.sat.meanmo - 1.0027) < 0.0002) + return 1; + else + return 0; + }, + + FindAOS: function() + { + PLib.aostime = 0.0; + + if (PLib.AosHappens() && PLib.Geostationary() == 0 && PLib.Decayed(indx, PLib.daynum) == 0) + { + PLib.Calc(); + + while (PLib.sat_ele < -1.0) + { + PLib.daynum -= 0.00035 * (PLib.sat_ele * (((PLib.sat_alt / 8400.0) + 0.46)) - 2.0); + PLib.Calc(); + } + + while (PLib.aostime == 0.0) + { + if (Math.abs(PLib.sat_ele) < 0.03) + PLib.aostime = PLib.daynum; + else + { + PLib.daynum -= PLib.sat_ele * Math.sqrt(PLib.sat_alt) / 530000.0; + PLib.Calc(); + } + } + } + + return PLib.aostime; + }, + + FindLOS: function() + { + PLib.lostime = 0.0; + + if (PLib.Geostationary() == 0 && PLib.AosHappens() == 1 && PLib.Decayed(indx, PLib.daynum) == 0) + { + PLib.Calc(); + + do + { + PLib.daynum += PLib.sat_ele * Math.sqrt(PLib.sat_alt) / 502500.0; + PLib.Calc(); + + if (Math.abs(PLib.sat_ele) < 0.03) + PLib.lostime = PLib.daynum; + + } while (PLib.lostime == 0.0); + } + + return PLib.lostime; + }, + + // calculate preview for the next minutes in orbit + // @return: array with [longitude, latitude] value + calculateTrack: function (minutes) + { + var points = new Array (); + var longitude; + + PLib.PreCalc (); + for (var i = 0; i < minutes; i++) + { + PLib.daynum = PLib.FutureDaynum (i); + PLib.Calc (); + longitude = 360 - PLib.isplong; + if (longitude > 180) + longitude = -PLib.isplong; + points.push ([longitude, PLib.isplat]); + } + // document.getElementById ("debug").innerHTML = PLib.Daynum2Date (PLib.daynum); + return points; + }, + + QuickFind: function(satname) + { + var satInfo = new Object(); + + if ((PLib.sat.name == satname) || (satname == PLib.sat.catnum)) + { + PLib.daynum = PLib.CurrentDaynum(); + PLib.PreCalc(); + PLib.Calc(); + + if (PLib.Decayed(PLib.daynum) == 0) + { + satInfo.dateTime = PLib.Daynum2Date(PLib.daynum); + satInfo.elevation = PLib.iel; + satInfo.azimuth = PLib.iaz; + satInfo.orbitalPhase = PLib.ma256; + satInfo.latitude = PLib.isplat; + satInfo.altitude = Math.round (PLib.sat_alt); + + var lng = 360 - PLib.isplong; + if (lng > 180) + lng = -PLib.isplong; + satInfo.longitude = lng; + + satInfo.slantRange = PLib.irk; + satInfo.orbitNumber = PLib.rv; + satInfo.visibility = PLib.findsun; + } + } + return satInfo; + }, + + formatDateOnly: function(dt) + { + var months = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]; + return months[dt.getMonth()] + " " + dt.getDate(); + }, + + formatTimeOnly: function(dt) + { + var h = dt.getHours(); + var m = dt.getMinutes(); + + var amPm = h < 12 ? "AM" : "PM" + + h = h > 12 ? h - 12 : h; + h = h == 0 ? h = 12 : h; + m = m < 10 ? "0" + m : m; + + return h + ":" + m + amPm; + }, + + extractDate: function(dt) + { + var d = new Date(); + d.setTime(dt.valueOf()); + d.setHours(0); + d.setMinutes(0); + d.setSeconds(0); + d.setMilliseconds(0); + + return d; + }, + + addDay: function(dt) + { + var d = new Date(dt.getTime() + 86400000); + return d; + }, + + getTodaysPasses: function() + { + var satInfoColl = new Array(); + var arrIdx = 0; + var x = 0, y = 0, z = 0, lastel = 0; + var start = 0, now = 0; + + now = (3651.0 + PLib.CurrentDaynum()) * 86400.0; + + if (start == 0) + start = now; + + if ((start >= now - 31557600) && (start <= now + 31557600)) + { + PLib.daynum = (start / 86400.0) - 3651.0; + PLib.PreCalc(); + PLib.Calc(); + + var d = new Date(); + var passNo = 1; + + if (PLib.AosHappens() && PLib.Geostationary() == 0 && PLib.Decayed(PLib.daynum) == 0) + { + PLib.daynum = PLib.FindAOS(); + + while (PLib.Daynum2Date(PLib.daynum) < PLib.addDay(d)) + { + var satInfo = new Object(); + + satInfo.number = z + 1; + satInfo.name = PLib.sat.name; + satInfo.passNo = passNo++; + satInfo.dateTimeStart = PLib.Daynum2Date(PLib.daynum); + satInfo.peakElevation = PLib.iel; + satInfo.riseAzimuth + = satInfo.peakAzimuth + = PLib.iaz; + satInfo.orbitalPhase = PLib.ma256; + satInfo.latitude = PLib.isplat; + + var lng = 360 - PLib.isplong; + if (lng > 180) lng = -PLib.isplong; + satInfo.longitude = lng; + + satInfo.riseRange + = satInfo.peakRange + = PLib.irk; + satInfo.orbitNumber = PLib.rv; + + var plusCount = 0; + var asteriskCount = 0; + + while (PLib.iel >= 0) + { + if (PLib.iel > satInfo.peakElevation) + { + satInfo.peakElevation = PLib.iel; + satInfo.peakAzimuth = PLib.iaz; + satInfo.peakRange = PLib.irk; + } + + if (PLib.findsun == '+') + plusCount++; + else if (PLib.findsun == '*') + asteriskCount++; + + lastel = PLib.iel; + PLib.daynum += Math.cos((PLib.sat_ele - 1.0) * PLib.deg2rad) * Math.sqrt(PLib.sat_alt) / 25000.0; + PLib.Calc(); + } + + if (lastel != 0) + { + PLib.daynum = PLib.FindLOS(); + PLib.Calc(); + } + + satInfo.dateTimeEnd = PLib.Daynum2Date(PLib.daynum); + satInfo.decayAzimuth = PLib.iaz; + satInfo.decayRange = PLib.irk; + + if ((plusCount > 3) || (plusCount > 2 && asteriskCount > 2)) + { + satInfo.visibility = '+'; + } + else if (asteriskCount > 2) + { + satInfo.visibility = '*'; + } + + satInfoColl[arrIdx++] = satInfo; + + PLib.daynum += (1 / 24 / 6); + PLib.daynum = PLib.FindAOS(); + } + } + } + + return satInfoColl; + }, + + configureGroundStation: function(lat, lng, alt, name) + { + PLib.qth.stnlat = lat; + PLib.qth.stnalt = alt; + PLib.qth.name = name; + + if (lng < 0) PLib.qth.stnlong = -lng; + else PLib.qth.stnlong = 360 - lng; + + PLib.obs_geodetic.lat = PLib.qth.stnlat * PLib.deg2rad; + PLib.obs_geodetic.lon = -PLib.qth.stnlong * PLib.deg2rad; + PLib.obs_geodetic.alt = PLib.qth.stnalt / 1000.0; + PLib.obs_geodetic.theta = 0.0; + }, + + // FIXME: find a better way to round + roundTo: function (num, dec) + { + return Math.round (Math.round (num * Math.pow (10, dec + 1) / 10.0)) / Math.pow (10, dec); + } + }; + +PLib.obs_geodetic = new PLib.geodetic_t(); +PLib.tle = new PLib.tle_t(); + +// vim: ts=2 tw=0 expandtab diff --git a/tools/mmd/tracker.wsgi b/tools/mmd/tracker.wsgi new file mode 100644 index 0000000..cd64971 --- /dev/null +++ b/tools/mmd/tracker.wsgi @@ -0,0 +1,106 @@ +#!/usr/bin/env python + +from cgi import escape +from urlparse import parse_qs + +def application (environ, response): + """ + beginning of WSGI/python application for + MURSAT1 Tracker + """ + + body = ''' + + + + + MURSAT1 tracker + + + + + + + + +
+ , + Lon: + , + Lat: + , + Alt: + +
+
+ + + + + + + + + + + + + + + +
LongitudeLatitudeAzimuthElevationAltitude
+ + + + +
+
Set refresh rate to + seconds +
+
+ + preview for the next + minutes +
+

+
+'''
+
+  qs = parse_qs (environ['QUERY_STRING'], True)
+  if qs.has_key ('longitude') and qs.has_key ('latitude') and qs.has_key ('altitude'):
+    query = {
+      'longitude': escape (qs.get ('longitude')[0]),
+      'latitude': escape (qs.get ('latitude')[0]),
+      'altitude': escape (qs.get ('altitude')[0])
+      }
+    if qs.has_key ('name'):
+      query ['name'] = escape (qs.get ('name')[0])
+    else:
+      query ['name'] = 'unknown set'
+  else:
+    query = {
+      'longitude': 15.44226,
+      'latitude': 47.06576,
+      'altitude': 376,
+      'name': 'Graz'
+      }
+
+  body = body.format (**query)
+  headers = ([('Content-Type', 'text/html'), ('Content-Length', str (len (body)))])
+  response ('200 OK', headers)
+
+  return [body]
+
+# vim: tw=0 ts=2 expandtab
+# EOF
-- 
cgit v1.2.3