Skip to content

Commit

Permalink
fix: 🐛 fix degrees vs radians issues
Browse files Browse the repository at this point in the history
  • Loading branch information
thkruz committed Jan 1, 2024
1 parent c6824a4 commit 6103597
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 79 deletions.
23 changes: 19 additions & 4 deletions examples/sensor.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
/* eslint-disable no-console */
import { Satellite } from '@src/objects/Satellite';
import { calcGmst, ecf2eci, eci2lla, eci2rae } from '@src/transforms/transforms';
import { DEG2RAD } from '@src/utils/constants';
import { Sensor } from '../src/objects';
import { Degrees, Kilometers, SpaceObjectType, TleLine1, TleLine2, Transforms } from '../src/ootk';

Expand Down Expand Up @@ -30,15 +32,28 @@ const sat = new Satellite({

const date = new Date('2023-12-31T20:51:19.934Z');

const rae = Transforms.ecf2rae(testSensor, {
const ecf = {
x: 4000 as Kilometers,
y: 7000 as Kilometers,
z: 3000 as Kilometers,
});
};
// const ecf2 = { x: 982.8336640053099, y: -6779.137352354403, z: 3813.7284924837254 } as EcfVec3<Kilometers>;

const rae = Transforms.ecf2rae(testSensor, ecf);

const { gmst } = calcGmst(date);
const rae2 = eci2rae(date, ecf2eci(ecf, gmst), testSensor);
const lla = eci2lla(ecf2eci(ecf, gmst), gmst);

console.log(rae);
console.log(rae2);
console.log({
lat: lla.lat * DEG2RAD,
lon: lla.lon * DEG2RAD,
alt: lla.alt,
});

// sat.propagateTo(date);

// console.log(sat.raeOpt(capeCodRadar, date));
console.log(sat.getJ2000().inertial);
console.log(sat.raeOpt(testSensor, date));
console.log(sat.getJ2000(date).toITRF().toGeodetic());
8 changes: 7 additions & 1 deletion src/objects/Satellite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,13 @@ export class Satellite {
const eci = this.getEci(date).position;
const ecf = Transforms.eci2ecf(eci, gmst);

return Transforms.ecf2rae(sensor, ecf);
const lla = {
lat: (sensor.lat * DEG2RAD) as Radians,
lon: (sensor.lon * DEG2RAD) as Radians,
alt: sensor.alt,
};

return Transforms.ecf2rae(lla, ecf);
}

/**
Expand Down
95 changes: 83 additions & 12 deletions src/transforms/transforms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@
* Orbital Object ToolKit. If not, see <http://www.gnu.org/licenses/>.
*/

import { Sensor, Sgp4, Utils } from '@src/ootk';
import {
Degrees,
EcefVec3,
EcfVec3,
EciVec3,
EnuVec3,
GreenwichMeanSiderealTime,
Kilometers,
LlaVec3,
RadarSensor,
Expand All @@ -38,7 +40,7 @@ import {
RuvVec3,
SezVec3,
} from '../types/types';
import { DEG2RAD, PI, RAD2DEG, TAU } from '../utils/constants';
import { DAY_TO_MS, DEG2RAD, PI, RAD2DEG, TAU } from '../utils/constants';

/**
* Converts Azimuth and Elevation to U and V.
Expand Down Expand Up @@ -182,10 +184,35 @@ export function enu2rf<D extends number, A extends number = Radians>({ x, y, z }
};
}

/**
* Calculates Geodetic Lat Lon Alt to ECF coordinates.
*/
export function lla2ecf<D extends number>(lla: LlaVec3<Radians, D>): EcfVec3<D> {
const { lon, lat, alt } = lla;

const a = 6378.137;
const b = 6356.7523142;
const f = (a - b) / a;
const e2 = 2 * f - f * f;
const normal = a / Math.sqrt(1 - e2 * (Math.sin(lat) * Math.sin(lat)));

const x = (normal + alt) * Math.cos(lat) * Math.cos(lon);
const y = (normal + alt) * Math.cos(lat) * Math.sin(lon);
const z = (normal * (1 - e2) + alt) * Math.sin(lat);

return {
x: <D>x,
y: <D>y,
z: <D>z,
};
}

/**
* Calculates Geodetic Lat Lon Alt to ECEF coordinates.
*
* @deprecated This needs to be validated.
*/
export function lla2ecf<D extends number>(lla: LlaVec3<Radians, D>): EcefVec3<D> {
export function lla2ecef<D extends number>(lla: LlaVec3<Degrees, D>): EcefVec3<D> {
const { lat, lon, alt } = lla;
const a = 6378.137; // semi-major axis length in meters according to the WGS84
const b = 6356.752314245; // semi-minor axis length in meters according to the WGS84
Expand All @@ -202,13 +229,13 @@ export function lla2ecf<D extends number>(lla: LlaVec3<Radians, D>): EcefVec3<D>
* Converts LLA to SEZ coordinates.
* @see http://www.celestrak.com/columns/v02n02/
*/
export function lla2sez<D extends number>(lla: LlaVec3<Degrees, D>, ecf: EcfVec3<D>): SezVec3<D> {
const lat = (lla.lat * DEG2RAD) as Radians;
const lon = (lla.lon * DEG2RAD) as Radians;
export function lla2sez<D extends number>(lla: LlaVec3<Radians, D>, ecf: EcfVec3<D>): SezVec3<D> {
const lat = lla.lat;
const lon = lla.lon;

const observerEcf = lla2ecf({
lat: (lla.lat * DEG2RAD) as Radians,
lon: (lla.lon * DEG2RAD) as Radians,
lat,
lon,
alt: <Kilometers>0,
});

Expand Down Expand Up @@ -375,13 +402,57 @@ export function uv2azel(u: Radians, v: Radians, coneHalfAngle: Radians): { az: R
* @param ecf The Earth-Centered Fixed (ECF) coordinates.
* @returns The Right Ascension (RA), Elevation (E), and Azimuth (A) coordinates.
*/
export function ecf2rae<D extends number>(lla: LlaVec3<Degrees, D>, ecf: EcfVec3<D>): RaeVec3<D, Degrees> {
export function ecf2rae<D extends number>(lla: LlaVec3<Radians, D>, ecf: EcfVec3<D>): RaeVec3<D, Degrees> {
const sezCoords = lla2sez(lla, ecf);
const rae = sez2rae(sezCoords);

return {
rng: rae.rng,
az: (rae.az * RAD2DEG) as Degrees,
el: (rae.el * RAD2DEG) as Degrees,
return { rng: rae.rng, az: (rae.az * RAD2DEG) as Degrees, el: (rae.el * RAD2DEG) as Degrees };
}

/**
* Calculates the Greenwich Mean Sidereal Time (GMST) for a given date.
*
* @param date - The date for which to calculate the GMST.
* @returns An object containing the GMST value and the Julian date.
*/
export function calcGmst(date: Date): { gmst: GreenwichMeanSiderealTime; j: number } {
const j =
Utils.jday(
date.getUTCFullYear(),
date.getUTCMonth() + 1,
date.getUTCDate(),
date.getUTCHours(),
date.getUTCMinutes(),
date.getUTCSeconds(),
) +
date.getUTCMilliseconds() * DAY_TO_MS;

const gmst = Sgp4.gstime(j);

return { gmst, j };
}

/**
* Converts ECI coordinates to RAE (Right Ascension, Azimuth, Elevation) coordinates.
* @param {Date} now - Current date and time.
* @param {EciArr3} eci - ECI coordinates of the satellite.
* @param {SensorObject} sensor - Sensor object containing observer's geodetic coordinates.
* @returns {Object} Object containing azimuth, elevation and range in degrees and kilometers respectively.
*/
export function eci2rae(
now: Date,
eci: EciVec3<Kilometers>,
sensor: Sensor,
): { az: Degrees; el: Degrees; rng: Kilometers } {
now = new Date(now);
const { gmst } = calcGmst(now);

const positionEcf = eci2ecf(eci, gmst);
const lla = {
lat: (sensor.lat * DEG2RAD) as Radians,
lon: (sensor.lon * DEG2RAD) as Radians,
alt: sensor.alt,
};

return ecf2rae(lla, positionEcf);
}
4 changes: 2 additions & 2 deletions test/objects/__snapshots__/star.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ exports[`Basic Star functionality should be able to get ECI coordinates 2`] = `5

exports[`Basic Star functionality should be able to get ECI coordinates 3`] = `-2.4943615850552645e-11`;

exports[`Basic Star functionality should be able to get rae coordinates 1`] = `4.71238898038469`;
exports[`Basic Star functionality should be able to get rae coordinates 1`] = `270`;

exports[`Basic Star functionality should be able to get rae coordinates 2`] = `0.9966158375158686`;
exports[`Basic Star functionality should be able to get rae coordinates 2`] = `57.10188128555508`;

exports[`Basic Star functionality should be able to get rae coordinates 3`] = `250000`;
4 changes: 2 additions & 2 deletions test/objects/star.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ describe('Basic Star functionality', () => {
it('should be able to get rae coordinates', () => {
const rae = star.getRae(
{
lat: <Radians>0,
lon: <Radians>0,
lat: <Degrees>0,
lon: <Degrees>0,
alt: <Kilometers>0,
},
new Date(1661400000000),
Expand Down
110 changes: 55 additions & 55 deletions test/sat/__snapshots__/sensor.test.ts.snap
Original file line number Diff line number Diff line change
@@ -1,121 +1,121 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Basic Sensor functionality should be able to get rae coordinates 1`] = `2.629108354091844`;
exports[`Basic Sensor functionality should be able to get rae coordinates 1`] = `2.62910835409574`;

exports[`Basic Sensor functionality should be able to get rae coordinates 2`] = `-0.4265038258082757`;
exports[`Basic Sensor functionality should be able to get rae coordinates 2`] = `-0.42650382580852597`;

exports[`Basic Sensor functionality should be able to get rae coordinates 3`] = `6156.556070063796`;
exports[`Basic Sensor functionality should be able to get rae coordinates 3`] = `6156.5560701071345`;

exports[`Basic Sensor functionality should be able to get rae coordinates 4`] = `2.629108354091844`;
exports[`Basic Sensor functionality should be able to get rae coordinates 4`] = `2.62910835409574`;

exports[`Basic Sensor functionality should be able to get rae coordinates 5`] = `-0.4265038258082757`;
exports[`Basic Sensor functionality should be able to get rae coordinates 5`] = `-0.42650382580852597`;

exports[`Basic Sensor functionality should be able to get rae coordinates 6`] = `6156.556070063796`;
exports[`Basic Sensor functionality should be able to get rae coordinates 6`] = `6156.5560701071345`;

exports[`Basic Sensor functionality should create a lookangles array 1`] = `
Array [
Object {
"az": 180.13876758624156,
"el": 0.015361507052862225,
"rng": 2342.737908604558,
"az": 3.144014604864707,
"el": 0.0002681088678837023,
"rng": 2342.737908649094,
"time": 2022-08-25T07:15:53.000Z,
"type": 0,
},
Object {
"az": 75.7980806492444,
"el": -0.028830957334440976,
"maxElPass": 0.17148507081196085,
"rng": 2358.7204661051765,
"az": 1.3229260740398223,
"el": -0.0005031951401863713,
"maxElPass": 0.17148507079617165,
"rng": 2358.7204660942584,
"time": 2022-08-25T07:24:24.000Z,
"type": 2,
},
Object {
"az": 232.18906583186794,
"el": 0.009600433988362477,
"rng": 2347.461425625144,
"az": 4.052463685880971,
"el": 0.0001675591744800231,
"rng": 2347.461425652447,
"time": 2022-08-25T08:50:55.000Z,
"type": 0,
},
Object {
"az": 54.52261565864341,
"el": -0.02413294135461665,
"maxElPass": 1.5418848225221131,
"rng": 2359.154162131899,
"az": 0.9515991600581195,
"el": -0.00042119929302788286,
"maxElPass": 1.5418848224515804,
"rng": 2359.154162106056,
"time": 2022-08-25T09:01:48.000Z,
"type": 2,
},
Object {
"az": 273.62009396619993,
"el": 0.04473721840290453,
"rng": 2349.43400753881,
"az": 4.775571539307538,
"el": 0.0007808117510869499,
"rng": 2349.4340075359833,
"time": 2022-08-25T10:28:25.000Z,
"type": 0,
},
Object {
"az": 49.638932677761765,
"el": -0.030434434506850978,
"maxElPass": 0.3482094176129491,
"rng": 2358.137482792154,
"az": 0.8663628124171412,
"el": -0.0005311810963317111,
"maxElPass": 0.34820941760929697,
"rng": 2358.137482763319,
"time": 2022-08-25T10:38:29.000Z,
"type": 2,
},
Object {
"az": 302.060157955515,
"el": 0.021825330760619138,
"rng": 2354.1913017184143,
"az": 5.2719442954018465,
"el": 0.00038092387390169485,
"rng": 2354.1913016947638,
"time": 2022-08-25T12:06:27.000Z,
"type": 0,
},
Object {
"az": 62.062147356797546,
"el": -0.047720598190494616,
"maxElPass": 0.23309471413013108,
"rng": 2355.3145751792804,
"az": 1.0831888122507203,
"el": -0.0008328815676606213,
"maxElPass": 0.2330947141235898,
"rng": 2355.3145751584284,
"time": 2022-08-25T12:15:50.000Z,
"type": 2,
},
Object {
"az": 310.644650630328,
"el": 0.034319691788985335,
"rng": 2351.3514012828773,
"az": 5.421771957192329,
"el": 0.0005989916117731009,
"rng": 2351.3514012538535,
"time": 2022-08-25T13:43:37.000Z,
"type": 0,
},
Object {
"az": 93.78468715091233,
"el": -0.05092447343831976,
"maxElPass": 0.41989657303646716,
"rng": 2346.7733683863107,
"az": 1.6368515787551787,
"el": -0.0008887997395797053,
"maxElPass": 0.41989657303552286,
"rng": 2346.773368389268,
"time": 2022-08-25T13:53:54.000Z,
"type": 2,
},
Object {
"az": 302.82920181425385,
"el": 0.008831974766942259,
"rng": 2350.585020694925,
"az": 5.285366642829193,
"el": 0.00015414703091340442,
"rng": 2350.585020670774,
"time": 2022-08-25T15:20:18.000Z,
"type": 0,
},
Object {
"az": 136.91615645014073,
"el": -0.06079535528704331,
"maxElPass": 0.9909446544534085,
"rng": 2338.0820302051443,
"az": 2.3896377292436397,
"el": -0.0010610791279322895,
"maxElPass": 0.9909446543741702,
"rng": 2338.082030237695,
"time": 2022-08-25T15:31:03.000Z,
"type": 2,
},
Object {
"az": 275.6078287616163,
"el": 0.009865997778276727,
"rng": 2342.5887956584797,
"az": 4.810264056144007,
"el": 0.00017219413697323465,
"rng": 2342.5887956541233,
"time": 2022-08-25T16:58:14.000Z,
"type": 0,
},
Object {
"az": 193.81307114785773,
"el": -0.03284642331569769,
"maxElPass": 0.09468940062113852,
"rng": 2331.5278975783554,
"az": 3.382676224927582,
"el": -0.0005732782426437735,
"maxElPass": 0.09468940060916482,
"rng": 2331.5278976216196,
"time": 2022-08-25T17:05:13.000Z,
"type": 2,
},
Expand Down
Loading

0 comments on commit 6103597

Please sign in to comment.