@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,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compute the **thrust** of a rocket engine from its exhaust, including the pressure term.
|
|
3
|
+
*
|
|
4
|
+
* $$
|
|
5
|
+
* F = \dot m\, v_e + (p_e - p_a)\, A_e
|
|
6
|
+
* $$
|
|
7
|
+
*
|
|
8
|
+
* Where:
|
|
9
|
+
* - $ \dot m $ is the mass flow rate (kg/s)
|
|
10
|
+
* - $ v_e $ is the exhaust velocity at the nozzle exit (m/s)
|
|
11
|
+
* - $ p_e $ is the pressure at the nozzle exit (Pa)
|
|
12
|
+
* - $ p_a $ is the ambient pressure (Pa), 0 in vacuum
|
|
13
|
+
* - $ A_e $ is the nozzle exit area (m²)
|
|
14
|
+
*
|
|
15
|
+
* **Units**
|
|
16
|
+
* - Inputs: `mDot` in **kg/s**, `ve` in **m/s**, `pe` and `pa` in **Pa**, `Ae` in **m²**.
|
|
17
|
+
* - Output: $ F $ in **N**.
|
|
18
|
+
*
|
|
19
|
+
* ::: info Notes
|
|
20
|
+
*
|
|
21
|
+
* - The same engine gives more thrust in vacuum than at sea level: $ p_a $ pushes back on the nozzle exit.
|
|
22
|
+
* - A nozzle with $ p_e < p_a $ is over-expanded, and the pressure term reduces the thrust.
|
|
23
|
+
* - With $ p_e = p_a $ the thrust is $ \dot m\, v_e $, and $ v_e $ equals $ I_{sp}\, g_0 $.
|
|
24
|
+
*
|
|
25
|
+
* :::
|
|
26
|
+
*
|
|
27
|
+
* @param mDot - Mass flow rate $ \dot m $ in **kg/s** (finite, >= 0).
|
|
28
|
+
* @param ve - Exhaust velocity $ v_e $ in **m/s** (finite, >= 0).
|
|
29
|
+
* @param pe - Nozzle exit pressure $ p_e $ in **Pa** (finite, >= 0).
|
|
30
|
+
* @param pa - Ambient pressure $ p_a $ in **Pa** (finite, >= 0).
|
|
31
|
+
* @param Ae - Nozzle exit area $ A_e $ in **m²** (finite, >= 0).
|
|
32
|
+
* @returns Thrust $ F $ in **N**. Can be negative for a badly over-expanded nozzle with little flow.
|
|
33
|
+
* @throws {TypeError} If any input is not a finite number.
|
|
34
|
+
* @throws {RangeError} If any input is negative.
|
|
35
|
+
* @group Manoeuvres
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* // 250 kg/s at 3000 m/s, exit at 70 kPa through a 1.2 m² nozzle
|
|
40
|
+
* const vacuum = rocketThrust(250, 3000, 70_000, 0, 1.2); // 834 000 N
|
|
41
|
+
* const seaLevel = rocketThrust(250, 3000, 70_000, 101_325, 1.2); // ≈ 712 410 N
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* @see {@link massFlowRate}
|
|
45
|
+
* @see https://en.wikipedia.org/wiki/Rocket_engine_nozzle Rocket engine nozzle (thrust equation)
|
|
46
|
+
*/
|
|
47
|
+
export declare const rocketThrust: (mDot: number, ve: number, pe: number, pa: number, Ae: number) => number;
|
|
48
|
+
//# sourceMappingURL=rocket-thrust.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rocket-thrust.d.ts","sourceRoot":"","sources":["../../../src/categories/manoeuvres/rocket-thrust.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,eAAO,MAAM,YAAY,GACvB,MAAM,MAAM,EACZ,IAAI,MAAM,EACV,IAAI,MAAM,EACV,IAAI,MAAM,EACV,IAAI,MAAM,KACT,MAeF,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compute the **thrust** of a rocket engine from its exhaust, including the pressure term.
|
|
3
|
+
*
|
|
4
|
+
* $$
|
|
5
|
+
* F = \dot m\, v_e + (p_e - p_a)\, A_e
|
|
6
|
+
* $$
|
|
7
|
+
*
|
|
8
|
+
* Where:
|
|
9
|
+
* - $ \dot m $ is the mass flow rate (kg/s)
|
|
10
|
+
* - $ v_e $ is the exhaust velocity at the nozzle exit (m/s)
|
|
11
|
+
* - $ p_e $ is the pressure at the nozzle exit (Pa)
|
|
12
|
+
* - $ p_a $ is the ambient pressure (Pa), 0 in vacuum
|
|
13
|
+
* - $ A_e $ is the nozzle exit area (m²)
|
|
14
|
+
*
|
|
15
|
+
* **Units**
|
|
16
|
+
* - Inputs: `mDot` in **kg/s**, `ve` in **m/s**, `pe` and `pa` in **Pa**, `Ae` in **m²**.
|
|
17
|
+
* - Output: $ F $ in **N**.
|
|
18
|
+
*
|
|
19
|
+
* ::: info Notes
|
|
20
|
+
*
|
|
21
|
+
* - The same engine gives more thrust in vacuum than at sea level: $ p_a $ pushes back on the nozzle exit.
|
|
22
|
+
* - A nozzle with $ p_e < p_a $ is over-expanded, and the pressure term reduces the thrust.
|
|
23
|
+
* - With $ p_e = p_a $ the thrust is $ \dot m\, v_e $, and $ v_e $ equals $ I_{sp}\, g_0 $.
|
|
24
|
+
*
|
|
25
|
+
* :::
|
|
26
|
+
*
|
|
27
|
+
* @param mDot - Mass flow rate $ \dot m $ in **kg/s** (finite, >= 0).
|
|
28
|
+
* @param ve - Exhaust velocity $ v_e $ in **m/s** (finite, >= 0).
|
|
29
|
+
* @param pe - Nozzle exit pressure $ p_e $ in **Pa** (finite, >= 0).
|
|
30
|
+
* @param pa - Ambient pressure $ p_a $ in **Pa** (finite, >= 0).
|
|
31
|
+
* @param Ae - Nozzle exit area $ A_e $ in **m²** (finite, >= 0).
|
|
32
|
+
* @returns Thrust $ F $ in **N**. Can be negative for a badly over-expanded nozzle with little flow.
|
|
33
|
+
* @throws {TypeError} If any input is not a finite number.
|
|
34
|
+
* @throws {RangeError} If any input is negative.
|
|
35
|
+
* @group Manoeuvres
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* // 250 kg/s at 3000 m/s, exit at 70 kPa through a 1.2 m² nozzle
|
|
40
|
+
* const vacuum = rocketThrust(250, 3000, 70_000, 0, 1.2); // 834 000 N
|
|
41
|
+
* const seaLevel = rocketThrust(250, 3000, 70_000, 101_325, 1.2); // ≈ 712 410 N
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* @see {@link massFlowRate}
|
|
45
|
+
* @see https://en.wikipedia.org/wiki/Rocket_engine_nozzle Rocket engine nozzle (thrust equation)
|
|
46
|
+
*/
|
|
47
|
+
export const rocketThrust = (mDot, ve, pe, pa, Ae) => {
|
|
48
|
+
for (const [name, v] of [
|
|
49
|
+
['mDot', mDot],
|
|
50
|
+
['ve', ve],
|
|
51
|
+
['pe', pe],
|
|
52
|
+
['pa', pa],
|
|
53
|
+
['Ae', Ae]
|
|
54
|
+
]) {
|
|
55
|
+
if (!Number.isFinite(v))
|
|
56
|
+
throw new TypeError(`${name} must be a finite number. Received: ${v}`);
|
|
57
|
+
if (v < 0)
|
|
58
|
+
throw new RangeError(`${name} must be >= 0. Received: ${v}`);
|
|
59
|
+
}
|
|
60
|
+
return mDot * ve + (pe - pa) * Ae;
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=rocket-thrust.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rocket-thrust.js","sourceRoot":"","sources":["../../../src/categories/manoeuvres/rocket-thrust.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,IAAY,EACZ,EAAU,EACV,EAAU,EACV,EAAU,EACV,EAAU,EACF,EAAE;IACV,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI;QACtB,CAAC,MAAM,EAAE,IAAI,CAAC;QACd,CAAC,IAAI,EAAE,EAAE,CAAC;QACV,CAAC,IAAI,EAAE,EAAE,CAAC;QACV,CAAC,IAAI,EAAE,EAAE,CAAC;QACV,CAAC,IAAI,EAAE,EAAE,CAAC;KACF,EAAE,CAAC;QACX,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;YACrB,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,uCAAuC,CAAC,EAAE,CAAC,CAAC;QAEzE,IAAI,CAAC,GAAG,CAAC;YAAE,MAAM,IAAI,UAAU,CAAC,GAAG,IAAI,4BAA4B,CAAC,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED,OAAO,IAAI,GAAG,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC;AACpC,CAAC,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compute the **thrust-to-weight ratio** of a vehicle in a gravity field.
|
|
3
|
+
*
|
|
4
|
+
* $$
|
|
5
|
+
* \frac{T}{W} = \frac{F}{m\, g}
|
|
6
|
+
* $$
|
|
7
|
+
*
|
|
8
|
+
* Where:
|
|
9
|
+
* - $ F $ is the thrust (N)
|
|
10
|
+
* - $ m $ is the vehicle's mass (kg)
|
|
11
|
+
* - $ g $ is the local gravitational acceleration (m/s²)
|
|
12
|
+
*
|
|
13
|
+
* **Units**
|
|
14
|
+
* - Inputs: `F` in **N**, `m` in **kg**, `g` in **m/s²**.
|
|
15
|
+
* - Output: dimensionless ratio.
|
|
16
|
+
*
|
|
17
|
+
* ::: info Notes
|
|
18
|
+
*
|
|
19
|
+
* - A vehicle can only lift off vertically when $ T/W > 1 $.
|
|
20
|
+
* - Use the local $ g $, e.g. $ \mu / r^2 $ for the body you're on, not standard gravity.
|
|
21
|
+
* - The ratio grows during a burn as propellant is used up; pass the current mass.
|
|
22
|
+
*
|
|
23
|
+
* :::
|
|
24
|
+
*
|
|
25
|
+
* ::: practice Apollo 11's lunar module, leaving the Moon
|
|
26
|
+
*
|
|
27
|
+
* **1.94**
|
|
28
|
+
*
|
|
29
|
+
* _Ascent stage at liftoff, in the Moon's 1.62 m/s² gravity_
|
|
30
|
+
*
|
|
31
|
+
* On Earth the same stage would manage only 0.32: too little to lift off.
|
|
32
|
+
*
|
|
33
|
+
* ```ts
|
|
34
|
+
* thrustToWeight(15_409, 4888, 1.624); // ≈ 1.94
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* :::
|
|
38
|
+
*
|
|
39
|
+
* @param F - Thrust $ F $ in **N** (finite, >= 0).
|
|
40
|
+
* @param m - Mass $ m $ in **kg** (finite, > 0).
|
|
41
|
+
* @param g - Local gravitational acceleration $ g $ in **m/s²** (finite, > 0).
|
|
42
|
+
* @returns Thrust-to-weight ratio (dimensionless).
|
|
43
|
+
* @throws {TypeError} If any input is not a finite number.
|
|
44
|
+
* @throws {RangeError} If `F < 0`, `m <= 0` or `g <= 0`.
|
|
45
|
+
* @group Manoeuvres
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* // A 2000 kg lander with a 45 kN engine on Mars (g ≈ 3.71 m/s²)
|
|
50
|
+
* const tw = thrustToWeight(45_000, 2000, 3.71);
|
|
51
|
+
* // tw ≈ 6.06
|
|
52
|
+
* ```
|
|
53
|
+
*
|
|
54
|
+
* @see {@link massFlowRate}
|
|
55
|
+
*/
|
|
56
|
+
export declare const thrustToWeight: (F: number, m: number, g: number) => number;
|
|
57
|
+
//# sourceMappingURL=thrust-to-weight.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thrust-to-weight.d.ts","sourceRoot":"","sources":["../../../src/categories/manoeuvres/thrust-to-weight.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AACH,eAAO,MAAM,cAAc,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,EAAE,GAAG,MAAM,KAAG,MAiBhE,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compute the **thrust-to-weight ratio** of a vehicle in a gravity field.
|
|
3
|
+
*
|
|
4
|
+
* $$
|
|
5
|
+
* \frac{T}{W} = \frac{F}{m\, g}
|
|
6
|
+
* $$
|
|
7
|
+
*
|
|
8
|
+
* Where:
|
|
9
|
+
* - $ F $ is the thrust (N)
|
|
10
|
+
* - $ m $ is the vehicle's mass (kg)
|
|
11
|
+
* - $ g $ is the local gravitational acceleration (m/s²)
|
|
12
|
+
*
|
|
13
|
+
* **Units**
|
|
14
|
+
* - Inputs: `F` in **N**, `m` in **kg**, `g` in **m/s²**.
|
|
15
|
+
* - Output: dimensionless ratio.
|
|
16
|
+
*
|
|
17
|
+
* ::: info Notes
|
|
18
|
+
*
|
|
19
|
+
* - A vehicle can only lift off vertically when $ T/W > 1 $.
|
|
20
|
+
* - Use the local $ g $, e.g. $ \mu / r^2 $ for the body you're on, not standard gravity.
|
|
21
|
+
* - The ratio grows during a burn as propellant is used up; pass the current mass.
|
|
22
|
+
*
|
|
23
|
+
* :::
|
|
24
|
+
*
|
|
25
|
+
* ::: practice Apollo 11's lunar module, leaving the Moon
|
|
26
|
+
*
|
|
27
|
+
* **1.94**
|
|
28
|
+
*
|
|
29
|
+
* _Ascent stage at liftoff, in the Moon's 1.62 m/s² gravity_
|
|
30
|
+
*
|
|
31
|
+
* On Earth the same stage would manage only 0.32: too little to lift off.
|
|
32
|
+
*
|
|
33
|
+
* ```ts
|
|
34
|
+
* thrustToWeight(15_409, 4888, 1.624); // ≈ 1.94
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* :::
|
|
38
|
+
*
|
|
39
|
+
* @param F - Thrust $ F $ in **N** (finite, >= 0).
|
|
40
|
+
* @param m - Mass $ m $ in **kg** (finite, > 0).
|
|
41
|
+
* @param g - Local gravitational acceleration $ g $ in **m/s²** (finite, > 0).
|
|
42
|
+
* @returns Thrust-to-weight ratio (dimensionless).
|
|
43
|
+
* @throws {TypeError} If any input is not a finite number.
|
|
44
|
+
* @throws {RangeError} If `F < 0`, `m <= 0` or `g <= 0`.
|
|
45
|
+
* @group Manoeuvres
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* // A 2000 kg lander with a 45 kN engine on Mars (g ≈ 3.71 m/s²)
|
|
50
|
+
* const tw = thrustToWeight(45_000, 2000, 3.71);
|
|
51
|
+
* // tw ≈ 6.06
|
|
52
|
+
* ```
|
|
53
|
+
*
|
|
54
|
+
* @see {@link massFlowRate}
|
|
55
|
+
*/
|
|
56
|
+
export const thrustToWeight = (F, m, g) => {
|
|
57
|
+
for (const [name, v] of [
|
|
58
|
+
['F', F],
|
|
59
|
+
['m', m],
|
|
60
|
+
['g', g]
|
|
61
|
+
]) {
|
|
62
|
+
if (!Number.isFinite(v))
|
|
63
|
+
throw new TypeError(`${name} must be a finite number. Received: ${v}`);
|
|
64
|
+
}
|
|
65
|
+
if (F < 0)
|
|
66
|
+
throw new RangeError(`F must be >= 0. Received: ${F}`);
|
|
67
|
+
if (m <= 0)
|
|
68
|
+
throw new RangeError(`m must be > 0. Received: ${m}`);
|
|
69
|
+
if (g <= 0)
|
|
70
|
+
throw new RangeError(`g must be > 0. Received: ${g}`);
|
|
71
|
+
return F / (m * g);
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=thrust-to-weight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thrust-to-weight.js","sourceRoot":"","sources":["../../../src/categories/manoeuvres/thrust-to-weight.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS,EAAU,EAAE;IACxE,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI;QACtB,CAAC,GAAG,EAAE,CAAC,CAAC;QACR,CAAC,GAAG,EAAE,CAAC,CAAC;QACR,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,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,6BAA6B,CAAC,EAAE,CAAC,CAAC;IAElE,IAAI,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,4BAA4B,CAAC,EAAE,CAAC,CAAC;IAElE,IAAI,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,4BAA4B,CAAC,EAAE,CAAC,CAAC;IAElE,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AACrB,CAAC,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { ClassicalElementsInterface, StateVectorInterface } from '@interstellar-tools/types';
|
|
2
|
+
/**
|
|
3
|
+
* Convert the six **classical orbital elements** to a **state vector** (position and velocity).
|
|
4
|
+
*
|
|
5
|
+
* In the perifocal frame, with $ p = a(1 - e^2) $:
|
|
6
|
+
*
|
|
7
|
+
* $$
|
|
8
|
+
* \mathbf r_{PQW} = \frac{p}{1 + e\cos\nu}\begin{pmatrix}\cos\nu \\ \sin\nu \\ 0\end{pmatrix}, \quad
|
|
9
|
+
* \mathbf v_{PQW} = \sqrt{\frac{\mu}{p}}\begin{pmatrix}-\sin\nu \\ e + \cos\nu \\ 0\end{pmatrix}
|
|
10
|
+
* $$
|
|
11
|
+
*
|
|
12
|
+
* then rotated into the inertial frame:
|
|
13
|
+
*
|
|
14
|
+
* $$
|
|
15
|
+
* \mathbf r = R_3(\Omega)\,R_1(i)\,R_3(\omega)\,\mathbf r_{PQW}, \quad
|
|
16
|
+
* \mathbf v = R_3(\Omega)\,R_1(i)\,R_3(\omega)\,\mathbf v_{PQW}
|
|
17
|
+
* $$
|
|
18
|
+
*
|
|
19
|
+
* **Units**
|
|
20
|
+
* - Inputs: `a` in **m**, `e` dimensionless, angles in **radians**, `mu` in **m³/s²**.
|
|
21
|
+
* - Output: `r` in **m**, `v` in **m/s**.
|
|
22
|
+
*
|
|
23
|
+
* ::: info Notes
|
|
24
|
+
*
|
|
25
|
+
* - The inverse of {@link stateToElements}, including its conventions for circular and equatorial orbits.
|
|
26
|
+
* - Elliptic orbits need $ a > 0 $ and hyperbolic ones $ a < 0 $. A parabolic orbit ($ e = 1 $) has no finite $ a $, so it isn't supported.
|
|
27
|
+
* - On a hyperbola, only true anomalies with $ 1 + e\cos\nu > 0 $ exist: the body never reaches the asymptotes.
|
|
28
|
+
*
|
|
29
|
+
* :::
|
|
30
|
+
*
|
|
31
|
+
* @param elements - The classical orbital elements.
|
|
32
|
+
* @param mu - Gravitational parameter $ \mu $ in **m³/s²** (finite, > 0).
|
|
33
|
+
* @returns The position `r` in **m** and velocity `v` in **m/s**.
|
|
34
|
+
* @throws {TypeError} If any input is not a finite number.
|
|
35
|
+
* @throws {RangeError} If `mu <= 0`, `e < 0`, `e = 1`, `i` is outside [0, π], `a` has the wrong sign for `e`, or `nu` is beyond a hyperbola's asymptotes.
|
|
36
|
+
* @group Orbits
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* import type { Radians } from '@interstellar-tools/types';
|
|
41
|
+
*
|
|
42
|
+
* // A circular, equatorial orbit at 7000 km, a quarter of the way round
|
|
43
|
+
* const { r, v } = elementsToState(
|
|
44
|
+
* {
|
|
45
|
+
* a: 7_000_000,
|
|
46
|
+
* e: 0,
|
|
47
|
+
* i: 0 as Radians,
|
|
48
|
+
* raan: 0 as Radians,
|
|
49
|
+
* argp: 0 as Radians,
|
|
50
|
+
* nu: (Math.PI / 2) as Radians
|
|
51
|
+
* },
|
|
52
|
+
* 3.986004418e14
|
|
53
|
+
* );
|
|
54
|
+
* // r ≈ [0, 7 000 000, 0] m, v ≈ [-7546, 0, 0] m/s
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* @see {@link stateToElements}
|
|
58
|
+
* @see https://en.wikipedia.org/wiki/Perifocal_coordinate_system Perifocal coordinate system
|
|
59
|
+
*/
|
|
60
|
+
export declare const elementsToState: (elements: ClassicalElementsInterface, mu: number) => StateVectorInterface;
|
|
61
|
+
//# sourceMappingURL=elements-to-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"elements-to-state.d.ts","sourceRoot":"","sources":["../../../src/categories/orbits/elements-to-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,0BAA0B,EAC1B,oBAAoB,EAErB,MAAM,2BAA2B,CAAC;AAOnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACH,eAAO,MAAM,eAAe,GAC1B,UAAU,0BAA0B,EACpC,IAAI,MAAM,KACT,oBA4DF,CAAC"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { applyMatrix3 } from '../helpers/apply-matrix-3.js';
|
|
2
|
+
import { matMul3 } from '../helpers/mat-mul3.js';
|
|
3
|
+
import { rot1 } from '../helpers/rot-1.js';
|
|
4
|
+
import { rot3 } from '../helpers/rot-3.js';
|
|
5
|
+
/**
|
|
6
|
+
* Convert the six **classical orbital elements** to a **state vector** (position and velocity).
|
|
7
|
+
*
|
|
8
|
+
* In the perifocal frame, with $ p = a(1 - e^2) $:
|
|
9
|
+
*
|
|
10
|
+
* $$
|
|
11
|
+
* \mathbf r_{PQW} = \frac{p}{1 + e\cos\nu}\begin{pmatrix}\cos\nu \\ \sin\nu \\ 0\end{pmatrix}, \quad
|
|
12
|
+
* \mathbf v_{PQW} = \sqrt{\frac{\mu}{p}}\begin{pmatrix}-\sin\nu \\ e + \cos\nu \\ 0\end{pmatrix}
|
|
13
|
+
* $$
|
|
14
|
+
*
|
|
15
|
+
* then rotated into the inertial frame:
|
|
16
|
+
*
|
|
17
|
+
* $$
|
|
18
|
+
* \mathbf r = R_3(\Omega)\,R_1(i)\,R_3(\omega)\,\mathbf r_{PQW}, \quad
|
|
19
|
+
* \mathbf v = R_3(\Omega)\,R_1(i)\,R_3(\omega)\,\mathbf v_{PQW}
|
|
20
|
+
* $$
|
|
21
|
+
*
|
|
22
|
+
* **Units**
|
|
23
|
+
* - Inputs: `a` in **m**, `e` dimensionless, angles in **radians**, `mu` in **m³/s²**.
|
|
24
|
+
* - Output: `r` in **m**, `v` in **m/s**.
|
|
25
|
+
*
|
|
26
|
+
* ::: info Notes
|
|
27
|
+
*
|
|
28
|
+
* - The inverse of {@link stateToElements}, including its conventions for circular and equatorial orbits.
|
|
29
|
+
* - Elliptic orbits need $ a > 0 $ and hyperbolic ones $ a < 0 $. A parabolic orbit ($ e = 1 $) has no finite $ a $, so it isn't supported.
|
|
30
|
+
* - On a hyperbola, only true anomalies with $ 1 + e\cos\nu > 0 $ exist: the body never reaches the asymptotes.
|
|
31
|
+
*
|
|
32
|
+
* :::
|
|
33
|
+
*
|
|
34
|
+
* @param elements - The classical orbital elements.
|
|
35
|
+
* @param mu - Gravitational parameter $ \mu $ in **m³/s²** (finite, > 0).
|
|
36
|
+
* @returns The position `r` in **m** and velocity `v` in **m/s**.
|
|
37
|
+
* @throws {TypeError} If any input is not a finite number.
|
|
38
|
+
* @throws {RangeError} If `mu <= 0`, `e < 0`, `e = 1`, `i` is outside [0, π], `a` has the wrong sign for `e`, or `nu` is beyond a hyperbola's asymptotes.
|
|
39
|
+
* @group Orbits
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* import type { Radians } from '@interstellar-tools/types';
|
|
44
|
+
*
|
|
45
|
+
* // A circular, equatorial orbit at 7000 km, a quarter of the way round
|
|
46
|
+
* const { r, v } = elementsToState(
|
|
47
|
+
* {
|
|
48
|
+
* a: 7_000_000,
|
|
49
|
+
* e: 0,
|
|
50
|
+
* i: 0 as Radians,
|
|
51
|
+
* raan: 0 as Radians,
|
|
52
|
+
* argp: 0 as Radians,
|
|
53
|
+
* nu: (Math.PI / 2) as Radians
|
|
54
|
+
* },
|
|
55
|
+
* 3.986004418e14
|
|
56
|
+
* );
|
|
57
|
+
* // r ≈ [0, 7 000 000, 0] m, v ≈ [-7546, 0, 0] m/s
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* @see {@link stateToElements}
|
|
61
|
+
* @see https://en.wikipedia.org/wiki/Perifocal_coordinate_system Perifocal coordinate system
|
|
62
|
+
*/
|
|
63
|
+
export const elementsToState = (elements, mu) => {
|
|
64
|
+
const { a, e, i, raan, argp, nu } = elements;
|
|
65
|
+
for (const [name, x] of [
|
|
66
|
+
['a', a],
|
|
67
|
+
['e', e],
|
|
68
|
+
['i', i],
|
|
69
|
+
['raan', raan],
|
|
70
|
+
['argp', argp],
|
|
71
|
+
['nu', nu],
|
|
72
|
+
['mu', mu]
|
|
73
|
+
]) {
|
|
74
|
+
if (!Number.isFinite(x))
|
|
75
|
+
throw new TypeError(`${name} must be a finite number. Received: ${x}`);
|
|
76
|
+
}
|
|
77
|
+
if (mu <= 0)
|
|
78
|
+
throw new RangeError(`mu must be > 0. Received: ${mu}`);
|
|
79
|
+
if (e < 0)
|
|
80
|
+
throw new RangeError(`e must be >= 0. Received: ${e}`);
|
|
81
|
+
if (Math.abs(e - 1) < 1e-12)
|
|
82
|
+
throw new RangeError('Parabolic orbits (e = 1) are not supported: they have no finite semi-major axis.');
|
|
83
|
+
if (i < 0 || i > Math.PI)
|
|
84
|
+
throw new RangeError(`i must be in [0, π]. Received: ${i}`);
|
|
85
|
+
if (e < 1 && a <= 0)
|
|
86
|
+
throw new RangeError(`a must be > 0 for an elliptic orbit. Received: a=${a}, e=${e}`);
|
|
87
|
+
if (e > 1 && a >= 0)
|
|
88
|
+
throw new RangeError(`a must be < 0 for a hyperbolic orbit. Received: a=${a}, e=${e}`);
|
|
89
|
+
const p = a * (1 - e * e);
|
|
90
|
+
const denominator = 1 + e * Math.cos(nu);
|
|
91
|
+
if (denominator <= 0)
|
|
92
|
+
throw new RangeError(`nu is beyond the hyperbola's asymptotes (1 + e cos nu <= 0). Received: nu=${nu}, e=${e}`);
|
|
93
|
+
const rPqw = [
|
|
94
|
+
(p * Math.cos(nu)) / denominator,
|
|
95
|
+
(p * Math.sin(nu)) / denominator,
|
|
96
|
+
0
|
|
97
|
+
];
|
|
98
|
+
const speed = Math.sqrt(mu / p);
|
|
99
|
+
const vPqw = [
|
|
100
|
+
-speed * Math.sin(nu),
|
|
101
|
+
speed * (e + Math.cos(nu)),
|
|
102
|
+
0
|
|
103
|
+
];
|
|
104
|
+
const Q = matMul3(matMul3(rot3(raan), rot1(i)), rot3(argp));
|
|
105
|
+
return { r: applyMatrix3(Q, rPqw), v: applyMatrix3(Q, vPqw) };
|
|
106
|
+
};
|
|
107
|
+
//# sourceMappingURL=elements-to-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"elements-to-state.js","sourceRoot":"","sources":["../../../src/categories/orbits/elements-to-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { Radians } from '@interstellar-tools/types';
|
|
2
|
+
/**
|
|
3
|
+
* Compute the **inclination** of the orbit reached by launching from a latitude on an azimuth.
|
|
4
|
+
*
|
|
5
|
+
* $$
|
|
6
|
+
* \cos i = \cos\varphi \,\sin\beta
|
|
7
|
+
* $$
|
|
8
|
+
*
|
|
9
|
+
* Where:
|
|
10
|
+
* - $ i $ is the orbit's inclination (rad)
|
|
11
|
+
* - $ \varphi $ is the geocentric latitude of the point (rad)
|
|
12
|
+
* - $ \beta $ is the inertial azimuth or heading at that point, clockwise from north (rad)
|
|
13
|
+
*
|
|
14
|
+
* **Units**
|
|
15
|
+
* - Inputs: `lat` and `azimuth` in **radians**.
|
|
16
|
+
* - Output: $ i $ in **radians**, in [0, π].
|
|
17
|
+
*
|
|
18
|
+
* ::: info Notes
|
|
19
|
+
*
|
|
20
|
+
* - `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)).
|
|
21
|
+
* - The relation holds at every point of the ground track, not only at launch: an orbit never reaches a latitude higher than its inclination.
|
|
22
|
+
* - Launching due east ($ \beta = 90° $) gives the lowest inclination a site can reach without a plane change: its own latitude.
|
|
23
|
+
* - Azimuths between 180° and 360° head west, into retrograde orbits ($ i > 90° $).
|
|
24
|
+
* - `azimuth` is inertial. A rocket's azimuth over the ground differs, because the pad is moving east; see {@link rotatingLaunchAzimuth}.
|
|
25
|
+
*
|
|
26
|
+
* :::
|
|
27
|
+
*
|
|
28
|
+
* ::: practice Apollo 11, entering Earth orbit
|
|
29
|
+
*
|
|
30
|
+
* **32.52°**
|
|
31
|
+
*
|
|
32
|
+
* _At orbit insertion: 32.497° N geocentric, heading 88.848°_
|
|
33
|
+
*
|
|
34
|
+
* The flown parking orbit was inclined 32.521°. Apollo 11 entered orbit near the northernmost point of its track, heading almost due east. With the published geodetic latitude, 32.672°, the result would be 32.69°.
|
|
35
|
+
*
|
|
36
|
+
* ```ts
|
|
37
|
+
* inclinationFromLaunchAzimuth(toRad(32.497), toRad(88.848)); // ≈ 32.52°
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* :::
|
|
41
|
+
*
|
|
42
|
+
* @param lat - Geocentric latitude $ \varphi $ in **radians** (finite, in [-π/2, π/2]).
|
|
43
|
+
* @param azimuth - Inertial azimuth $ \beta $ in **radians**, clockwise from north (finite).
|
|
44
|
+
* @returns Inclination $ i $ in **radians**, in [0, π].
|
|
45
|
+
* @throws {TypeError} If any input is not a finite number.
|
|
46
|
+
* @throws {RangeError} If `lat` is outside [-π/2, π/2].
|
|
47
|
+
* @group Orbits
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* import type { Radians } from '@interstellar-tools/types';
|
|
52
|
+
*
|
|
53
|
+
* const toRad = (deg: number) => ((deg * Math.PI) / 180) as Radians;
|
|
54
|
+
*
|
|
55
|
+
* // Baikonur (45.97° N), launching north-east at 63°
|
|
56
|
+
* const i = inclinationFromLaunchAzimuth(toRad(45.97), toRad(63));
|
|
57
|
+
* // i ≈ 51.7°
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* @see {@link launchAzimuthForInclination}
|
|
61
|
+
* @see https://en.wikipedia.org/wiki/Launch_azimuth Launch azimuth
|
|
62
|
+
*/
|
|
63
|
+
export declare const inclinationFromLaunchAzimuth: (lat: Radians, azimuth: Radians) => Radians;
|
|
64
|
+
//# sourceMappingURL=inclination-from-launch-azimuth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inclination-from-launch-azimuth.d.ts","sourceRoot":"","sources":["../../../src/categories/orbits/inclination-from-launch-azimuth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AACH,eAAO,MAAM,4BAA4B,GACvC,KAAK,OAAO,EACZ,SAAS,OAAO,KACf,OAgBF,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compute the **inclination** of the orbit reached by launching from a latitude on an azimuth.
|
|
3
|
+
*
|
|
4
|
+
* $$
|
|
5
|
+
* \cos i = \cos\varphi \,\sin\beta
|
|
6
|
+
* $$
|
|
7
|
+
*
|
|
8
|
+
* Where:
|
|
9
|
+
* - $ i $ is the orbit's inclination (rad)
|
|
10
|
+
* - $ \varphi $ is the geocentric latitude of the point (rad)
|
|
11
|
+
* - $ \beta $ is the inertial azimuth or heading at that point, clockwise from north (rad)
|
|
12
|
+
*
|
|
13
|
+
* **Units**
|
|
14
|
+
* - Inputs: `lat` and `azimuth` in **radians**.
|
|
15
|
+
* - Output: $ i $ in **radians**, in [0, π].
|
|
16
|
+
*
|
|
17
|
+
* ::: info Notes
|
|
18
|
+
*
|
|
19
|
+
* - `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)).
|
|
20
|
+
* - The relation holds at every point of the ground track, not only at launch: an orbit never reaches a latitude higher than its inclination.
|
|
21
|
+
* - Launching due east ($ \beta = 90° $) gives the lowest inclination a site can reach without a plane change: its own latitude.
|
|
22
|
+
* - Azimuths between 180° and 360° head west, into retrograde orbits ($ i > 90° $).
|
|
23
|
+
* - `azimuth` is inertial. A rocket's azimuth over the ground differs, because the pad is moving east; see {@link rotatingLaunchAzimuth}.
|
|
24
|
+
*
|
|
25
|
+
* :::
|
|
26
|
+
*
|
|
27
|
+
* ::: practice Apollo 11, entering Earth orbit
|
|
28
|
+
*
|
|
29
|
+
* **32.52°**
|
|
30
|
+
*
|
|
31
|
+
* _At orbit insertion: 32.497° N geocentric, heading 88.848°_
|
|
32
|
+
*
|
|
33
|
+
* The flown parking orbit was inclined 32.521°. Apollo 11 entered orbit near the northernmost point of its track, heading almost due east. With the published geodetic latitude, 32.672°, the result would be 32.69°.
|
|
34
|
+
*
|
|
35
|
+
* ```ts
|
|
36
|
+
* inclinationFromLaunchAzimuth(toRad(32.497), toRad(88.848)); // ≈ 32.52°
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* :::
|
|
40
|
+
*
|
|
41
|
+
* @param lat - Geocentric latitude $ \varphi $ in **radians** (finite, in [-π/2, π/2]).
|
|
42
|
+
* @param azimuth - Inertial azimuth $ \beta $ in **radians**, clockwise from north (finite).
|
|
43
|
+
* @returns Inclination $ i $ in **radians**, in [0, π].
|
|
44
|
+
* @throws {TypeError} If any input is not a finite number.
|
|
45
|
+
* @throws {RangeError} If `lat` is outside [-π/2, π/2].
|
|
46
|
+
* @group Orbits
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* import type { Radians } from '@interstellar-tools/types';
|
|
51
|
+
*
|
|
52
|
+
* const toRad = (deg: number) => ((deg * Math.PI) / 180) as Radians;
|
|
53
|
+
*
|
|
54
|
+
* // Baikonur (45.97° N), launching north-east at 63°
|
|
55
|
+
* const i = inclinationFromLaunchAzimuth(toRad(45.97), toRad(63));
|
|
56
|
+
* // i ≈ 51.7°
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* @see {@link launchAzimuthForInclination}
|
|
60
|
+
* @see https://en.wikipedia.org/wiki/Launch_azimuth Launch azimuth
|
|
61
|
+
*/
|
|
62
|
+
export const inclinationFromLaunchAzimuth = (lat, azimuth) => {
|
|
63
|
+
for (const [name, v] of [
|
|
64
|
+
['lat', lat],
|
|
65
|
+
['azimuth', azimuth]
|
|
66
|
+
]) {
|
|
67
|
+
if (!Number.isFinite(v))
|
|
68
|
+
throw new TypeError(`${name} must be a finite number. Received: ${v}`);
|
|
69
|
+
}
|
|
70
|
+
if (Math.abs(lat) > Math.PI / 2)
|
|
71
|
+
throw new RangeError(`lat must be in [-π/2, π/2]. Received: ${lat}`);
|
|
72
|
+
// Clamp against rounding just outside [-1, 1]
|
|
73
|
+
const cosI = Math.min(1, Math.max(-1, Math.cos(lat) * Math.sin(azimuth)));
|
|
74
|
+
return Math.acos(cosI);
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=inclination-from-launch-azimuth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inclination-from-launch-azimuth.js","sourceRoot":"","sources":["../../../src/categories/orbits/inclination-from-launch-azimuth.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAC1C,GAAY,EACZ,OAAgB,EACP,EAAE;IACX,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI;QACtB,CAAC,KAAK,EAAE,GAAG,CAAC;QACZ,CAAC,SAAS,EAAE,OAAO,CAAC;KACZ,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,8CAA8C;IAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAE1E,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAY,CAAC;AACpC,CAAC,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { Radians } from '@interstellar-tools/types';
|
|
2
|
+
export interface LaunchAzimuthsInterface {
|
|
3
|
+
/** Azimuth for the ascending pass: heading north, in [0, π/2] or [3π/2, 2π) */
|
|
4
|
+
northbound: Radians;
|
|
5
|
+
/** Azimuth for the descending pass: heading south, in [π/2, 3π/2] */
|
|
6
|
+
southbound: Radians;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Compute the **inertial launch azimuths** that reach an inclination from a latitude.
|
|
10
|
+
*
|
|
11
|
+
* $$
|
|
12
|
+
* \sin\beta = \frac{\cos i}{\cos\varphi}
|
|
13
|
+
* $$
|
|
14
|
+
*
|
|
15
|
+
* Where:
|
|
16
|
+
* - $ \beta $ is the inertial azimuth, clockwise from north (rad)
|
|
17
|
+
* - $ i $ is the target inclination (rad)
|
|
18
|
+
* - $ \varphi $ is the geocentric launch latitude (rad)
|
|
19
|
+
*
|
|
20
|
+
* Two azimuths reach every reachable inclination: one heading north ($ \beta $) and one heading south ($ \pi - \beta $).
|
|
21
|
+
*
|
|
22
|
+
* **Units**
|
|
23
|
+
* - Inputs: `lat` and `i` in **radians**.
|
|
24
|
+
* - Output: both azimuths in **radians**, in [0, 2π).
|
|
25
|
+
*
|
|
26
|
+
* ::: info Notes
|
|
27
|
+
*
|
|
28
|
+
* - `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)).
|
|
29
|
+
* - A site can only reach inclinations between $ |\varphi| $ and $ \pi - |\varphi| $ directly. Anything else needs a plane change, or a dogleg during ascent.
|
|
30
|
+
* - The azimuths are inertial. Over the ground, the rocket flies a slightly different heading; see {@link rotatingLaunchAzimuth}.
|
|
31
|
+
* - At $ i = |\varphi| $ the two solutions meet, due east (or due west for retrograde orbits).
|
|
32
|
+
*
|
|
33
|
+
* :::
|
|
34
|
+
*
|
|
35
|
+
* ::: practice To the ISS from Cape Canaveral
|
|
36
|
+
*
|
|
37
|
+
* **44.9°**
|
|
38
|
+
*
|
|
39
|
+
* _Inertial azimuth from Pad 39A, 28.447° N geocentric, to an orbit inclined 51.64°_
|
|
40
|
+
*
|
|
41
|
+
* Over the ground the rocket flies 42.7°, because the pad is already moving east at 409 m/s.
|
|
42
|
+
*
|
|
43
|
+
* ```ts
|
|
44
|
+
* launchAzimuthForInclination(toRad(28.447), toRad(51.64)).northbound; // ≈ 44.9°
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* :::
|
|
48
|
+
*
|
|
49
|
+
* @param lat - Geocentric launch latitude $ \varphi $ in **radians** (finite, in (-π/2, π/2)).
|
|
50
|
+
* @param i - Target inclination $ i $ in **radians** (finite, in [0, π]).
|
|
51
|
+
* @returns The northbound and southbound inertial azimuths, in **radians**.
|
|
52
|
+
* @throws {TypeError} If any input is not a finite number.
|
|
53
|
+
* @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|`).
|
|
54
|
+
* @group Orbits
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```ts
|
|
58
|
+
* import type { Radians } from '@interstellar-tools/types';
|
|
59
|
+
*
|
|
60
|
+
* const toRad = (deg: number) => ((deg * Math.PI) / 180) as Radians;
|
|
61
|
+
*
|
|
62
|
+
* // A sun-synchronous orbit (97.8°) from Vandenberg (34.7° N)
|
|
63
|
+
* const { southbound } = launchAzimuthForInclination(toRad(34.7), toRad(97.8));
|
|
64
|
+
* // southbound ≈ 189.5°: south, slightly west
|
|
65
|
+
* ```
|
|
66
|
+
*
|
|
67
|
+
* @see {@link inclinationFromLaunchAzimuth}
|
|
68
|
+
* @see https://en.wikipedia.org/wiki/Launch_azimuth Launch azimuth
|
|
69
|
+
*/
|
|
70
|
+
export declare const launchAzimuthForInclination: (lat: Radians, i: Radians) => LaunchAzimuthsInterface;
|
|
71
|
+
//# sourceMappingURL=launch-azimuth-for-inclination.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launch-azimuth-for-inclination.d.ts","sourceRoot":"","sources":["../../../src/categories/orbits/launch-azimuth-for-inclination.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAIzD,MAAM,WAAW,uBAAuB;IACtC,+EAA+E;IAC/E,UAAU,EAAE,OAAO,CAAC;IACpB,qEAAqE;IACrE,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AACH,eAAO,MAAM,2BAA2B,GACtC,KAAK,OAAO,EACZ,GAAG,OAAO,KACT,uBA8BF,CAAC"}
|