Replace gpredict.js with satellite.js
package.json: Add satellite.js dependency Signed-off-by: Fabian P. Schmidt <kerel@mailbox.org> Move to satellite.js in map, drop satellite footprint Signed-off-by: Fabian P. Schmidt <kerel@mailbox.org> Remove gpredict.js dependency Signed-off-by: Fabian P. Schmidt <kerel@mailbox.org> Replace gpredict.js with satellite.js Builds on the work of kerel-fs in !596 and #440, implements satellite.js for core TLE and SGP4 handling, deprecating and removing gpredict.js fixes #440 does NOT fix #204 Signed-off-by: Corey Shields <cshields@gmail.com>spacecruft
parent
8adda93204
commit
2b17d32a67
|
@ -13,7 +13,7 @@ from django.core.exceptions import ObjectDoesNotExist
|
|||
from django.core.paginator import Paginator
|
||||
from django.db import OperationalError
|
||||
from django.db.models import Count, Max, Prefetch, Q
|
||||
from django.http import HttpResponse, JsonResponse
|
||||
from django.http import HttpResponse, HttpResponseServerError, JsonResponse
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
|
@ -332,8 +332,11 @@ def recent_decoded_cnt(request, norad):
|
|||
|
||||
:returns: JSON of point counts as JsonResponse
|
||||
"""
|
||||
results = read_influx(norad)
|
||||
return JsonResponse(results, safe=False)
|
||||
if settings.USE_INFLUX:
|
||||
results = read_influx(norad)
|
||||
return JsonResponse(results, safe=False)
|
||||
|
||||
return HttpResponseServerError()
|
||||
|
||||
|
||||
class TransmitterCreateView(LoginRequiredMixin, BSModalCreateView):
|
||||
|
|
|
@ -1,121 +1,169 @@
|
|||
/*global mapboxgl Sat_t gtk_sat_data_read_sat predict_calc julian_date Geodetic_t radians xkmper de2ra asin sin cos arccos degrees pio2 pi fabs */
|
||||
/*global mapboxgl satellite */
|
||||
|
||||
$(document).ready(function() {
|
||||
'use strict';
|
||||
|
||||
var name = $('div#map').data('name');
|
||||
var sin = Math.sin;
|
||||
var cos = Math.cos;
|
||||
var fabs = Math.abs;
|
||||
var acos = Math.acos;
|
||||
var asin = Math.asin;
|
||||
|
||||
var pi = Math.pi;
|
||||
var earthRadius = 6.378135E3; /* Earth radius km */
|
||||
var de2ra = 1.74532925E-2; /* Degrees to Radians */
|
||||
var pio2 =1.5707963267949; /* Pi/2 */
|
||||
|
||||
var tle1 = $('div#map').data('tle1');
|
||||
var tle2 = $('div#map').data('tle2');
|
||||
var mapboxtoken = $('div#map').data('mapboxtoken');
|
||||
|
||||
mapboxgl.accessToken = mapboxtoken;
|
||||
|
||||
// Load satellite orbit data from TLE
|
||||
var sat = new Sat_t();
|
||||
gtk_sat_data_read_sat([name, tle1, tle2], sat);
|
||||
/* Returns angle in radians from arg id degrees */
|
||||
function radians(arg) {
|
||||
return (arg * de2ra);
|
||||
}
|
||||
|
||||
/* Returns angle in degrees from arg in rads */
|
||||
function degrees(arg) {
|
||||
return (arg / de2ra);
|
||||
}
|
||||
|
||||
function get_orbits(sat) {
|
||||
// NOTE: This function has side effects (alters sat)!
|
||||
/** brief Arccosine implementation.
|
||||
*
|
||||
* Returns a value between zero and two pi.
|
||||
* Borrowed from gsat 0.9 by Xavier Crehueras, EB3CZS.
|
||||
* Optimized by Alexandru Csete.
|
||||
*/
|
||||
function arccos(x, y) {
|
||||
if (x && y) {
|
||||
if (y > 0.0) {
|
||||
return Math.acos(x / y);
|
||||
}
|
||||
else if (y < 0.0) {
|
||||
return pi + Math.acos(x / y);
|
||||
}
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
function get_orbits(satrec, t) {
|
||||
/**
|
||||
* Calculate 300 orbital points with 60 second increments, starting at epoch t
|
||||
*
|
||||
* @return {Array} Array that contains Arrays of geodetic (lon, lat) pairs in degrees
|
||||
*/
|
||||
|
||||
// Number of positions to compute
|
||||
var COUNT = 300;
|
||||
const COUNT = 300;
|
||||
|
||||
// Interval in ms between positions to compute
|
||||
var STEP = 60*1000;
|
||||
const STEP = 60*1000;
|
||||
|
||||
// Create satellite orbit
|
||||
var current_orbit = [];
|
||||
var all_orbits = [];
|
||||
|
||||
var t = new Date();
|
||||
|
||||
var previous = 0;
|
||||
for ( var i = 0; i < COUNT; i++) {
|
||||
predict_calc(sat, (0,0), julian_date(t));
|
||||
const coords = calc_geodetic_coords(satrec, t) ;
|
||||
|
||||
if (Math.abs(sat.ssplon - previous) > 180) {
|
||||
// orbit crossing -PI, PI
|
||||
if (Math.abs(coords['lon'] - previous) > 180) {
|
||||
// Satellite passed the 180th meridian.
|
||||
// Save last orbital point and
|
||||
// start new Array for the next orbit
|
||||
current_orbit.push([coords['lon']+360, coords['lat']]);
|
||||
all_orbits.push(current_orbit);
|
||||
current_orbit = [];
|
||||
}
|
||||
|
||||
current_orbit.push([sat.ssplon, sat.ssplat]);
|
||||
previous = sat.ssplon;
|
||||
current_orbit.push([coords['lon'], coords['lat']]);
|
||||
previous = coords['lon'];
|
||||
|
||||
// Increase time for next point
|
||||
t.setTime(t.getTime() + STEP);
|
||||
}
|
||||
|
||||
return all_orbits;
|
||||
}
|
||||
|
||||
function get_range_circle(sat_ssplat, sat_ssplon, sat_footprint) {
|
||||
// NOTE: This function has side effects (alters sat)!
|
||||
function calc_geodetic_coords(satrec, t) {
|
||||
const positionAndVelocity = satellite.propagate(satrec, t);
|
||||
const gmst = satellite.gstime(t);
|
||||
const positionEci = positionAndVelocity.position;
|
||||
const positionGd = satellite.eciToGeodetic(positionEci, gmst);
|
||||
const longitude = satellite.degreesLong(positionGd.longitude);
|
||||
const latitude = satellite.degreesLat(positionGd.latitude);
|
||||
|
||||
var azi;
|
||||
// var msx, msy, ssx, ssy;
|
||||
var ssplat,
|
||||
return {'lon': longitude,
|
||||
'lat': latitude,
|
||||
'height': positionGd.height};
|
||||
}
|
||||
|
||||
function get_range_circle(current_coords) {
|
||||
// first we have to calculate the footprint
|
||||
var footprint = 12756.33 * acos (earthRadius / (earthRadius+current_coords.height));
|
||||
|
||||
var azi,
|
||||
ssplat,
|
||||
ssplon,
|
||||
beta,
|
||||
azimuth,
|
||||
num,
|
||||
dem;
|
||||
// var rangelon, rangelat, mlon;
|
||||
|
||||
var geo = new Geodetic_t();
|
||||
|
||||
/* Range circle calculations.
|
||||
* Borrowed from gsat 0.9.0 by Xavier Crehueras, EB3CZS
|
||||
* who borrowed from John Magliacane, KD2BD.
|
||||
* Optimized by Alexandru Csete and William J Beksi.
|
||||
*/
|
||||
ssplat = radians(sat_ssplat);
|
||||
ssplon = radians(sat_ssplon);
|
||||
beta = (0.5 * sat_footprint) / xkmper;
|
||||
ssplat = radians(current_coords.lat);
|
||||
ssplon = radians(current_coords.lon);
|
||||
beta = (0.5 * footprint) / earthRadius;
|
||||
|
||||
var points = [];
|
||||
var lat = 0.0;
|
||||
var lon = 0.0;
|
||||
|
||||
for (azi = 0; azi < 360; azi += 5) {
|
||||
azimuth = de2ra * azi;
|
||||
geo.lat = asin(sin(ssplat) * cos(beta) + cos(azimuth) * sin(beta)
|
||||
lat = asin(sin(ssplat) * cos(beta) + cos(azimuth) * sin(beta)
|
||||
* cos(ssplat));
|
||||
num = cos(beta) - (sin(ssplat) * sin(geo.lat));
|
||||
dem = cos(ssplat) * cos(geo.lat);
|
||||
num = cos(beta) - (sin(ssplat) * sin(lat));
|
||||
dem = cos(ssplat) * cos(lat);
|
||||
|
||||
if (azi == 0 && (beta > pio2 - ssplat)) {
|
||||
geo.lon = ssplon + pi;
|
||||
lon = ssplon + pi;
|
||||
}
|
||||
else if (azi == 180 && (beta > pio2 + ssplat)) {
|
||||
geo.lon = ssplon + pi;
|
||||
lon = ssplon + pi;
|
||||
}
|
||||
else if (fabs(num / dem) > 1.0) {
|
||||
geo.lon = ssplon;
|
||||
lon = ssplon;
|
||||
} else {
|
||||
if ((180 - azi) >= 0) {
|
||||
geo.lon = ssplon - arccos(num, dem);
|
||||
lon = ssplon - arccos(num, dem);
|
||||
} else {
|
||||
geo.lon = ssplon + arccos(num, dem);
|
||||
lon = ssplon + arccos(num, dem);
|
||||
}
|
||||
}
|
||||
|
||||
points.push([degrees(geo.lon), degrees(geo.lat)]);
|
||||
points.push([degrees(lon), degrees(lat)]);
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
function get_location(sat) {
|
||||
// NOTE: This function has side effects (alters sat)!
|
||||
var now = new Date();
|
||||
predict_calc(sat, (0, 0), julian_date(now));
|
||||
// Load satellite orbit data from TLE
|
||||
var satrec = satellite.twoline2satrec(tle1, tle2);
|
||||
|
||||
return [sat.ssplon, sat.ssplat];
|
||||
}
|
||||
|
||||
// Calculate orbits, footprint and current satellite location
|
||||
var sat_location = get_location(sat);
|
||||
var footprint = get_range_circle(sat.ssplat, sat.ssplon, sat.footprint);
|
||||
var all_orbits = get_orbits(sat);
|
||||
// Calculate orbits and current satellite location
|
||||
const now = new Date();
|
||||
var current_coords = calc_geodetic_coords(satrec, now);
|
||||
var sat_location = [current_coords.lon, current_coords.lat];
|
||||
var footprint = get_range_circle(current_coords);
|
||||
|
||||
var all_orbits = get_orbits(satrec, now);
|
||||
|
||||
var map = new mapboxgl.Map({
|
||||
container: 'map',
|
||||
|
@ -211,13 +259,12 @@ $(document).ready(function() {
|
|||
});
|
||||
|
||||
function update_map() {
|
||||
// Recalculate footprint and current satellite location
|
||||
sat_location = get_location(sat);
|
||||
footprint = get_range_circle(sat.ssplat, sat.ssplon, sat.footprint);
|
||||
|
||||
// Recalculate current satellite location
|
||||
current_coords = calc_geodetic_coords(satrec, new Date());
|
||||
sat_location = [current_coords.lon, current_coords.lat];
|
||||
footprint = get_range_circle(current_coords);
|
||||
location_data.features[0].geometry.coordinates = sat_location;
|
||||
footprint_data.features[0].geometry.coordinates = [footprint];
|
||||
|
||||
map.getSource('sat_location').setData(location_data);
|
||||
map.getSource('sat_footprint').setData(footprint_data);
|
||||
}
|
||||
|
|
|
@ -604,10 +604,11 @@
|
|||
<script src="{% static 'js/jquery.bootstrap.modal.forms.min.js' %}"></script>
|
||||
<script src="{% static 'lib/admin-lte/plugins/moment/moment.min.js' %}"></script>
|
||||
<script src="{% static 'lib/admin-lte/plugins/chart.js/Chart.bundle.min.js' %}"></script>
|
||||
<script src="{% static 'lib/gpredict.js/dist/gpredict.min.js' %}"></script>
|
||||
<script src="{% static 'js/satellite.js' %}"></script>
|
||||
{% if showmap %}
|
||||
<script src="{% static 'lib/mapbox-gl/dist/mapbox-gl.js' %}"></script>
|
||||
<script src="{% static 'lib/mathjs/lib/browser/math.js' %}"></script>
|
||||
<script src="{% static 'lib/satellite.js/dist/satellite.min.js' %}"></script>
|
||||
<script src="{% static 'js/map.js' %}"></script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -1486,6 +1486,11 @@
|
|||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
|
||||
},
|
||||
"complex.js": {
|
||||
"version": "2.0.11",
|
||||
"resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.0.11.tgz",
|
||||
"integrity": "sha512-6IArJLApNtdg1P1dFtn3dnyzoZBEF0MwMnrfF1exSBRpZYoy4yieMkpZhQDC0uwctw48vii0CFVyHfpgZ/DfGw=="
|
||||
},
|
||||
"component-emitter": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
|
||||
|
@ -2154,6 +2159,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"decimal.js": {
|
||||
"version": "10.2.1",
|
||||
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.2.1.tgz",
|
||||
"integrity": "sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw=="
|
||||
},
|
||||
"decode-uri-component": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
|
||||
|
@ -2528,6 +2538,11 @@
|
|||
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
|
||||
"dev": true
|
||||
},
|
||||
"escape-latex": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-latex/-/escape-latex-1.2.0.tgz",
|
||||
"integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw=="
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
|
@ -3235,6 +3250,11 @@
|
|||
"for-in": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"fraction.js": {
|
||||
"version": "4.0.13",
|
||||
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.0.13.tgz",
|
||||
"integrity": "sha512-E1fz2Xs9ltlUp+qbiyx9wmt2n9dRzPsS11Jtdb8D2o+cC7wr9xkkKsVKJuBX0ST+LVS+LhLO+SbLJNtfWcJvXA=="
|
||||
},
|
||||
"fragment-cache": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
|
||||
|
@ -3489,10 +3509,6 @@
|
|||
"minimist": "^1.2.5"
|
||||
}
|
||||
},
|
||||
"gpredict.js": {
|
||||
"version": "github:kerel-fs/gpredict.js#611b18c073a66449c39e712017fbdcbc73972f2c",
|
||||
"from": "github:kerel-fs/gpredict.js"
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
|
||||
|
@ -4266,6 +4282,11 @@
|
|||
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
|
||||
"dev": true
|
||||
},
|
||||
"javascript-natural-sort": {
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz",
|
||||
"integrity": "sha1-+eIwPUUH9tdDVac2ZNFED7Wg71k="
|
||||
},
|
||||
"jquery": {
|
||||
"version": "3.5.1",
|
||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz",
|
||||
|
@ -4699,6 +4720,21 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"mathjs": {
|
||||
"version": "9.2.0",
|
||||
"resolved": "https://registry.npmjs.org/mathjs/-/mathjs-9.2.0.tgz",
|
||||
"integrity": "sha512-R2fQxaOmyifxgP4+c59dnfLwpKI1KYHdnT5lLwDuHIZvgyGb71M8ay6kTJTEv9rG04pduqvX4tbBUoG5ypTF8A==",
|
||||
"requires": {
|
||||
"complex.js": "^2.0.11",
|
||||
"decimal.js": "^10.2.1",
|
||||
"escape-latex": "^1.2.0",
|
||||
"fraction.js": "^4.0.13",
|
||||
"javascript-natural-sort": "^0.7.1",
|
||||
"seedrandom": "^3.0.5",
|
||||
"tiny-emitter": "^2.1.0",
|
||||
"typed-function": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"mathml-tag-names": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz",
|
||||
|
@ -6094,6 +6130,11 @@
|
|||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"satellite.js": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/satellite.js/-/satellite.js-4.1.3.tgz",
|
||||
"integrity": "sha512-l65XHxmT4n31DSGQy/jnu/sLfKn42g862h1p9NyalOEYCpEsplFAqUIT4+euK0AByizZML2Zkjbl0HWI79KC0A=="
|
||||
},
|
||||
"sax": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
||||
|
@ -6113,6 +6154,11 @@
|
|||
"get-assigned-identifiers": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"seedrandom": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz",
|
||||
"integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg=="
|
||||
},
|
||||
"select2": {
|
||||
"version": "4.0.13",
|
||||
"resolved": "https://registry.npmjs.org/select2/-/select2-4.0.13.tgz",
|
||||
|
@ -7019,6 +7065,11 @@
|
|||
"integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=",
|
||||
"dev": true
|
||||
},
|
||||
"tiny-emitter": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
|
||||
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
|
||||
},
|
||||
"tiny-inflate": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz",
|
||||
|
@ -7150,6 +7201,11 @@
|
|||
"integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
|
||||
"dev": true
|
||||
},
|
||||
"typed-function": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/typed-function/-/typed-function-2.0.0.tgz",
|
||||
"integrity": "sha512-Hhy1Iwo/e4AtLZNK10ewVVcP2UEs408DS35ubP825w/YgSBK1KVLwALvvIG4yX75QJrxjCpcWkzkVRB0BwwYlA=="
|
||||
},
|
||||
"typedarray": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
||||
|
|
|
@ -19,17 +19,19 @@
|
|||
"admin-lte": "^3.0",
|
||||
"d3": "^6.3.0",
|
||||
"flot": "^4.2.1",
|
||||
"gpredict.js": "github:kerel-fs/gpredict.js",
|
||||
"mapbox-gl": "^2.0.0",
|
||||
"mathjs": "^9.2.0",
|
||||
"satellite.js": "^4.1.3",
|
||||
"swagger-ui-dist": "^3.39.0"
|
||||
},
|
||||
"assets": [
|
||||
"admin-lte/**/*",
|
||||
"d3/dist/d3.min.js",
|
||||
"flot/dist/**/*",
|
||||
"gpredict.js/dist/gpredict.min.js",
|
||||
"mapbox-gl/dist/mapbox-gl.css",
|
||||
"mapbox-gl/dist/mapbox-gl.js",
|
||||
"mathjs/lib/browser/math.js",
|
||||
"satellite.js/dist/satellite.min.js",
|
||||
"swagger-ui-dist/swagger-ui.css",
|
||||
"swagger-ui-dist/swagger-ui-bundle.js"
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue