From 4a0ef1ebe261d9fb4a86418170991576267e9285 Mon Sep 17 00:00:00 2001 From: Theodore Kruczek Date: Sun, 14 Jan 2024 08:57:27 -0500 Subject: [PATCH] fix: :bug: fix calculation of doppler factor --- .vscode/tasks.json | 12 ++ package.json | 5 +- src/utils/constants.ts | 5 + src/utils/functions.ts | 32 ++--- test/utils/__snapshots__/utils.test.ts.snap | 5 + test/utils/utils.test.ts | 142 +++++++++++--------- 6 files changed, 118 insertions(+), 83 deletions(-) create mode 100644 test/utils/__snapshots__/utils.test.ts.snap diff --git a/.vscode/tasks.json b/.vscode/tasks.json index e4a4027..b88c7f2 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -13,6 +13,18 @@ "color": "terminal.ansiBlue" } }, + { + "label": "Clean Dist Folder", + "command": "npm run clean", + "type": "shell", + "args": [], + "isBackground": true, + "problemMatcher": [], + "icon": { + "id": "trash", + "color": "terminal.ansiYellow" + } + }, { "label": "Test with Jest", "command": "npm test", diff --git a/package.json b/package.json index 0a0a5d0..6491ce2 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "module": "dist/main.js", "description": "Orbital Object Toolkit. A modern typed replacement for satellite.js including SGP4 propagation, TLE parsing, Sun and Moon calculations, and more.", "scripts": { - "build": "node ./scripts/cleanup.mjs && npx tsc -p tsconfig.build.json -m esnext", + "build": "npm run clean && npx tsc -p tsconfig.build.json -m esnext", + "clean": "node ./scripts/cleanup.mjs", "lint": "npx eslint src", "lint:fix": "npx eslint src --fix", "test": "jest", @@ -50,4 +51,4 @@ "typescript": "^4.9.5" }, "homepage": "https://github.com/thkruz/ootk-core" -} +} \ No newline at end of file diff --git a/src/utils/constants.ts b/src/utils/constants.ts index ea8ca7d..1549d1e 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -47,6 +47,11 @@ export const ttasec2rad = (asec2rad / 10000.0) as Radians; */ export const masec2rad = (asec2rad / 1000.0) as Radians; +/** + * The angular velocity of the Earth in radians per second. + */ +export const angularVelocityOfEarth = 7.292115e-5; + /** * Astronomical unit in kilometers. */ diff --git a/src/utils/functions.ts b/src/utils/functions.ts index bfb6366..35fd84d 100644 --- a/src/utils/functions.ts +++ b/src/utils/functions.ts @@ -2,7 +2,8 @@ /* eslint-disable func-style */ import { AngularDiameterMethod } from '../enums/AngularDiameterMethod'; import { AngularDistanceMethod } from '../enums/AngularDistanceMethod'; -import { DifferentiableFunction, EciVec3, Radians, SpaceObjectType } from '../types/types'; +import { DifferentiableFunction, EcfVec3, Kilometers, Radians, SpaceObjectType } from '../types/types'; +import { angularVelocityOfEarth, cKmPerSec } from './constants'; /** * Calculates the factorial of a given number. @@ -630,33 +631,24 @@ export const spaceObjType2Str = (spaceObjType: SpaceObjectType): string => * @param velocity - The velocity vector of the source. * @returns The calculated Doppler factor. */ -export const dopplerFactor = (location: EciVec3, position: EciVec3, velocity: EciVec3): number => { - const mfactor = 7.292115e-5; - const c = 299792.458; // Speed of light in km/s - - const range = { +export const dopplerFactor = ( + location: EcfVec3, + position: EcfVec3, + velocity: EcfVec3, +): number => { + const range = { x: position.x - location.x, y: position.y - location.y, z: position.z - location.z, }; const distance = Math.sqrt(range.x ** 2 + range.y ** 2 + range.z ** 2); - - const rangeVel = { - x: velocity.x + mfactor * location.y, - y: velocity.y - mfactor * location.x, + const rangeVel = { + x: velocity.x + angularVelocityOfEarth * location.y, + y: velocity.y - angularVelocityOfEarth * location.x, z: velocity.z, }; - const rangeRate = (range.x * rangeVel.x + range.y * rangeVel.y + range.z * rangeVel.z) / distance; - let dopplerFactor = 0; - - if (rangeRate < 0) { - dopplerFactor = 1 + (rangeRate / c) * sign(rangeRate); - } - - if (rangeRate >= 0) { - dopplerFactor = 1 - (rangeRate / c) * sign(rangeRate); - } + const dopplerFactor = 1 - rangeRate / cKmPerSec; return dopplerFactor; }; diff --git a/test/utils/__snapshots__/utils.test.ts.snap b/test/utils/__snapshots__/utils.test.ts.snap new file mode 100644 index 0000000..65b660d --- /dev/null +++ b/test/utils/__snapshots__/utils.test.ts.snap @@ -0,0 +1,5 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Doppler factor calculates earth rotation the same as before #1 1`] = `1.000001479636888`; + +exports[`Doppler factor calculates earth rotation the same as before #2 1`] = `1`; diff --git a/test/utils/utils.test.ts b/test/utils/utils.test.ts index 096d0c3..c1713a0 100644 --- a/test/utils/utils.test.ts +++ b/test/utils/utils.test.ts @@ -1,96 +1,116 @@ -import { EciVec3, Kilometers, linearDistance, Vec3 } from '../../src/main'; +import { EcfVec3, Kilometers, linearDistance, RADIUS_OF_EARTH, Vec3 } from '../../src/main'; import { dopplerFactor, getDayOfYear } from '../../src/utils/functions'; -const numDigits = 8; - -const earthRadius = 6378.137; const sincos45deg = Math.sqrt(2) / 2; describe('Doppler factor', () => { - it('without observer movement', () => { + it('works without observer movement and object moving away', () => { // North Pole - const observerEci = { + const observerEcf = { x: 0, y: 0, - z: earthRadius, - } as EciVec3; - const positionEci = { + z: RADIUS_OF_EARTH, + } as EcfVec3; + const positionEcf = { x: 0, y: 0, - z: earthRadius + 500, - } as EciVec3; - // Escape velocity - const velocityEci = { - x: 7.91, + z: RADIUS_OF_EARTH + 500, + } as EcfVec3; + const velocityEcf = { + x: 0, y: 0, - z: 0, - } as EciVec3; - const dopFactor = dopplerFactor(observerEci, positionEci, velocityEci); + z: 1, + } as EcfVec3; + const dopFactor = dopplerFactor(observerEcf, positionEcf, velocityEcf); - expect(dopFactor).toBeCloseTo(1, numDigits); + expect(dopFactor).toBeLessThan(1); }); - it('movement of observer is not affected', () => { - const observerEci = { - x: earthRadius, + it('works without observer movement and object moving towards', () => { + // North Pole + const observerEcf = { + x: 0, y: 0, - z: 0, - } as EciVec3; - const positionEci = { - x: earthRadius + 500, + z: RADIUS_OF_EARTH, + } as EcfVec3; + const positionEcf = { + x: 0, y: 0, - z: 0, - } as EciVec3; - const velocityEci = { + z: RADIUS_OF_EARTH + 500, + } as EcfVec3; + const velocityEcf = { x: 0, - y: 7.91, - z: 0, - } as EciVec3; - const dopFactor = dopplerFactor(observerEci, positionEci, velocityEci); + y: 0, + z: -1, + } as EcfVec3; + const dopFactor = dopplerFactor(observerEcf, positionEcf, velocityEcf); - expect(dopFactor).toBeCloseTo(1, numDigits); + expect(dopFactor).toBeGreaterThan(1); }); - it('special case', () => { - const observerEci = { - x: earthRadius, + it('calculates earth rotation the same as before #1', () => { + const observerEcf = { + x: RADIUS_OF_EARTH, y: 0, z: 0, - } as EciVec3; - const positionEci = { - x: (earthRadius + 500) * sincos45deg, // z*sin(45) - y: (earthRadius + 500) * sincos45deg, // z*cos(45) + } as EcfVec3; + const positionEcf = { + x: (RADIUS_OF_EARTH + 500) * sincos45deg, // z*sin(45) + y: (RADIUS_OF_EARTH + 500) * sincos45deg, // z*cos(45) z: 0, - } as EciVec3; - const velocityEci = { - x: 7.91 * sincos45deg, - y: 7.91 * sincos45deg, + } as EcfVec3; + const velocityEcf = { + x: 0, + y: 0, z: 0, - } as EciVec3; - const dopFactor = dopplerFactor(observerEci, positionEci, velocityEci); + } as EcfVec3; + const dopFactor = dopplerFactor(observerEcf, positionEcf, velocityEcf); - expect(dopFactor).toBeCloseTo(0.9999892152210788, numDigits); + expect(dopFactor).toMatchSnapshot(); }); - test('if negative range rate works', () => { - const observerEci = { - x: earthRadius, + it('works without observer movement and a stationary object', () => { + // North Pole + const observerEcf = { + x: 0, + y: 0, + z: RADIUS_OF_EARTH, + } as EcfVec3; + const positionEcf = { + x: 0, + y: 0, + z: RADIUS_OF_EARTH + 500, + } as EcfVec3; + const velocityEcf = { + x: 0, y: 0, z: 0, - } as EciVec3; - const positionEci = { - x: (earthRadius + 500) * sincos45deg, // z*sin(45) - y: (earthRadius + 500) * sincos45deg, // z*cos(45) + } as EcfVec3; + const dopFactor = dopplerFactor(observerEcf, positionEcf, velocityEcf); + + expect(dopFactor).toEqual(1); + }); + + it('calculates earth rotation the same as before #2', () => { + // North Pole + const observerEcf = { + x: RADIUS_OF_EARTH, + y: 0, z: 0, - } as EciVec3; - const velocityEci = { - x: -7.91 * sincos45deg, - y: -7.91 * sincos45deg, + } as EcfVec3; + const positionEcf = { + x: RADIUS_OF_EARTH + 500, + y: 0, z: 0, - } as EciVec3; - const dopFactor = dopplerFactor(observerEci, positionEci, velocityEci); + } as EcfVec3; + const velocityEcf = { + x: 0, + y: 0, + z: 1, + } as EcfVec3; + const dopFactor = dopplerFactor(observerEcf, positionEcf, velocityEcf); - expect(dopFactor).toBeCloseTo(1.000013747277977, numDigits); + expect(dopFactor).toMatchSnapshot(); }); });