@interstellar-tools/equations 0.64.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/categories/helpers/misc.d.ts +18 -0
- package/dist/categories/helpers/misc.d.ts.map +1 -1
- package/dist/categories/helpers/misc.js +24 -0
- package/dist/categories/helpers/misc.js.map +1 -1
- package/dist/categories/manoeuvres/burn-time.d.ts +63 -0
- package/dist/categories/manoeuvres/burn-time.d.ts.map +1 -0
- package/dist/categories/manoeuvres/burn-time.js +87 -0
- package/dist/categories/manoeuvres/burn-time.js.map +1 -0
- package/dist/categories/manoeuvres/gravity-loss.d.ts +48 -0
- package/dist/categories/manoeuvres/gravity-loss.d.ts.map +1 -0
- package/dist/categories/manoeuvres/gravity-loss.js +74 -0
- package/dist/categories/manoeuvres/gravity-loss.js.map +1 -0
- package/dist/categories/manoeuvres/initial-mass-for-delta-v.d.ts +60 -0
- package/dist/categories/manoeuvres/initial-mass-for-delta-v.d.ts.map +1 -0
- package/dist/categories/manoeuvres/initial-mass-for-delta-v.js +79 -0
- package/dist/categories/manoeuvres/initial-mass-for-delta-v.js.map +1 -0
- package/dist/categories/manoeuvres/mass-flow-rate.d.ts +57 -0
- package/dist/categories/manoeuvres/mass-flow-rate.d.ts.map +1 -0
- package/dist/categories/manoeuvres/mass-flow-rate.js +73 -0
- package/dist/categories/manoeuvres/mass-flow-rate.js.map +1 -0
- package/dist/categories/manoeuvres/rocket-thrust.d.ts +48 -0
- package/dist/categories/manoeuvres/rocket-thrust.d.ts.map +1 -0
- package/dist/categories/manoeuvres/rocket-thrust.js +62 -0
- package/dist/categories/manoeuvres/rocket-thrust.js.map +1 -0
- package/dist/categories/manoeuvres/thrust-to-weight.d.ts +57 -0
- package/dist/categories/manoeuvres/thrust-to-weight.d.ts.map +1 -0
- package/dist/categories/manoeuvres/thrust-to-weight.js +73 -0
- package/dist/categories/manoeuvres/thrust-to-weight.js.map +1 -0
- package/dist/categories/orbits/elements-to-state.d.ts +61 -0
- package/dist/categories/orbits/elements-to-state.d.ts.map +1 -0
- package/dist/categories/orbits/elements-to-state.js +107 -0
- package/dist/categories/orbits/elements-to-state.js.map +1 -0
- package/dist/categories/orbits/inclination-from-launch-azimuth.d.ts +64 -0
- package/dist/categories/orbits/inclination-from-launch-azimuth.d.ts.map +1 -0
- package/dist/categories/orbits/inclination-from-launch-azimuth.js +76 -0
- package/dist/categories/orbits/inclination-from-launch-azimuth.js.map +1 -0
- package/dist/categories/orbits/launch-azimuth-for-inclination.d.ts +71 -0
- package/dist/categories/orbits/launch-azimuth-for-inclination.d.ts.map +1 -0
- package/dist/categories/orbits/launch-azimuth-for-inclination.js +87 -0
- package/dist/categories/orbits/launch-azimuth-for-inclination.js.map +1 -0
- package/dist/categories/orbits/rotating-launch-azimuth.d.ts +49 -0
- package/dist/categories/orbits/rotating-launch-azimuth.d.ts.map +1 -0
- package/dist/categories/orbits/rotating-launch-azimuth.js +65 -0
- package/dist/categories/orbits/rotating-launch-azimuth.js.map +1 -0
- package/dist/categories/orbits/state-to-elements.d.ts +82 -0
- package/dist/categories/orbits/state-to-elements.d.ts.map +1 -0
- package/dist/categories/orbits/state-to-elements.js +131 -0
- package/dist/categories/orbits/state-to-elements.js.map +1 -0
- package/dist/categories/orbits/surface-rotation-speed.d.ts +61 -0
- package/dist/categories/orbits/surface-rotation-speed.d.ts.map +1 -0
- package/dist/categories/orbits/surface-rotation-speed.js +74 -0
- package/dist/categories/orbits/surface-rotation-speed.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { norm2pi } from '../helpers/misc.js';
|
|
2
|
+
/**
|
|
3
|
+
* Compute the **inertial launch azimuths** that reach an inclination from a latitude.
|
|
4
|
+
*
|
|
5
|
+
* $$
|
|
6
|
+
* \sin\beta = \frac{\cos i}{\cos\varphi}
|
|
7
|
+
* $$
|
|
8
|
+
*
|
|
9
|
+
* Where:
|
|
10
|
+
* - $ \beta $ is the inertial azimuth, clockwise from north (rad)
|
|
11
|
+
* - $ i $ is the target inclination (rad)
|
|
12
|
+
* - $ \varphi $ is the geocentric launch latitude (rad)
|
|
13
|
+
*
|
|
14
|
+
* Two azimuths reach every reachable inclination: one heading north ($ \beta $) and one heading south ($ \pi - \beta $).
|
|
15
|
+
*
|
|
16
|
+
* **Units**
|
|
17
|
+
* - Inputs: `lat` and `i` in **radians**.
|
|
18
|
+
* - Output: both azimuths in **radians**, in [0, 2π).
|
|
19
|
+
*
|
|
20
|
+
* ::: info Notes
|
|
21
|
+
*
|
|
22
|
+
* - `lat` is the **geocentric** latitude. Published latitudes are usually geodetic, which on Earth differ by up to 0.19°, and the inclination by about as much. Convert first (see [#186](https://github.com/phun-ky/interstellar-tools/issues/186)).
|
|
23
|
+
* - A site can only reach inclinations between $ |\varphi| $ and $ \pi - |\varphi| $ directly. Anything else needs a plane change, or a dogleg during ascent.
|
|
24
|
+
* - The azimuths are inertial. Over the ground, the rocket flies a slightly different heading; see {@link rotatingLaunchAzimuth}.
|
|
25
|
+
* - At $ i = |\varphi| $ the two solutions meet, due east (or due west for retrograde orbits).
|
|
26
|
+
*
|
|
27
|
+
* :::
|
|
28
|
+
*
|
|
29
|
+
* ::: practice To the ISS from Cape Canaveral
|
|
30
|
+
*
|
|
31
|
+
* **44.9°**
|
|
32
|
+
*
|
|
33
|
+
* _Inertial azimuth from Pad 39A, 28.447° N geocentric, to an orbit inclined 51.64°_
|
|
34
|
+
*
|
|
35
|
+
* Over the ground the rocket flies 42.7°, because the pad is already moving east at 409 m/s.
|
|
36
|
+
*
|
|
37
|
+
* ```ts
|
|
38
|
+
* launchAzimuthForInclination(toRad(28.447), toRad(51.64)).northbound; // ≈ 44.9°
|
|
39
|
+
* ```
|
|
40
|
+
*
|
|
41
|
+
* :::
|
|
42
|
+
*
|
|
43
|
+
* @param lat - Geocentric launch latitude $ \varphi $ in **radians** (finite, in (-π/2, π/2)).
|
|
44
|
+
* @param i - Target inclination $ i $ in **radians** (finite, in [0, π]).
|
|
45
|
+
* @returns The northbound and southbound inertial azimuths, in **radians**.
|
|
46
|
+
* @throws {TypeError} If any input is not a finite number.
|
|
47
|
+
* @throws {RangeError} If `lat` is not in (-π/2, π/2), `i` is not in [0, π], or `i` can't be reached from `lat` (`i < |lat|` or `i > π - |lat|`).
|
|
48
|
+
* @group Orbits
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* import type { Radians } from '@interstellar-tools/types';
|
|
53
|
+
*
|
|
54
|
+
* const toRad = (deg: number) => ((deg * Math.PI) / 180) as Radians;
|
|
55
|
+
*
|
|
56
|
+
* // A sun-synchronous orbit (97.8°) from Vandenberg (34.7° N)
|
|
57
|
+
* const { southbound } = launchAzimuthForInclination(toRad(34.7), toRad(97.8));
|
|
58
|
+
* // southbound ≈ 189.5°: south, slightly west
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* @see {@link inclinationFromLaunchAzimuth}
|
|
62
|
+
* @see https://en.wikipedia.org/wiki/Launch_azimuth Launch azimuth
|
|
63
|
+
*/
|
|
64
|
+
export const launchAzimuthForInclination = (lat, i) => {
|
|
65
|
+
for (const [name, v] of [
|
|
66
|
+
['lat', lat],
|
|
67
|
+
['i', i]
|
|
68
|
+
]) {
|
|
69
|
+
if (!Number.isFinite(v))
|
|
70
|
+
throw new TypeError(`${name} must be a finite number. Received: ${v}`);
|
|
71
|
+
}
|
|
72
|
+
if (Math.abs(lat) >= Math.PI / 2)
|
|
73
|
+
throw new RangeError(`lat must be in (-π/2, π/2). Received: ${lat}`);
|
|
74
|
+
if (i < 0 || i > Math.PI)
|
|
75
|
+
throw new RangeError(`i must be in [0, π]. Received: ${i}`);
|
|
76
|
+
const sinBeta = Math.cos(i) / Math.cos(lat);
|
|
77
|
+
// Allow rounding at the edge, where i = |lat| exactly
|
|
78
|
+
const tolerance = 1e-12;
|
|
79
|
+
if (Math.abs(sinBeta) > 1 + tolerance)
|
|
80
|
+
throw new RangeError(`i can't be reached from lat: it must be in [|lat|, π - |lat|]. Received: i=${i}, lat=${lat}`);
|
|
81
|
+
const beta = Math.asin(Math.min(1, Math.max(-1, sinBeta)));
|
|
82
|
+
return {
|
|
83
|
+
northbound: norm2pi(beta),
|
|
84
|
+
southbound: norm2pi(Math.PI - beta)
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
//# sourceMappingURL=launch-azimuth-for-inclination.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launch-azimuth-for-inclination.js","sourceRoot":"","sources":["../../../src/categories/orbits/launch-azimuth-for-inclination.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAS7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,CACzC,GAAY,EACZ,CAAU,EACe,EAAE;IAC3B,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI;QACtB,CAAC,KAAK,EAAE,GAAG,CAAC;QACZ,CAAC,GAAG,EAAE,CAAC,CAAC;KACA,EAAE,CAAC;QACX,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;YACrB,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,uCAAuC,CAAC,EAAE,CAAC,CAAC;IAC3E,CAAC;IAED,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,EAAE,GAAG,CAAC;QAC9B,MAAM,IAAI,UAAU,CAAC,yCAAyC,GAAG,EAAE,CAAC,CAAC;IAEvE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE;QACtB,MAAM,IAAI,UAAU,CAAC,kCAAkC,CAAC,EAAE,CAAC,CAAC;IAE9D,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC5C,sDAAsD;IACtD,MAAM,SAAS,GAAG,KAAK,CAAC;IAExB,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,SAAS;QACnC,MAAM,IAAI,UAAU,CAClB,8EAA8E,CAAC,SAAS,GAAG,EAAE,CAC9F,CAAC;IAEJ,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAE3D,OAAO;QACL,UAAU,EAAE,OAAO,CAAC,IAAI,CAAY;QACpC,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAY;KAC/C,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Radians } from '@interstellar-tools/types';
|
|
2
|
+
/**
|
|
3
|
+
* Compute the **azimuth over the ground** for an inertial launch azimuth, on a rotating body.
|
|
4
|
+
*
|
|
5
|
+
* $$
|
|
6
|
+
* \tan\beta_\text{rot} = \frac{v \sin\beta - v_\text{rot}}{v \cos\beta}
|
|
7
|
+
* $$
|
|
8
|
+
*
|
|
9
|
+
* Where:
|
|
10
|
+
* - $ \beta $ is the inertial azimuth, clockwise from north (rad)
|
|
11
|
+
* - $ v $ is the inertial speed to reach, e.g. the orbital speed at insertion (m/s)
|
|
12
|
+
* - $ v_\text{rot} $ is the pad's eastward speed from the body's rotation (m/s)
|
|
13
|
+
*
|
|
14
|
+
* **Units**
|
|
15
|
+
* - Inputs: `azimuth` in **radians**, `v` and `vRot` in **m/s**.
|
|
16
|
+
* - Output: $ \beta_\text{rot} $ in **radians**, in [0, 2π).
|
|
17
|
+
*
|
|
18
|
+
* ::: info Notes
|
|
19
|
+
*
|
|
20
|
+
* - The pad is already moving east, so the rocket only has to add the difference: it steers a little further from east than the inertial azimuth.
|
|
21
|
+
* - Get $ v_\text{rot} $ from {@link surfaceRotationSpeed} and $ \beta $ from {@link launchAzimuthForInclination}.
|
|
22
|
+
* - Uses a flat, local approximation: good for the azimuth at launch, not for the whole ascent.
|
|
23
|
+
*
|
|
24
|
+
* :::
|
|
25
|
+
*
|
|
26
|
+
* @param azimuth - Inertial azimuth $ \beta $ in **radians**, clockwise from north (finite).
|
|
27
|
+
* @param v - Inertial speed $ v $ in **m/s** (finite, > 0).
|
|
28
|
+
* @param vRot - Eastward surface speed $ v_\text{rot} $ in **m/s** (finite).
|
|
29
|
+
* @returns Azimuth over the ground $ \beta_\text{rot} $ in **radians**, in [0, 2π).
|
|
30
|
+
* @throws {TypeError} If any input is not a finite number.
|
|
31
|
+
* @throws {RangeError} If `v <= 0`, or the speed over the ground is zero (the target velocity equals the pad's).
|
|
32
|
+
* @group Orbits
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* import type { Radians } from '@interstellar-tools/types';
|
|
37
|
+
*
|
|
38
|
+
* const toRad = (deg: number) => ((deg * Math.PI) / 180) as Radians;
|
|
39
|
+
*
|
|
40
|
+
* // Due north inertially at 7.8 km/s, from a pad moving east at 409 m/s
|
|
41
|
+
* const beta = rotatingLaunchAzimuth(toRad(0), 7800, 409);
|
|
42
|
+
* // beta ≈ 357.0°: aim slightly west of north to cancel the pad's eastward speed
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* @see {@link launchAzimuthForInclination}
|
|
46
|
+
* @see {@link surfaceRotationSpeed}
|
|
47
|
+
*/
|
|
48
|
+
export declare const rotatingLaunchAzimuth: (azimuth: Radians, v: number, vRot: number) => Radians;
|
|
49
|
+
//# sourceMappingURL=rotating-launch-azimuth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rotating-launch-azimuth.d.ts","sourceRoot":"","sources":["../../../src/categories/orbits/rotating-launch-azimuth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAIzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,eAAO,MAAM,qBAAqB,GAChC,SAAS,OAAO,EAChB,GAAG,MAAM,EACT,MAAM,MAAM,KACX,OAqBF,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { norm2pi } from '../helpers/misc.js';
|
|
2
|
+
/**
|
|
3
|
+
* Compute the **azimuth over the ground** for an inertial launch azimuth, on a rotating body.
|
|
4
|
+
*
|
|
5
|
+
* $$
|
|
6
|
+
* \tan\beta_\text{rot} = \frac{v \sin\beta - v_\text{rot}}{v \cos\beta}
|
|
7
|
+
* $$
|
|
8
|
+
*
|
|
9
|
+
* Where:
|
|
10
|
+
* - $ \beta $ is the inertial azimuth, clockwise from north (rad)
|
|
11
|
+
* - $ v $ is the inertial speed to reach, e.g. the orbital speed at insertion (m/s)
|
|
12
|
+
* - $ v_\text{rot} $ is the pad's eastward speed from the body's rotation (m/s)
|
|
13
|
+
*
|
|
14
|
+
* **Units**
|
|
15
|
+
* - Inputs: `azimuth` in **radians**, `v` and `vRot` in **m/s**.
|
|
16
|
+
* - Output: $ \beta_\text{rot} $ in **radians**, in [0, 2π).
|
|
17
|
+
*
|
|
18
|
+
* ::: info Notes
|
|
19
|
+
*
|
|
20
|
+
* - The pad is already moving east, so the rocket only has to add the difference: it steers a little further from east than the inertial azimuth.
|
|
21
|
+
* - Get $ v_\text{rot} $ from {@link surfaceRotationSpeed} and $ \beta $ from {@link launchAzimuthForInclination}.
|
|
22
|
+
* - Uses a flat, local approximation: good for the azimuth at launch, not for the whole ascent.
|
|
23
|
+
*
|
|
24
|
+
* :::
|
|
25
|
+
*
|
|
26
|
+
* @param azimuth - Inertial azimuth $ \beta $ in **radians**, clockwise from north (finite).
|
|
27
|
+
* @param v - Inertial speed $ v $ in **m/s** (finite, > 0).
|
|
28
|
+
* @param vRot - Eastward surface speed $ v_\text{rot} $ in **m/s** (finite).
|
|
29
|
+
* @returns Azimuth over the ground $ \beta_\text{rot} $ in **radians**, in [0, 2π).
|
|
30
|
+
* @throws {TypeError} If any input is not a finite number.
|
|
31
|
+
* @throws {RangeError} If `v <= 0`, or the speed over the ground is zero (the target velocity equals the pad's).
|
|
32
|
+
* @group Orbits
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* import type { Radians } from '@interstellar-tools/types';
|
|
37
|
+
*
|
|
38
|
+
* const toRad = (deg: number) => ((deg * Math.PI) / 180) as Radians;
|
|
39
|
+
*
|
|
40
|
+
* // Due north inertially at 7.8 km/s, from a pad moving east at 409 m/s
|
|
41
|
+
* const beta = rotatingLaunchAzimuth(toRad(0), 7800, 409);
|
|
42
|
+
* // beta ≈ 357.0°: aim slightly west of north to cancel the pad's eastward speed
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* @see {@link launchAzimuthForInclination}
|
|
46
|
+
* @see {@link surfaceRotationSpeed}
|
|
47
|
+
*/
|
|
48
|
+
export const rotatingLaunchAzimuth = (azimuth, v, vRot) => {
|
|
49
|
+
for (const [name, x] of [
|
|
50
|
+
['azimuth', azimuth],
|
|
51
|
+
['v', v],
|
|
52
|
+
['vRot', vRot]
|
|
53
|
+
]) {
|
|
54
|
+
if (!Number.isFinite(x))
|
|
55
|
+
throw new TypeError(`${name} must be a finite number. Received: ${x}`);
|
|
56
|
+
}
|
|
57
|
+
if (v <= 0)
|
|
58
|
+
throw new RangeError(`v must be > 0. Received: ${v}`);
|
|
59
|
+
const east = v * Math.sin(azimuth) - vRot;
|
|
60
|
+
const north = v * Math.cos(azimuth);
|
|
61
|
+
if (Math.hypot(east, north) <= 1e-12 * v)
|
|
62
|
+
throw new RangeError('The speed over the ground is zero, so the azimuth is undefined.');
|
|
63
|
+
return norm2pi(Math.atan2(east, north));
|
|
64
|
+
};
|
|
65
|
+
//# sourceMappingURL=rotating-launch-azimuth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rotating-launch-azimuth.js","sourceRoot":"","sources":["../../../src/categories/orbits/rotating-launch-azimuth.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,OAAgB,EAChB,CAAS,EACT,IAAY,EACH,EAAE;IACX,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI;QACtB,CAAC,SAAS,EAAE,OAAO,CAAC;QACpB,CAAC,GAAG,EAAE,CAAC,CAAC;QACR,CAAC,MAAM,EAAE,IAAI,CAAC;KACN,EAAE,CAAC;QACX,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;YACrB,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,uCAAuC,CAAC,EAAE,CAAC,CAAC;IAC3E,CAAC;IAED,IAAI,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,4BAA4B,CAAC,EAAE,CAAC,CAAC;IAElE,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IAC1C,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAEpC,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC;QACtC,MAAM,IAAI,UAAU,CAClB,iEAAiE,CAClE,CAAC;IAEJ,OAAO,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAY,CAAC;AACrD,CAAC,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { ClassicalElementsInterface, Vector3DTupleType } from '@interstellar-tools/types';
|
|
2
|
+
/**
|
|
3
|
+
* Convert a **state vector** (position and velocity) to the six **classical orbital elements**.
|
|
4
|
+
*
|
|
5
|
+
* $$
|
|
6
|
+
* \mathbf h = \mathbf r \times \mathbf v, \quad
|
|
7
|
+
* \mathbf e = \frac{\mathbf v \times \mathbf h}{\mu} - \frac{\mathbf r}{r}, \quad
|
|
8
|
+
* \mathbf n = \hat{\mathbf k} \times \mathbf h, \quad
|
|
9
|
+
* a = -\frac{\mu}{2\varepsilon}, \quad
|
|
10
|
+
* \varepsilon = \frac{v^2}{2} - \frac{\mu}{r}
|
|
11
|
+
* $$
|
|
12
|
+
*
|
|
13
|
+
* $$
|
|
14
|
+
* i = \arccos\frac{h_z}{h}, \quad
|
|
15
|
+
* \Omega = \operatorname{atan2}(n_y, n_x), \quad
|
|
16
|
+
* \omega = \angle(\mathbf n, \mathbf e), \quad
|
|
17
|
+
* \nu = \angle(\mathbf e, \mathbf r)
|
|
18
|
+
* $$
|
|
19
|
+
*
|
|
20
|
+
* where each angle $ \angle $ is measured in the direction of motion, about $ \mathbf h $.
|
|
21
|
+
*
|
|
22
|
+
* **Units**
|
|
23
|
+
* - Inputs: `r` in **m**, `v` in **m/s**, `mu` in **m³/s²**.
|
|
24
|
+
* - Output: `a` in **m**, `e` dimensionless, angles in **radians**.
|
|
25
|
+
*
|
|
26
|
+
* ::: info Notes
|
|
27
|
+
*
|
|
28
|
+
* - Works for elliptic and hyperbolic orbits. A hyperbolic orbit has a negative `a`, and `nu` in [0, 2π) like the others: the incoming branch is just below 2π.
|
|
29
|
+
* - Some angles are undefined for special orbits. Below `tolerance`, the function uses these conventions, which {@link elementsToState} reverses:
|
|
30
|
+
* - **circular** ($ e \approx 0 $): `argp = 0`, and `nu` is measured from the ascending node (the argument of latitude);
|
|
31
|
+
* - **equatorial** ($ i \approx 0 $ or $ \pi $): `raan = 0`, and `argp` is measured from the x axis (the longitude of periapsis);
|
|
32
|
+
* - **circular and equatorial**: `raan = argp = 0`, and `nu` is measured from the x axis (the true longitude).
|
|
33
|
+
* - The frame is whatever inertial frame `r` and `v` are given in, centred on the body with parameter `mu`; the reference plane is its xy plane.
|
|
34
|
+
*
|
|
35
|
+
* :::
|
|
36
|
+
*
|
|
37
|
+
* ::: practice Apollo 11, leaving for the Moon
|
|
38
|
+
*
|
|
39
|
+
* **e = 0.977**
|
|
40
|
+
*
|
|
41
|
+
* _From the flown state at trans-lunar injection: 6 712.6 km from Earth's centre, 10 834.3 m/s, 7.367° above the horizontal_
|
|
42
|
+
*
|
|
43
|
+
* The AS-506 flight evaluation report gives 0.97696; the inputs here are rounded. An orbit that stretched reaches far beyond the Moon, but the Moon's gravity takes over long before.
|
|
44
|
+
*
|
|
45
|
+
* ```ts
|
|
46
|
+
* const r = 6_712_602; // m
|
|
47
|
+
* const v = 10_834.3; // m/s
|
|
48
|
+
* const gamma = toRad(7.367);
|
|
49
|
+
* stateToElements(
|
|
50
|
+
* [r, 0, 0],
|
|
51
|
+
* [v * Math.sin(gamma), v * Math.cos(gamma), 0],
|
|
52
|
+
* 3.986004418e14
|
|
53
|
+
* ).e; // ≈ 0.97715
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* :::
|
|
57
|
+
*
|
|
58
|
+
* @param r - Position vector in **m** (finite components, not zero).
|
|
59
|
+
* @param v - Velocity vector in **m/s** (finite components).
|
|
60
|
+
* @param mu - Gravitational parameter $ \mu $ in **m³/s²** (finite, > 0).
|
|
61
|
+
* @param tolerance - Below this, `e` counts as circular and $ \sin i $ as equatorial. Defaults to `1e-10`.
|
|
62
|
+
* @returns The classical orbital elements.
|
|
63
|
+
* @throws {TypeError} If any input is not a finite number.
|
|
64
|
+
* @throws {RangeError} If `mu <= 0`, `tolerance < 0`, `r` is zero, or the motion is straight up or down (no angular momentum).
|
|
65
|
+
* @group Orbits
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```ts
|
|
69
|
+
* // Curtis, Orbital Mechanics for Engineering Students, in km and km/s
|
|
70
|
+
* const { a, e, i, raan, argp, nu } = stateToElements(
|
|
71
|
+
* [-6045e3, -3490e3, 2500e3],
|
|
72
|
+
* [-3.457e3, 6.618e3, 2.533e3],
|
|
73
|
+
* 398_600e9
|
|
74
|
+
* );
|
|
75
|
+
* // e ≈ 0.1712, i ≈ 153.2°, raan ≈ 255.3°, argp ≈ 20.07°, nu ≈ 28.45°
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
78
|
+
* @see {@link elementsToState}
|
|
79
|
+
* @see https://en.wikipedia.org/wiki/Orbital_elements Orbital elements
|
|
80
|
+
*/
|
|
81
|
+
export declare const stateToElements: (r: Vector3DTupleType, v: Vector3DTupleType, mu: number, tolerance?: number) => ClassicalElementsInterface;
|
|
82
|
+
//# sourceMappingURL=state-to-elements.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-to-elements.d.ts","sourceRoot":"","sources":["../../../src/categories/orbits/state-to-elements.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,0BAA0B,EAE1B,iBAAiB,EAClB,MAAM,2BAA2B,CAAC;AAInC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8EG;AACH,eAAO,MAAM,eAAe,GAC1B,GAAG,iBAAiB,EACpB,GAAG,iBAAiB,EACpB,IAAI,MAAM,EACV,kBAAiB,KAChB,0BA6DF,CAAC"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { cross, dot, norm, norm2pi, scale, sub } from '../helpers/misc.js';
|
|
2
|
+
/**
|
|
3
|
+
* Convert a **state vector** (position and velocity) to the six **classical orbital elements**.
|
|
4
|
+
*
|
|
5
|
+
* $$
|
|
6
|
+
* \mathbf h = \mathbf r \times \mathbf v, \quad
|
|
7
|
+
* \mathbf e = \frac{\mathbf v \times \mathbf h}{\mu} - \frac{\mathbf r}{r}, \quad
|
|
8
|
+
* \mathbf n = \hat{\mathbf k} \times \mathbf h, \quad
|
|
9
|
+
* a = -\frac{\mu}{2\varepsilon}, \quad
|
|
10
|
+
* \varepsilon = \frac{v^2}{2} - \frac{\mu}{r}
|
|
11
|
+
* $$
|
|
12
|
+
*
|
|
13
|
+
* $$
|
|
14
|
+
* i = \arccos\frac{h_z}{h}, \quad
|
|
15
|
+
* \Omega = \operatorname{atan2}(n_y, n_x), \quad
|
|
16
|
+
* \omega = \angle(\mathbf n, \mathbf e), \quad
|
|
17
|
+
* \nu = \angle(\mathbf e, \mathbf r)
|
|
18
|
+
* $$
|
|
19
|
+
*
|
|
20
|
+
* where each angle $ \angle $ is measured in the direction of motion, about $ \mathbf h $.
|
|
21
|
+
*
|
|
22
|
+
* **Units**
|
|
23
|
+
* - Inputs: `r` in **m**, `v` in **m/s**, `mu` in **m³/s²**.
|
|
24
|
+
* - Output: `a` in **m**, `e` dimensionless, angles in **radians**.
|
|
25
|
+
*
|
|
26
|
+
* ::: info Notes
|
|
27
|
+
*
|
|
28
|
+
* - Works for elliptic and hyperbolic orbits. A hyperbolic orbit has a negative `a`, and `nu` in [0, 2π) like the others: the incoming branch is just below 2π.
|
|
29
|
+
* - Some angles are undefined for special orbits. Below `tolerance`, the function uses these conventions, which {@link elementsToState} reverses:
|
|
30
|
+
* - **circular** ($ e \approx 0 $): `argp = 0`, and `nu` is measured from the ascending node (the argument of latitude);
|
|
31
|
+
* - **equatorial** ($ i \approx 0 $ or $ \pi $): `raan = 0`, and `argp` is measured from the x axis (the longitude of periapsis);
|
|
32
|
+
* - **circular and equatorial**: `raan = argp = 0`, and `nu` is measured from the x axis (the true longitude).
|
|
33
|
+
* - The frame is whatever inertial frame `r` and `v` are given in, centred on the body with parameter `mu`; the reference plane is its xy plane.
|
|
34
|
+
*
|
|
35
|
+
* :::
|
|
36
|
+
*
|
|
37
|
+
* ::: practice Apollo 11, leaving for the Moon
|
|
38
|
+
*
|
|
39
|
+
* **e = 0.977**
|
|
40
|
+
*
|
|
41
|
+
* _From the flown state at trans-lunar injection: 6 712.6 km from Earth's centre, 10 834.3 m/s, 7.367° above the horizontal_
|
|
42
|
+
*
|
|
43
|
+
* The AS-506 flight evaluation report gives 0.97696; the inputs here are rounded. An orbit that stretched reaches far beyond the Moon, but the Moon's gravity takes over long before.
|
|
44
|
+
*
|
|
45
|
+
* ```ts
|
|
46
|
+
* const r = 6_712_602; // m
|
|
47
|
+
* const v = 10_834.3; // m/s
|
|
48
|
+
* const gamma = toRad(7.367);
|
|
49
|
+
* stateToElements(
|
|
50
|
+
* [r, 0, 0],
|
|
51
|
+
* [v * Math.sin(gamma), v * Math.cos(gamma), 0],
|
|
52
|
+
* 3.986004418e14
|
|
53
|
+
* ).e; // ≈ 0.97715
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* :::
|
|
57
|
+
*
|
|
58
|
+
* @param r - Position vector in **m** (finite components, not zero).
|
|
59
|
+
* @param v - Velocity vector in **m/s** (finite components).
|
|
60
|
+
* @param mu - Gravitational parameter $ \mu $ in **m³/s²** (finite, > 0).
|
|
61
|
+
* @param tolerance - Below this, `e` counts as circular and $ \sin i $ as equatorial. Defaults to `1e-10`.
|
|
62
|
+
* @returns The classical orbital elements.
|
|
63
|
+
* @throws {TypeError} If any input is not a finite number.
|
|
64
|
+
* @throws {RangeError} If `mu <= 0`, `tolerance < 0`, `r` is zero, or the motion is straight up or down (no angular momentum).
|
|
65
|
+
* @group Orbits
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```ts
|
|
69
|
+
* // Curtis, Orbital Mechanics for Engineering Students, in km and km/s
|
|
70
|
+
* const { a, e, i, raan, argp, nu } = stateToElements(
|
|
71
|
+
* [-6045e3, -3490e3, 2500e3],
|
|
72
|
+
* [-3.457e3, 6.618e3, 2.533e3],
|
|
73
|
+
* 398_600e9
|
|
74
|
+
* );
|
|
75
|
+
* // e ≈ 0.1712, i ≈ 153.2°, raan ≈ 255.3°, argp ≈ 20.07°, nu ≈ 28.45°
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
78
|
+
* @see {@link elementsToState}
|
|
79
|
+
* @see https://en.wikipedia.org/wiki/Orbital_elements Orbital elements
|
|
80
|
+
*/
|
|
81
|
+
export const stateToElements = (r, v, mu, tolerance = 1e-10) => {
|
|
82
|
+
for (const [name, vector] of [
|
|
83
|
+
['r', r],
|
|
84
|
+
['v', v]
|
|
85
|
+
]) {
|
|
86
|
+
for (const x of vector)
|
|
87
|
+
if (!Number.isFinite(x))
|
|
88
|
+
throw new TypeError(`${name} must have finite components. Received: ${x}`);
|
|
89
|
+
}
|
|
90
|
+
for (const [name, x] of [
|
|
91
|
+
['mu', mu],
|
|
92
|
+
['tolerance', tolerance]
|
|
93
|
+
]) {
|
|
94
|
+
if (!Number.isFinite(x))
|
|
95
|
+
throw new TypeError(`${name} must be a finite number. Received: ${x}`);
|
|
96
|
+
}
|
|
97
|
+
if (mu <= 0)
|
|
98
|
+
throw new RangeError(`mu must be > 0. Received: ${mu}`);
|
|
99
|
+
if (tolerance < 0)
|
|
100
|
+
throw new RangeError(`tolerance must be >= 0. Received: ${tolerance}`);
|
|
101
|
+
const rn = norm(r);
|
|
102
|
+
const vn = norm(v);
|
|
103
|
+
if (rn === 0)
|
|
104
|
+
throw new RangeError('r must not be the zero vector.');
|
|
105
|
+
const h = cross(r, v);
|
|
106
|
+
const hn = norm(h);
|
|
107
|
+
if (hn <= 1e-12 * rn * vn || hn === 0)
|
|
108
|
+
throw new RangeError('The motion is straight up or down (no angular momentum), so the orbit has no plane.');
|
|
109
|
+
const hHat = scale(h, 1 / hn);
|
|
110
|
+
const eVec = sub(scale(cross(v, h), 1 / mu), scale(r, 1 / rn));
|
|
111
|
+
const e = norm(eVec);
|
|
112
|
+
const energy = (vn * vn) / 2 - mu / rn;
|
|
113
|
+
const a = -mu / (2 * energy);
|
|
114
|
+
const i = Math.acos(Math.min(1, Math.max(-1, h[2] / hn)));
|
|
115
|
+
// The ascending node points along k × h
|
|
116
|
+
const node = [-h[1], h[0], 0];
|
|
117
|
+
const equatorial = Math.hypot(h[0], h[1]) <= tolerance * hn;
|
|
118
|
+
const circular = e <= tolerance;
|
|
119
|
+
// The angle from u to w, measured in the direction of motion
|
|
120
|
+
const angle = (u, w) => norm2pi(Math.atan2(dot(cross(u, w), hHat), dot(u, w)));
|
|
121
|
+
const reference = equatorial ? [1, 0, 0] : node;
|
|
122
|
+
return {
|
|
123
|
+
a,
|
|
124
|
+
e,
|
|
125
|
+
i: i,
|
|
126
|
+
raan: (equatorial ? 0 : norm2pi(Math.atan2(node[1], node[0]))),
|
|
127
|
+
argp: (circular ? 0 : angle(reference, eVec)),
|
|
128
|
+
nu: (circular ? angle(reference, r) : angle(eVec, r))
|
|
129
|
+
};
|
|
130
|
+
};
|
|
131
|
+
//# sourceMappingURL=state-to-elements.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-to-elements.js","sourceRoot":"","sources":["../../../src/categories/orbits/state-to-elements.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { Radians } from '@interstellar-tools/types';
|
|
2
|
+
/**
|
|
3
|
+
* Compute the **eastward speed** of a point on a rotating body's surface, at a latitude.
|
|
4
|
+
*
|
|
5
|
+
* $$
|
|
6
|
+
* v_\text{rot} = \omega\, R \cos\varphi
|
|
7
|
+
* $$
|
|
8
|
+
*
|
|
9
|
+
* Where:
|
|
10
|
+
* - $ \omega $ is the body's rotation rate (rad/s), sidereal, not solar
|
|
11
|
+
* - $ R $ is the point's distance from the body's centre (m)
|
|
12
|
+
* - $ \varphi $ is the geocentric latitude (rad)
|
|
13
|
+
*
|
|
14
|
+
* **Units**
|
|
15
|
+
* - Inputs: `lat` in **radians**, `R` in **m**, `omega` in **rad/s**.
|
|
16
|
+
* - Output: $ v_\text{rot} $ in **m/s**, positive eastward.
|
|
17
|
+
*
|
|
18
|
+
* ::: info Notes
|
|
19
|
+
*
|
|
20
|
+
* - A rocket launched eastward gets this speed for free; one launched westward has to cancel it first.
|
|
21
|
+
* - Earth's sidereal rotation rate is about 7.2921150 × 10⁻⁵ rad/s.
|
|
22
|
+
* - A body that rotates backwards (Venus, Uranus) has a negative `omega`, and the result is negative: westward.
|
|
23
|
+
* - $ R\cos\varphi $ is the distance from the rotation axis. On an oblate body, pass the geocentric latitude and the point's distance from the body's centre, not the equatorial radius with a geodetic latitude (see [#186](https://github.com/phun-ky/interstellar-tools/issues/186)).
|
|
24
|
+
*
|
|
25
|
+
* :::
|
|
26
|
+
*
|
|
27
|
+
* ::: practice Apollo 11, on Pad 39A
|
|
28
|
+
*
|
|
29
|
+
* **408.6 m/s**
|
|
30
|
+
*
|
|
31
|
+
* _At 28.447° N geocentric, 6 373.3 km from Earth's centre, before the engines light_
|
|
32
|
+
*
|
|
33
|
+
* At the equator it's 465.1 m/s, which is one reason Europe launches from Kourou, at 5.2° N (463 m/s).
|
|
34
|
+
*
|
|
35
|
+
* ```ts
|
|
36
|
+
* surfaceRotationSpeed(toRad(28.447), 6_373_266, 7.292115e-5); // ≈ 408.6 m/s
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* :::
|
|
40
|
+
*
|
|
41
|
+
* @param lat - Geocentric latitude $ \varphi $ in **radians** (finite, in [-π/2, π/2]).
|
|
42
|
+
* @param R - Distance $ R $ from the body's centre in **m** (finite, > 0).
|
|
43
|
+
* @param omega - Rotation rate $ \omega $ in **rad/s** (finite).
|
|
44
|
+
* @returns Eastward surface speed $ v_\text{rot} $ in **m/s**.
|
|
45
|
+
* @throws {TypeError} If any input is not a finite number.
|
|
46
|
+
* @throws {RangeError} If `lat` is outside [-π/2, π/2] or `R <= 0`.
|
|
47
|
+
* @group Orbits
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* import type { Radians } from '@interstellar-tools/types';
|
|
52
|
+
*
|
|
53
|
+
* // Earth's equator
|
|
54
|
+
* surfaceRotationSpeed(0 as Radians, 6_378_137, 7.292115e-5); // ≈ 465.1 m/s
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* @see {@link inclinationFromLaunchAzimuth}
|
|
58
|
+
* @see {@link rotatingLaunchAzimuth}
|
|
59
|
+
*/
|
|
60
|
+
export declare const surfaceRotationSpeed: (lat: Radians, R: number, omega: number) => number;
|
|
61
|
+
//# sourceMappingURL=surface-rotation-speed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surface-rotation-speed.d.ts","sourceRoot":"","sources":["../../../src/categories/orbits/surface-rotation-speed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACH,eAAO,MAAM,oBAAoB,GAC/B,KAAK,OAAO,EACZ,GAAG,MAAM,EACT,OAAO,MAAM,KACZ,MAgBF,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compute the **eastward speed** of a point on a rotating body's surface, at a latitude.
|
|
3
|
+
*
|
|
4
|
+
* $$
|
|
5
|
+
* v_\text{rot} = \omega\, R \cos\varphi
|
|
6
|
+
* $$
|
|
7
|
+
*
|
|
8
|
+
* Where:
|
|
9
|
+
* - $ \omega $ is the body's rotation rate (rad/s), sidereal, not solar
|
|
10
|
+
* - $ R $ is the point's distance from the body's centre (m)
|
|
11
|
+
* - $ \varphi $ is the geocentric latitude (rad)
|
|
12
|
+
*
|
|
13
|
+
* **Units**
|
|
14
|
+
* - Inputs: `lat` in **radians**, `R` in **m**, `omega` in **rad/s**.
|
|
15
|
+
* - Output: $ v_\text{rot} $ in **m/s**, positive eastward.
|
|
16
|
+
*
|
|
17
|
+
* ::: info Notes
|
|
18
|
+
*
|
|
19
|
+
* - A rocket launched eastward gets this speed for free; one launched westward has to cancel it first.
|
|
20
|
+
* - Earth's sidereal rotation rate is about 7.2921150 × 10⁻⁵ rad/s.
|
|
21
|
+
* - A body that rotates backwards (Venus, Uranus) has a negative `omega`, and the result is negative: westward.
|
|
22
|
+
* - $ R\cos\varphi $ is the distance from the rotation axis. On an oblate body, pass the geocentric latitude and the point's distance from the body's centre, not the equatorial radius with a geodetic latitude (see [#186](https://github.com/phun-ky/interstellar-tools/issues/186)).
|
|
23
|
+
*
|
|
24
|
+
* :::
|
|
25
|
+
*
|
|
26
|
+
* ::: practice Apollo 11, on Pad 39A
|
|
27
|
+
*
|
|
28
|
+
* **408.6 m/s**
|
|
29
|
+
*
|
|
30
|
+
* _At 28.447° N geocentric, 6 373.3 km from Earth's centre, before the engines light_
|
|
31
|
+
*
|
|
32
|
+
* At the equator it's 465.1 m/s, which is one reason Europe launches from Kourou, at 5.2° N (463 m/s).
|
|
33
|
+
*
|
|
34
|
+
* ```ts
|
|
35
|
+
* surfaceRotationSpeed(toRad(28.447), 6_373_266, 7.292115e-5); // ≈ 408.6 m/s
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* :::
|
|
39
|
+
*
|
|
40
|
+
* @param lat - Geocentric latitude $ \varphi $ in **radians** (finite, in [-π/2, π/2]).
|
|
41
|
+
* @param R - Distance $ R $ from the body's centre in **m** (finite, > 0).
|
|
42
|
+
* @param omega - Rotation rate $ \omega $ in **rad/s** (finite).
|
|
43
|
+
* @returns Eastward surface speed $ v_\text{rot} $ in **m/s**.
|
|
44
|
+
* @throws {TypeError} If any input is not a finite number.
|
|
45
|
+
* @throws {RangeError} If `lat` is outside [-π/2, π/2] or `R <= 0`.
|
|
46
|
+
* @group Orbits
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* import type { Radians } from '@interstellar-tools/types';
|
|
51
|
+
*
|
|
52
|
+
* // Earth's equator
|
|
53
|
+
* surfaceRotationSpeed(0 as Radians, 6_378_137, 7.292115e-5); // ≈ 465.1 m/s
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* @see {@link inclinationFromLaunchAzimuth}
|
|
57
|
+
* @see {@link rotatingLaunchAzimuth}
|
|
58
|
+
*/
|
|
59
|
+
export const surfaceRotationSpeed = (lat, R, omega) => {
|
|
60
|
+
for (const [name, v] of [
|
|
61
|
+
['lat', lat],
|
|
62
|
+
['R', R],
|
|
63
|
+
['omega', omega]
|
|
64
|
+
]) {
|
|
65
|
+
if (!Number.isFinite(v))
|
|
66
|
+
throw new TypeError(`${name} must be a finite number. Received: ${v}`);
|
|
67
|
+
}
|
|
68
|
+
if (Math.abs(lat) > Math.PI / 2)
|
|
69
|
+
throw new RangeError(`lat must be in [-π/2, π/2]. Received: ${lat}`);
|
|
70
|
+
if (R <= 0)
|
|
71
|
+
throw new RangeError(`R must be > 0. Received: ${R}`);
|
|
72
|
+
return omega * R * Math.cos(lat);
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=surface-rotation-speed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surface-rotation-speed.js","sourceRoot":"","sources":["../../../src/categories/orbits/surface-rotation-speed.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,GAAY,EACZ,CAAS,EACT,KAAa,EACL,EAAE;IACV,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI;QACtB,CAAC,KAAK,EAAE,GAAG,CAAC;QACZ,CAAC,GAAG,EAAE,CAAC,CAAC;QACR,CAAC,OAAO,EAAE,KAAK,CAAC;KACR,EAAE,CAAC;QACX,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;YACrB,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,uCAAuC,CAAC,EAAE,CAAC,CAAC;IAC3E,CAAC;IAED,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC;QAC7B,MAAM,IAAI,UAAU,CAAC,yCAAyC,GAAG,EAAE,CAAC,CAAC;IAEvE,IAAI,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,4BAA4B,CAAC,EAAE,CAAC,CAAC;IAElE,OAAO,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACnC,CAAC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -37,24 +37,36 @@ export * from './categories/orbits/atmospheric-drag-acceleration.js';
|
|
|
37
37
|
export * from './categories/orbits/characteristic-energy-c3.js';
|
|
38
38
|
export * from './categories/orbits/circular-speed.js';
|
|
39
39
|
export * from './categories/orbits/cw-hill-derivatives.js';
|
|
40
|
+
export * from './categories/orbits/elements-to-state.js';
|
|
40
41
|
export * from './categories/orbits/escape-speed.js';
|
|
41
42
|
export * from './categories/orbits/flight-path-angle-from-true-anomaly.js';
|
|
42
43
|
export * from './categories/orbits/hyperbolic-periapsis-speed.js';
|
|
44
|
+
export * from './categories/orbits/inclination-from-launch-azimuth.js';
|
|
43
45
|
export * from './categories/orbits/j2-argument-of-perigee-rate.js';
|
|
44
46
|
export * from './categories/orbits/j2-nodal-precession-rate.js';
|
|
45
47
|
export * from './categories/orbits/kepler-period.js';
|
|
48
|
+
export * from './categories/orbits/launch-azimuth-for-inclination.js';
|
|
46
49
|
export * from './categories/orbits/mean-motion.js';
|
|
47
50
|
export * from './categories/orbits/peri-apoapsis-radii.js';
|
|
51
|
+
export * from './categories/orbits/rotating-launch-azimuth.js';
|
|
48
52
|
export * from './categories/orbits/specific-angular-momentum-from-elements.js';
|
|
49
53
|
export * from './categories/orbits/specific-angular-momentum.js';
|
|
50
54
|
export * from './categories/orbits/specific-mechanical-energy.js';
|
|
51
55
|
export * from './categories/orbits/sphere-of-influence-radius.js';
|
|
56
|
+
export * from './categories/orbits/state-to-elements.js';
|
|
57
|
+
export * from './categories/orbits/surface-rotation-speed.js';
|
|
52
58
|
export * from './categories/orbits/vis-viva-speed.js';
|
|
59
|
+
export * from './categories/manoeuvres/burn-time.js';
|
|
53
60
|
export * from './categories/manoeuvres/combine-burns-delta-v.js';
|
|
54
61
|
export * from './categories/manoeuvres/gravity-assist-turning-angle.js';
|
|
62
|
+
export * from './categories/manoeuvres/gravity-loss.js';
|
|
55
63
|
export * from './categories/manoeuvres/hohmann-transfer.js';
|
|
64
|
+
export * from './categories/manoeuvres/initial-mass-for-delta-v.js';
|
|
65
|
+
export * from './categories/manoeuvres/mass-flow-rate.js';
|
|
56
66
|
export * from './categories/manoeuvres/oberth-energy-gain.js';
|
|
57
67
|
export * from './categories/manoeuvres/plane-change-delta-v.js';
|
|
58
68
|
export * from './categories/manoeuvres/rocket-delta-v-from-isp.js';
|
|
59
69
|
export * from './categories/manoeuvres/rocket-delta-v-from-ve.js';
|
|
70
|
+
export * from './categories/manoeuvres/rocket-thrust.js';
|
|
71
|
+
export * from './categories/manoeuvres/thrust-to-weight.js';
|
|
60
72
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,cAAc,qCAAqC,CAAC;AAEpD,cAAc,kCAAkC,CAAC;AAIjD,cAAc,8DAA8D,CAAC;AAE7E,cAAc,kEAAkE,CAAC;AAEjF,cAAc,wDAAwD,CAAC;AAEvE,cAAc,8DAA8D,CAAC;AAE7E,cAAc,qDAAqD,CAAC;AAEpE,cAAc,4DAA4D,CAAC;AAI3E,cAAc,wCAAwC,CAAC;AAEvD,cAAc,+CAA+C,CAAC;AAE9D,cAAc,+BAA+B,CAAC;AAE9C,cAAc,kCAAkC,CAAC;AAEjD,cAAc,8BAA8B,CAAC;AAE7C,cAAc,iDAAiD,CAAC;AAEhE,cAAc,iCAAiC,CAAC;AAEhD,cAAc,+BAA+B,CAAC;AAE9C,cAAc,+BAA+B,CAAC;AAE9C,cAAc,qCAAqC,CAAC;AAIpD,cAAc,gDAAgD,CAAC;AAE/D,cAAc,sCAAsC,CAAC;AAErD,cAAc,qDAAqD,CAAC;AAEpE,cAAc,gDAAgD,CAAC;AAI/D,cAAc,+CAA+C,CAAC;AAE9D,cAAc,uDAAuD,CAAC;AAEtE,cAAc,oDAAoD,CAAC;AAEnE,cAAc,qCAAqC,CAAC;AAIpD,cAAc,8CAA8C,CAAC;AAE7D,cAAc,uCAAuC,CAAC;AAEtD,cAAc,6CAA6C,CAAC;AAE5D,cAAc,iDAAiD,CAAC;AAIhE,cAAc,sDAAsD,CAAC;AAErE,cAAc,iDAAiD,CAAC;AAEhE,cAAc,uCAAuC,CAAC;AAEtD,cAAc,4CAA4C,CAAC;AAE3D,cAAc,qCAAqC,CAAC;AAEpD,cAAc,4DAA4D,CAAC;AAE3E,cAAc,mDAAmD,CAAC;AAElE,cAAc,oDAAoD,CAAC;AAEnE,cAAc,iDAAiD,CAAC;AAEhE,cAAc,sCAAsC,CAAC;AAErD,cAAc,oCAAoC,CAAC;AAEnD,cAAc,4CAA4C,CAAC;AAE3D,cAAc,gEAAgE,CAAC;AAE/E,cAAc,kDAAkD,CAAC;AAEjE,cAAc,mDAAmD,CAAC;AAElE,cAAc,mDAAmD,CAAC;AAElE,cAAc,uCAAuC,CAAC;AAItD,cAAc,kDAAkD,CAAC;AAEjE,cAAc,yDAAyD,CAAC;AAExE,cAAc,6CAA6C,CAAC;AAE5D,cAAc,+CAA+C,CAAC;AAE9D,cAAc,iDAAiD,CAAC;AAEhE,cAAc,oDAAoD,CAAC;AAEnE,cAAc,mDAAmD,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,cAAc,qCAAqC,CAAC;AAEpD,cAAc,kCAAkC,CAAC;AAIjD,cAAc,8DAA8D,CAAC;AAE7E,cAAc,kEAAkE,CAAC;AAEjF,cAAc,wDAAwD,CAAC;AAEvE,cAAc,8DAA8D,CAAC;AAE7E,cAAc,qDAAqD,CAAC;AAEpE,cAAc,4DAA4D,CAAC;AAI3E,cAAc,wCAAwC,CAAC;AAEvD,cAAc,+CAA+C,CAAC;AAE9D,cAAc,+BAA+B,CAAC;AAE9C,cAAc,kCAAkC,CAAC;AAEjD,cAAc,8BAA8B,CAAC;AAE7C,cAAc,iDAAiD,CAAC;AAEhE,cAAc,iCAAiC,CAAC;AAEhD,cAAc,+BAA+B,CAAC;AAE9C,cAAc,+BAA+B,CAAC;AAE9C,cAAc,qCAAqC,CAAC;AAIpD,cAAc,gDAAgD,CAAC;AAE/D,cAAc,sCAAsC,CAAC;AAErD,cAAc,qDAAqD,CAAC;AAEpE,cAAc,gDAAgD,CAAC;AAI/D,cAAc,+CAA+C,CAAC;AAE9D,cAAc,uDAAuD,CAAC;AAEtE,cAAc,oDAAoD,CAAC;AAEnE,cAAc,qCAAqC,CAAC;AAIpD,cAAc,8CAA8C,CAAC;AAE7D,cAAc,uCAAuC,CAAC;AAEtD,cAAc,6CAA6C,CAAC;AAE5D,cAAc,iDAAiD,CAAC;AAIhE,cAAc,sDAAsD,CAAC;AAErE,cAAc,iDAAiD,CAAC;AAEhE,cAAc,uCAAuC,CAAC;AAEtD,cAAc,4CAA4C,CAAC;AAE3D,cAAc,0CAA0C,CAAC;AAEzD,cAAc,qCAAqC,CAAC;AAEpD,cAAc,4DAA4D,CAAC;AAE3E,cAAc,mDAAmD,CAAC;AAElE,cAAc,wDAAwD,CAAC;AAEvE,cAAc,oDAAoD,CAAC;AAEnE,cAAc,iDAAiD,CAAC;AAEhE,cAAc,sCAAsC,CAAC;AAErD,cAAc,uDAAuD,CAAC;AAEtE,cAAc,oCAAoC,CAAC;AAEnD,cAAc,4CAA4C,CAAC;AAE3D,cAAc,gDAAgD,CAAC;AAE/D,cAAc,gEAAgE,CAAC;AAE/E,cAAc,kDAAkD,CAAC;AAEjE,cAAc,mDAAmD,CAAC;AAElE,cAAc,mDAAmD,CAAC;AAElE,cAAc,0CAA0C,CAAC;AAEzD,cAAc,+CAA+C,CAAC;AAE9D,cAAc,uCAAuC,CAAC;AAItD,cAAc,sCAAsC,CAAC;AAErD,cAAc,kDAAkD,CAAC;AAEjE,cAAc,yDAAyD,CAAC;AAExE,cAAc,yCAAyC,CAAC;AAExD,cAAc,6CAA6C,CAAC;AAE5D,cAAc,qDAAqD,CAAC;AAEpE,cAAc,2CAA2C,CAAC;AAE1D,cAAc,+CAA+C,CAAC;AAE9D,cAAc,iDAAiD,CAAC;AAEhE,cAAc,oDAAoD,CAAC;AAEnE,cAAc,mDAAmD,CAAC;AAElE,cAAc,0CAA0C,CAAC;AAEzD,cAAc,6CAA6C,CAAC"}
|