Skip to content

Commit

Permalink
feat: ✨ add caching for most common transforms
Browse files Browse the repository at this point in the history
  • Loading branch information
thkruz committed Jan 13, 2024
1 parent 705d0da commit 5b7cc17
Show file tree
Hide file tree
Showing 12 changed files with 138 additions and 73 deletions.
9 changes: 9 additions & 0 deletions examples/commonjs/satellite-js-migration.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,15 @@ const elevationDegrees = lookAngles.elevationDegrees; // Degrees
const rangeSat = lookAngles.range; // Kilometers
const rangeRate = lookAngles.rangeRate; // Kilometers/Second

// There is a built in cache to allow fast retrieval of repeated calculations.
// This means you can make repeat calls to `.rae()` for minimal performance hit.
const rangeCache = satellite.rae(observer, exampleDate).range;
const azimuthCached = satellite.rae(observer, exampleDate).azimuth;
const elevationCached = satellite.rae(observer, exampleDate).elevation;
const latitudeCached = satellite.lla(exampleDate).lat;
const longitudeCached = satellite.lla(exampleDate).lon;
const heightCached = satellite.lla(exampleDate).alt;

// Geodetic coords are accessed via `longitude`, `latitude`, `height`.
const longitude = positionGd.lon; // longitude is in degrees
const latitude = positionGd.lat; // latitude is in degrees
Expand Down
9 changes: 9 additions & 0 deletions examples/es6/satellite-js-migration.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,15 @@ const elevationDegrees = lookAngles.elevationDegrees; // Degrees
const rangeSat = lookAngles.range; // Kilometers
const rangeRate = lookAngles.rangeRate; // Kilometers/Second

// There is a built in cache to allow fast retrieval of repeated calculations.
// This means you can make repeat calls to `.rae()` for minimal performance hit.
const rangeCache = satellite.rae(observer, exampleDate).range;
const azimuthCached = satellite.rae(observer, exampleDate).azimuth;
const elevationCached = satellite.rae(observer, exampleDate).elevation;
const latitudeCached = satellite.lla(exampleDate).lat;
const longitudeCached = satellite.lla(exampleDate).lon;
const heightCached = satellite.lla(exampleDate).alt;

// Geodetic coords are accessed via `longitude`, `latitude`, `height`.
const longitude = positionGd.lon; // longitude is in degrees
const latitude = positionGd.lat; // latitude is in degrees
Expand Down
11 changes: 11 additions & 0 deletions examples/typescript/satellite-js-migration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,17 @@ const elevationDegrees = lookAngles.elevationDegrees; // Typed as Degrees
const rangeSat = lookAngles.range; // Typed as Kilometers
const rangeRate = lookAngles.rangeRate; // Kilometers/Second

/*
* There is a built in cache to allow fast retrieval of repeated calculations.
* This means you can make repeat calls to `.rae()` for minimal performance hit.
*/
const rangeCache = satellite.rae(observer, exampleDate).range;
const azimuthCached = satellite.rae(observer, exampleDate).azimuth;
const elevationCached = satellite.rae(observer, exampleDate).elevation;
const latitudeCached = satellite.lla(exampleDate).lat;
const longitudeCached = satellite.lla(exampleDate).lon;
const heightCached = satellite.lla(exampleDate).alt;

// Geodetic coords are accessed via `longitude`, `latitude`, `height`.
const longitude = positionGd.lon; // Longitude is in Degrees
const latitude = positionGd.lat; // Latitude is in Degrees
Expand Down
4 changes: 0 additions & 4 deletions src/interfaces/SatelliteParams.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { EciVec3, SpaceObjectType, TleLine1, TleLine2 } from '../types/types';

/**
* TODO: Reduce unnecessary calls to calculateTimeVariables using optional
* parameters and caching.
*/
/**
* Information about a space object.
*/
Expand Down
3 changes: 0 additions & 3 deletions src/objects/BaseObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ export class BaseObject {
position: EciVec3; // Where is the object
totalVelocity: number; // How fast is the object moving
velocity: EciVec3; // How fast is the object moving
time: Date; // When is the object
active = true; // Is the object active

constructor(info: BaseObjectParams) {
Expand All @@ -57,8 +56,6 @@ export class BaseObject {
z: <Kilometers>0,
}; // Default to 0 velocity until velocity is calculated
this.totalVelocity = Math.sqrt(this.velocity.x ** 2 + this.velocity.y ** 2 + this.velocity.z ** 2);

this.time = info.time ?? new Date();
}

/**
Expand Down
10 changes: 2 additions & 8 deletions src/objects/GroundPosition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export class GroundPosition extends BaseObject {
return false;
}

rae(sat: Satellite, date: Date = this.time): RaeVec3<Kilometers, Degrees> {
rae(sat: Satellite, date: Date = new Date()): RaeVec3<Kilometers, Degrees> {
return sat.raeOpt(this, date);
}

Expand All @@ -38,18 +38,12 @@ export class GroundPosition extends BaseObject {
return llaRad2ecf(this.llaRad());
}

eci(date: Date = this.time): EciVec3<Kilometers> {
eci(date: Date = new Date()): EciVec3<Kilometers> {
const { gmst } = calcGmst(date);

return lla2eci(this.llaRad(), gmst);
}

setTime(date: Date): this {
this.time = date;

return this;
}

llaRad(): LlaVec3<Radians, Kilometers> {
return {
lat: (this.lat * DEG2RAD) as Radians,
Expand Down
46 changes: 14 additions & 32 deletions src/objects/Satellite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,6 @@ import { dopplerFactor } from './../utils/functions';
import { BaseObject } from './BaseObject';
import { GroundPosition } from './GroundPosition';

/**
* TODO: #2 Reduce unnecessary calls to calculateTimeVariables using optional
* parameters and caching.
*/

/**
* Represents a satellite object with orbital information and methods for calculating its position and other properties.
*/
Expand Down Expand Up @@ -182,7 +177,7 @@ export class Satellite extends BaseObject {
*
* @optimized
*/
az(observer: GroundPosition, date: Date = this.time): Degrees {
az(observer: GroundPosition, date: Date = new Date()): Degrees {
return (this.raeOpt(observer, date).az * RAD2DEG) as Degrees;
}

Expand All @@ -192,7 +187,7 @@ export class Satellite extends BaseObject {
*
* @expanded
*/
rae(observer: GroundPosition, date: Date = this.time): RAE {
rae(observer: GroundPosition, date: Date = new Date()): RAE {
const rae = this.raeOpt(observer, date);
const rae2 = this.raeOpt(observer, new Date(date.getTime() + 1000));
const epoch = new EpochUTC(date.getTime());
Expand All @@ -216,7 +211,7 @@ export class Satellite extends BaseObject {
*
* @optimized
*/
ecf(date: Date = this.time): EcfVec3<Kilometers> {
ecf(date: Date = new Date()): EcfVec3<Kilometers> {
const { gmst } = Satellite.calculateTimeVariables(date);

return eci2ecf(this.eci(date).position, gmst);
Expand All @@ -227,7 +222,7 @@ export class Satellite extends BaseObject {
*
* @optimized
*/
eci(date: Date = this.time): PosVel<Kilometers> {
eci(date: Date = new Date()): PosVel<Kilometers> {
const { m } = Satellite.calculateTimeVariables(date, this.satrec);

if (!m) {
Expand All @@ -249,7 +244,7 @@ export class Satellite extends BaseObject {
* @returns The J2000 coordinates for the specified date.
* @throws Error if propagation fails.
*/
getJ2000(date: Date = this.time): J2000 {
getJ2000(date: Date = new Date()): J2000 {
const { m } = Satellite.calculateTimeVariables(date, this.satrec);

if (!m) {
Expand All @@ -276,29 +271,30 @@ export class Satellite extends BaseObject {
*
* @optimized
*/
el(observer: GroundPosition, date: Date = this.time): Degrees {
el(observer: GroundPosition, date: Date = new Date()): Degrees {
return (this.raeOpt(observer, date).el * RAD2DEG) as Degrees;
}

/**
* Calculates LLA position at a given time.
*/
lla(date: Date = this.time): LlaVec3<Degrees, Kilometers> {
lla(date: Date = new Date()): LlaVec3<Degrees, Kilometers> {
const { gmst } = Satellite.calculateTimeVariables(date, this.satrec);
const pos = this.eci(date).position;
const lla = eci2lla(pos, gmst);

return eci2lla(pos, gmst);
return lla;
}

getGeodetic(date: Date = this.time): Geodetic {
getGeodetic(date: Date = new Date()): Geodetic {
return this.getJ2000(date).toITRF().toGeodetic();
}

getITRF(date: Date = this.time): ITRF {
getITRF(date: Date = new Date()): ITRF {
return this.getJ2000(date).toITRF();
}

getRIC(reference: Satellite, date: Date = this.time): RIC {
getRIC(reference: Satellite, date: Date = new Date()): RIC {
return RIC.fromJ2000(this.getJ2000(date), reference.getJ2000(date));
}

Expand All @@ -307,7 +303,7 @@ export class Satellite extends BaseObject {
*
* @optimized
*/
raeOpt(observer: GroundPosition, date: Date = this.time): RaeVec3<Kilometers, Degrees> {
raeOpt(observer: GroundPosition, date: Date = new Date()): RaeVec3<Kilometers, Degrees> {
const { gmst } = Satellite.calculateTimeVariables(date, this.satrec);
const eci = this.eci(date).position;
const ecf = eci2ecf(eci, gmst);
Expand All @@ -320,7 +316,7 @@ export class Satellite extends BaseObject {
*
* @optimized
*/
range(observer: GroundPosition, date: Date = this.time): Kilometers {
range(observer: GroundPosition, date: Date = new Date()): Kilometers {
return this.raeOpt(observer, date).rng;
}

Expand Down Expand Up @@ -350,20 +346,6 @@ export class Satellite extends BaseObject {
return dopplerFactor(observer.eci(date), position.position, position.velocity);
}

/**
* Propagates the satellite position to the given date using the SGP4 model.
*
* This method changes the position and time properties of the satellite object.
*/
propagateTo(date: Date): this {
const pv = this.eci(date);

this.position = pv.position as EciVec3;
this.time = date;

return this;
}

/**
* Calculates the time variables for a given date relative to the TLE epoch.
* @param {Date} date Date to calculate
Expand Down
10 changes: 2 additions & 8 deletions src/objects/Sensor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export class Sensor extends GroundPosition {
return true;
}

calculatePasses(planningInterval: number, sat: Satellite, date: Date = this.time) {
calculatePasses(planningInterval: number, sat: Satellite, date: Date = new Date()) {
let isInViewLast = false;
let maxElThisPass = <Degrees>0;
const msnPlanPasses: Lookangle[] = [];
Expand Down Expand Up @@ -139,16 +139,10 @@ export class Sensor extends GroundPosition {
return true;
}

isSatInFov(sat: Satellite, date: Date = this.time): boolean {
isSatInFov(sat: Satellite, date: Date = new Date()): boolean {
return this.isRaeInFov(this.rae(sat, date));
}

setTime(date: Date): this {
this.time = date;

return this;
}

isDeepSpace(): boolean {
return this.maxRng > 6000;
}
Expand Down
4 changes: 2 additions & 2 deletions src/objects/Star.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export class Star extends BaseObject {
this.vmag = info.vmag;
}

eci(lla: LlaVec3 = { lat: <Degrees>180, lon: <Degrees>0, alt: <Kilometers>0 }, date: Date = this.time): EciVec3 {
eci(lla: LlaVec3 = { lat: <Degrees>180, lon: <Degrees>0, alt: <Kilometers>0 }, date: Date = new Date()): EciVec3 {
const rae = this.rae(lla, date);
const { gmst } = Star.calculateTimeVariables_(date);

Expand All @@ -76,7 +76,7 @@ export class Star extends BaseObject {

rae(
lla: LlaVec3<Degrees, Kilometers> = { lat: <Degrees>180, lon: <Degrees>0, alt: <Kilometers>0 },
date: Date = this.time,
date: Date = new Date(),
): RaeVec3 {
const starPos = Celestial.azEl(date, lla.lat, lla.lon, this.ra, this.dec);

Expand Down
24 changes: 24 additions & 0 deletions src/transforms/TransformCache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export class TransformCache {
private static cache_: Map<string, unknown> = new Map();

static get(key: string): unknown {
const value = this.cache_.get(key);

if (value) {
// eslint-disable-next-line no-console
console.log(`Cache hit for ${key}`);
}

return value;
}
static add(key: string, value: unknown) {
this.cache_.set(key, value);

// Max of 1000 items in the cache
if (this.cache_.size > 1000) {
const firstKey = this.cache_.keys().next().value;

this.cache_.delete(firstKey);
}
}
}
Loading

0 comments on commit 5b7cc17

Please sign in to comment.