@interstellar-tools/equations 1.1.0 → 1.3.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.
Files changed (53) hide show
  1. package/dist/categories/anomalies/asymptote-true-anomaly.d.ts +50 -0
  2. package/dist/categories/anomalies/asymptote-true-anomaly.d.ts.map +1 -0
  3. package/dist/categories/anomalies/asymptote-true-anomaly.js +55 -0
  4. package/dist/categories/anomalies/asymptote-true-anomaly.js.map +1 -0
  5. package/dist/categories/anomalies/hyperbolic-to-true-anomaly.d.ts +38 -0
  6. package/dist/categories/anomalies/hyperbolic-to-true-anomaly.d.ts.map +1 -0
  7. package/dist/categories/anomalies/hyperbolic-to-true-anomaly.js +49 -0
  8. package/dist/categories/anomalies/hyperbolic-to-true-anomaly.js.map +1 -0
  9. package/dist/categories/anomalies/true-to-hyperbolic-anomaly.d.ts +40 -0
  10. package/dist/categories/anomalies/true-to-hyperbolic-anomaly.d.ts.map +1 -0
  11. package/dist/categories/anomalies/true-to-hyperbolic-anomaly.js +54 -0
  12. package/dist/categories/anomalies/true-to-hyperbolic-anomaly.js.map +1 -0
  13. package/dist/categories/kepler/solve-kepler-hyperbolic.d.ts +49 -0
  14. package/dist/categories/kepler/solve-kepler-hyperbolic.d.ts.map +1 -0
  15. package/dist/categories/kepler/solve-kepler-hyperbolic.js +90 -0
  16. package/dist/categories/kepler/solve-kepler-hyperbolic.js.map +1 -0
  17. package/dist/categories/manoeuvres/cw-two-impulse-transfer.d.ts +58 -0
  18. package/dist/categories/manoeuvres/cw-two-impulse-transfer.d.ts.map +1 -0
  19. package/dist/categories/manoeuvres/cw-two-impulse-transfer.js +104 -0
  20. package/dist/categories/manoeuvres/cw-two-impulse-transfer.js.map +1 -0
  21. package/dist/categories/manoeuvres/phasing-wait-time.d.ts +55 -0
  22. package/dist/categories/manoeuvres/phasing-wait-time.d.ts.map +1 -0
  23. package/dist/categories/manoeuvres/phasing-wait-time.js +77 -0
  24. package/dist/categories/manoeuvres/phasing-wait-time.js.map +1 -0
  25. package/dist/categories/orbits/cw-propagate.d.ts +48 -0
  26. package/dist/categories/orbits/cw-propagate.d.ts.map +1 -0
  27. package/dist/categories/orbits/cw-propagate.js +68 -0
  28. package/dist/categories/orbits/cw-propagate.js.map +1 -0
  29. package/dist/categories/orbits/cw-state-transition.d.ts +65 -0
  30. package/dist/categories/orbits/cw-state-transition.d.ts.map +1 -0
  31. package/dist/categories/orbits/cw-state-transition.js +83 -0
  32. package/dist/categories/orbits/cw-state-transition.js.map +1 -0
  33. package/dist/categories/orbits/hyperbolic-eccentricity.d.ts +56 -0
  34. package/dist/categories/orbits/hyperbolic-eccentricity.d.ts.map +1 -0
  35. package/dist/categories/orbits/hyperbolic-eccentricity.js +72 -0
  36. package/dist/categories/orbits/hyperbolic-eccentricity.js.map +1 -0
  37. package/dist/categories/orbits/hyperbolic-semi-major-axis.d.ts +53 -0
  38. package/dist/categories/orbits/hyperbolic-semi-major-axis.d.ts.map +1 -0
  39. package/dist/categories/orbits/hyperbolic-semi-major-axis.js +66 -0
  40. package/dist/categories/orbits/hyperbolic-semi-major-axis.js.map +1 -0
  41. package/dist/categories/orbits/hyperbolic-time-of-flight.d.ts +64 -0
  42. package/dist/categories/orbits/hyperbolic-time-of-flight.d.ts.map +1 -0
  43. package/dist/categories/orbits/hyperbolic-time-of-flight.js +86 -0
  44. package/dist/categories/orbits/hyperbolic-time-of-flight.js.map +1 -0
  45. package/dist/categories/orbits/synodic-period.d.ts +59 -0
  46. package/dist/categories/orbits/synodic-period.d.ts.map +1 -0
  47. package/dist/categories/orbits/synodic-period.js +72 -0
  48. package/dist/categories/orbits/synodic-period.js.map +1 -0
  49. package/dist/index.d.ts +12 -0
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js +12 -0
  52. package/dist/index.js.map +1 -1
  53. package/package.json +1 -1
@@ -0,0 +1,50 @@
1
+ import type { Radians } from '@interstellar-tools/types';
2
+ /**
3
+ * Compute the **true anomaly of a hyperbola's asymptotes**: the limit a body on a hyperbola approaches but never reaches.
4
+ *
5
+ * $$
6
+ * \nu_\infty = \arccos\left(-\frac{1}{e}\right)
7
+ * $$
8
+ *
9
+ * **Units**
10
+ * - Input: `e` dimensionless.
11
+ * - Output: $ \nu_\infty $ in **radians**, in (π/2, π).
12
+ *
13
+ * ::: info Notes
14
+ *
15
+ * - The body comes in from $ -\nu_\infty $ and leaves towards $ +\nu_\infty $.
16
+ * - The trajectory turns through $ 2\nu_\infty - \pi = 2\arcsin(1/e) $, the turning angle of a flyby; see `gravityAssistTurningAngle`.
17
+ * - Just above $ e = 1 $ the asymptotes open to almost π (a near-parabola); for large $ e $ they close towards π/2 (a near-straight line).
18
+ *
19
+ * :::
20
+ *
21
+ * ::: practice Apollo 11, arriving at the Moon
22
+ *
23
+ * **134.0°**
24
+ *
25
+ * _Asymptote of the approach hyperbola, e = 1.44_
26
+ *
27
+ * Without the lunar orbit insertion burn at closest approach, the Moon's gravity would have bent Apollo 11's path through 88° and sent it back out of the Moon's sphere of influence.
28
+ *
29
+ * ```ts
30
+ * asymptoteTrueAnomaly(1.44); // ≈ 2.338 rad, 134.0°
31
+ * ```
32
+ *
33
+ * :::
34
+ *
35
+ * @param e - Eccentricity $ e $ (finite, > 1).
36
+ * @returns Asymptote true anomaly $ \nu_\infty $ in **radians**.
37
+ * @throws {TypeError} If `e` is not a finite number.
38
+ * @throws {RangeError} If `e <= 1`.
39
+ * @group Anomalies
40
+ *
41
+ * @example
42
+ * ```ts
43
+ * asymptoteTrueAnomaly(2); // 2π/3 (120°)
44
+ * ```
45
+ *
46
+ * @see {@link trueToHyperbolicAnomaly}
47
+ * @see https://en.wikipedia.org/wiki/Hyperbolic_trajectory Hyperbolic trajectory
48
+ */
49
+ export declare const asymptoteTrueAnomaly: (e: number) => Radians;
50
+ //# sourceMappingURL=asymptote-true-anomaly.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asymptote-true-anomaly.d.ts","sourceRoot":"","sources":["../../../src/categories/anomalies/asymptote-true-anomaly.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,eAAO,MAAM,oBAAoB,GAAI,GAAG,MAAM,KAAG,OAOhD,CAAC"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Compute the **true anomaly of a hyperbola's asymptotes**: the limit a body on a hyperbola approaches but never reaches.
3
+ *
4
+ * $$
5
+ * \nu_\infty = \arccos\left(-\frac{1}{e}\right)
6
+ * $$
7
+ *
8
+ * **Units**
9
+ * - Input: `e` dimensionless.
10
+ * - Output: $ \nu_\infty $ in **radians**, in (π/2, π).
11
+ *
12
+ * ::: info Notes
13
+ *
14
+ * - The body comes in from $ -\nu_\infty $ and leaves towards $ +\nu_\infty $.
15
+ * - The trajectory turns through $ 2\nu_\infty - \pi = 2\arcsin(1/e) $, the turning angle of a flyby; see `gravityAssistTurningAngle`.
16
+ * - Just above $ e = 1 $ the asymptotes open to almost π (a near-parabola); for large $ e $ they close towards π/2 (a near-straight line).
17
+ *
18
+ * :::
19
+ *
20
+ * ::: practice Apollo 11, arriving at the Moon
21
+ *
22
+ * **134.0°**
23
+ *
24
+ * _Asymptote of the approach hyperbola, e = 1.44_
25
+ *
26
+ * Without the lunar orbit insertion burn at closest approach, the Moon's gravity would have bent Apollo 11's path through 88° and sent it back out of the Moon's sphere of influence.
27
+ *
28
+ * ```ts
29
+ * asymptoteTrueAnomaly(1.44); // ≈ 2.338 rad, 134.0°
30
+ * ```
31
+ *
32
+ * :::
33
+ *
34
+ * @param e - Eccentricity $ e $ (finite, > 1).
35
+ * @returns Asymptote true anomaly $ \nu_\infty $ in **radians**.
36
+ * @throws {TypeError} If `e` is not a finite number.
37
+ * @throws {RangeError} If `e <= 1`.
38
+ * @group Anomalies
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * asymptoteTrueAnomaly(2); // 2π/3 (120°)
43
+ * ```
44
+ *
45
+ * @see {@link trueToHyperbolicAnomaly}
46
+ * @see https://en.wikipedia.org/wiki/Hyperbolic_trajectory Hyperbolic trajectory
47
+ */
48
+ export const asymptoteTrueAnomaly = (e) => {
49
+ if (!Number.isFinite(e))
50
+ throw new TypeError(`e must be a finite number. Received: ${e}`);
51
+ if (e <= 1)
52
+ throw new RangeError(`e must be > 1. Received: ${e}`);
53
+ return Math.acos(-1 / e);
54
+ };
55
+ //# sourceMappingURL=asymptote-true-anomaly.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asymptote-true-anomaly.js","sourceRoot":"","sources":["../../../src/categories/anomalies/asymptote-true-anomaly.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAS,EAAW,EAAE;IACzD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QACrB,MAAM,IAAI,SAAS,CAAC,wCAAwC,CAAC,EAAE,CAAC,CAAC;IAEnE,IAAI,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,4BAA4B,CAAC,EAAE,CAAC,CAAC;IAElE,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAY,CAAC;AACtC,CAAC,CAAC"}
@@ -0,0 +1,38 @@
1
+ import type { Radians } from '@interstellar-tools/types';
2
+ /**
3
+ * Convert a **hyperbolic anomaly** $ F $ to the **true anomaly** on a hyperbola.
4
+ *
5
+ * $$
6
+ * \tan\frac{\nu}{2} = \sqrt{\frac{e + 1}{e - 1}}\,\tanh\frac{F}{2}
7
+ * $$
8
+ *
9
+ * **Units**
10
+ * - Inputs: `F` in **radians**, `e` dimensionless.
11
+ * - Output: $ \nu $ in **radians**, in $ (-\nu_\infty, \nu_\infty) $.
12
+ *
13
+ * ::: info Notes
14
+ *
15
+ * - The inverse of {@link trueToHyperbolicAnomaly}.
16
+ * - As $ F \to \pm\infty $, $ \nu $ approaches the asymptotes $ \pm\nu_\infty $ but never reaches them.
17
+ * - Returns a signed angle, negative before periapsis. Use `norm2pi` for [0, 2π).
18
+ *
19
+ * :::
20
+ *
21
+ * @param F - Hyperbolic anomaly $ F $ in **radians** (finite).
22
+ * @param e - Eccentricity $ e $ (finite, > 1).
23
+ * @returns True anomaly $ \nu $ in **radians**, in (-π, π).
24
+ * @throws {TypeError} If any input is not a finite number.
25
+ * @throws {RangeError} If `e <= 1`.
26
+ * @group Anomalies
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * const nu = hyperbolicToTrueAnomaly(Math.acosh(2), 2);
31
+ * // nu ≈ π/2
32
+ * ```
33
+ *
34
+ * @see {@link trueToHyperbolicAnomaly}
35
+ * @see {@link solveKeplerHyperbolic}
36
+ */
37
+ export declare const hyperbolicToTrueAnomaly: (F: number, e: number) => Radians;
38
+ //# sourceMappingURL=hyperbolic-to-true-anomaly.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hyperbolic-to-true-anomaly.d.ts","sourceRoot":"","sources":["../../../src/categories/anomalies/hyperbolic-to-true-anomaly.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,uBAAuB,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,KAAG,OAa9D,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Convert a **hyperbolic anomaly** $ F $ to the **true anomaly** on a hyperbola.
3
+ *
4
+ * $$
5
+ * \tan\frac{\nu}{2} = \sqrt{\frac{e + 1}{e - 1}}\,\tanh\frac{F}{2}
6
+ * $$
7
+ *
8
+ * **Units**
9
+ * - Inputs: `F` in **radians**, `e` dimensionless.
10
+ * - Output: $ \nu $ in **radians**, in $ (-\nu_\infty, \nu_\infty) $.
11
+ *
12
+ * ::: info Notes
13
+ *
14
+ * - The inverse of {@link trueToHyperbolicAnomaly}.
15
+ * - As $ F \to \pm\infty $, $ \nu $ approaches the asymptotes $ \pm\nu_\infty $ but never reaches them.
16
+ * - Returns a signed angle, negative before periapsis. Use `norm2pi` for [0, 2π).
17
+ *
18
+ * :::
19
+ *
20
+ * @param F - Hyperbolic anomaly $ F $ in **radians** (finite).
21
+ * @param e - Eccentricity $ e $ (finite, > 1).
22
+ * @returns True anomaly $ \nu $ in **radians**, in (-π, π).
23
+ * @throws {TypeError} If any input is not a finite number.
24
+ * @throws {RangeError} If `e <= 1`.
25
+ * @group Anomalies
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * const nu = hyperbolicToTrueAnomaly(Math.acosh(2), 2);
30
+ * // nu ≈ π/2
31
+ * ```
32
+ *
33
+ * @see {@link trueToHyperbolicAnomaly}
34
+ * @see {@link solveKeplerHyperbolic}
35
+ */
36
+ export const hyperbolicToTrueAnomaly = (F, e) => {
37
+ for (const [name, x] of [
38
+ ['F', F],
39
+ ['e', e]
40
+ ]) {
41
+ if (!Number.isFinite(x))
42
+ throw new TypeError(`${name} must be a finite number. Received: ${x}`);
43
+ }
44
+ if (e <= 1)
45
+ throw new RangeError(`e must be > 1. Received: ${e}`);
46
+ return (2 *
47
+ Math.atan(Math.sqrt((e + 1) / (e - 1)) * Math.tanh(F / 2)));
48
+ };
49
+ //# sourceMappingURL=hyperbolic-to-true-anomaly.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hyperbolic-to-true-anomaly.js","sourceRoot":"","sources":["../../../src/categories/anomalies/hyperbolic-to-true-anomaly.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAS,EAAE,CAAS,EAAW,EAAE;IACvE,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI;QACtB,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,IAAI,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,4BAA4B,CAAC,EAAE,CAAC,CAAC;IAElE,OAAO,CAAC,CAAC;QACP,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAY,CAAC;AAC3E,CAAC,CAAC"}
@@ -0,0 +1,40 @@
1
+ import type { Radians } from '@interstellar-tools/types';
2
+ /**
3
+ * Convert a **true anomaly** on a hyperbola to the **hyperbolic anomaly** $ F $.
4
+ *
5
+ * $$
6
+ * \tanh\frac{F}{2} = \sqrt{\frac{e - 1}{e + 1}}\,\tan\frac{\nu}{2}
7
+ * $$
8
+ *
9
+ * **Units**
10
+ * - Inputs: `nu` in **radians**, `e` dimensionless.
11
+ * - Output: $ F $ in **radians** (dimensionless, unbounded).
12
+ *
13
+ * ::: info Notes
14
+ *
15
+ * - The hyperbolic counterpart of the eccentric anomaly. Feed it to $ M_h = e \sinh F - F $ to get a time from periapsis.
16
+ * - `nu` is wrapped to (-π, π] first, so the incoming branch can be given either as a negative angle or just below 2π, as {@link stateToElements} returns it.
17
+ * - Only $ |\nu| < \nu_\infty $ exists on a hyperbola; see {@link asymptoteTrueAnomaly}.
18
+ *
19
+ * :::
20
+ *
21
+ * @param nu - True anomaly $ \nu $ in **radians** (finite, inside the asymptotes).
22
+ * @param e - Eccentricity $ e $ (finite, > 1).
23
+ * @returns Hyperbolic anomaly $ F $ in **radians**: negative before periapsis, positive after.
24
+ * @throws {TypeError} If any input is not a finite number.
25
+ * @throws {RangeError} If `e <= 1` or `nu` is at or beyond the asymptotes.
26
+ * @group Anomalies
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * import type { Radians } from '@interstellar-tools/types';
31
+ *
32
+ * const F = trueToHyperbolicAnomaly((Math.PI / 2) as Radians, 2);
33
+ * // F ≈ 1.317 (cosh F = e)
34
+ * ```
35
+ *
36
+ * @see {@link hyperbolicToTrueAnomaly}
37
+ * @see https://en.wikipedia.org/wiki/Hyperbolic_trajectory#Hyperbolic_anomaly Hyperbolic anomaly
38
+ */
39
+ export declare const trueToHyperbolicAnomaly: (nu: Radians, e: number) => number;
40
+ //# sourceMappingURL=true-to-hyperbolic-anomaly.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"true-to-hyperbolic-anomaly.d.ts","sourceRoot":"","sources":["../../../src/categories/anomalies/true-to-hyperbolic-anomaly.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAIzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,eAAO,MAAM,uBAAuB,GAAI,IAAI,OAAO,EAAE,GAAG,MAAM,KAAG,MAmBhE,CAAC"}
@@ -0,0 +1,54 @@
1
+ import { asymptoteTrueAnomaly } from './asymptote-true-anomaly.js';
2
+ /**
3
+ * Convert a **true anomaly** on a hyperbola to the **hyperbolic anomaly** $ F $.
4
+ *
5
+ * $$
6
+ * \tanh\frac{F}{2} = \sqrt{\frac{e - 1}{e + 1}}\,\tan\frac{\nu}{2}
7
+ * $$
8
+ *
9
+ * **Units**
10
+ * - Inputs: `nu` in **radians**, `e` dimensionless.
11
+ * - Output: $ F $ in **radians** (dimensionless, unbounded).
12
+ *
13
+ * ::: info Notes
14
+ *
15
+ * - The hyperbolic counterpart of the eccentric anomaly. Feed it to $ M_h = e \sinh F - F $ to get a time from periapsis.
16
+ * - `nu` is wrapped to (-π, π] first, so the incoming branch can be given either as a negative angle or just below 2π, as {@link stateToElements} returns it.
17
+ * - Only $ |\nu| < \nu_\infty $ exists on a hyperbola; see {@link asymptoteTrueAnomaly}.
18
+ *
19
+ * :::
20
+ *
21
+ * @param nu - True anomaly $ \nu $ in **radians** (finite, inside the asymptotes).
22
+ * @param e - Eccentricity $ e $ (finite, > 1).
23
+ * @returns Hyperbolic anomaly $ F $ in **radians**: negative before periapsis, positive after.
24
+ * @throws {TypeError} If any input is not a finite number.
25
+ * @throws {RangeError} If `e <= 1` or `nu` is at or beyond the asymptotes.
26
+ * @group Anomalies
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * import type { Radians } from '@interstellar-tools/types';
31
+ *
32
+ * const F = trueToHyperbolicAnomaly((Math.PI / 2) as Radians, 2);
33
+ * // F ≈ 1.317 (cosh F = e)
34
+ * ```
35
+ *
36
+ * @see {@link hyperbolicToTrueAnomaly}
37
+ * @see https://en.wikipedia.org/wiki/Hyperbolic_trajectory#Hyperbolic_anomaly Hyperbolic anomaly
38
+ */
39
+ export const trueToHyperbolicAnomaly = (nu, e) => {
40
+ for (const [name, x] of [
41
+ ['nu', nu],
42
+ ['e', e]
43
+ ]) {
44
+ if (!Number.isFinite(x))
45
+ throw new TypeError(`${name} must be a finite number. Received: ${x}`);
46
+ }
47
+ if (e <= 1)
48
+ throw new RangeError(`e must be > 1. Received: ${e}`);
49
+ const wrapped = Math.atan2(Math.sin(nu), Math.cos(nu));
50
+ if (Math.abs(wrapped) >= asymptoteTrueAnomaly(e))
51
+ throw new RangeError(`nu is at or beyond the asymptotes (|nu| >= acos(-1/e)). Received: nu=${nu}, e=${e}`);
52
+ return 2 * Math.atanh(Math.sqrt((e - 1) / (e + 1)) * Math.tan(wrapped / 2));
53
+ };
54
+ //# sourceMappingURL=true-to-hyperbolic-anomaly.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"true-to-hyperbolic-anomaly.js","sourceRoot":"","sources":["../../../src/categories/anomalies/true-to-hyperbolic-anomaly.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,EAAW,EAAE,CAAS,EAAU,EAAE;IACxE,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI;QACtB,CAAC,IAAI,EAAE,EAAE,CAAC;QACV,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,IAAI,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,4BAA4B,CAAC,EAAE,CAAC,CAAC;IAElE,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAEvD,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,oBAAoB,CAAC,CAAC,CAAC;QAC9C,MAAM,IAAI,UAAU,CAClB,wEAAwE,EAAE,OAAO,CAAC,EAAE,CACrF,CAAC;IAEJ,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;AAC9E,CAAC,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Solve **Kepler's equation for a hyperbola**: find the hyperbolic anomaly $ F $ from the hyperbolic mean anomaly $ M_h $.
3
+ *
4
+ * $$
5
+ * M_h = e \sinh F - F
6
+ * $$
7
+ *
8
+ * solved with Newton's method:
9
+ *
10
+ * $$
11
+ * F_{n+1} = F_n - \frac{e \sinh F_n - F_n - M_h}{e \cosh F_n - 1}, \qquad F_0 = \min\left(\operatorname{asinh}\frac{|M_h|}{e - 1},\ \sqrt[3]{\frac{6|M_h|}{e}}\right)
12
+ * $$
13
+ *
14
+ * **Units**
15
+ * - Inputs: `Mh` in **radians**, `e` dimensionless.
16
+ * - Output: $ F $ in **radians** (dimensionless, unbounded).
17
+ *
18
+ * ::: info Notes
19
+ *
20
+ * - The equation is odd in $ F $, so the solver works on $ |M_h| $ and restores the sign. Negative values are before periapsis.
21
+ * - $ F_0 $ is an upper bound on the root, since $ e\sinh F - F $ is at least $ (e-1)\sinh F $ and at least $ (e-1)F + eF^3/6 $. The function is increasing and convex for $ F > 0 $, so Newton's method converges monotonically from there, even close to $ e = 1 $ where the derivative $ e\cosh F - 1 $ is small near periapsis.
22
+ * - Unlike an ellipse, a hyperbola isn't periodic: $ M_h $ isn't reduced to one turn.
23
+ * - {@link solveKeplerHighEccentricity} also accepts $ e > 1 $, but this solver throws when it doesn't converge instead of returning its last estimate.
24
+ *
25
+ * :::
26
+ *
27
+ * @param Mh - Hyperbolic mean anomaly $ M_h $ in **radians** (finite).
28
+ * @param e - Eccentricity $ e $ (finite, > 1).
29
+ * @param tolerance - Stop when a step is smaller than `tolerance * max(1, |F|)`. Defaults to `1e-14`.
30
+ * @param maxIter - Maximum number of Newton steps. Defaults to `50`.
31
+ * @returns The hyperbolic anomaly $ F $ in **radians**, with the sign of `Mh`.
32
+ * @throws {TypeError} If any input is not a finite number.
33
+ * @throws {RangeError} If `e <= 1`, `tolerance <= 0` or `maxIter < 1`.
34
+ * @throws {Error} If the iteration doesn't converge within `maxIter` steps.
35
+ * @group Kepler Solvers
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * import type { Radians } from '@interstellar-tools/types';
40
+ *
41
+ * const F = solveKeplerHyperbolic(12.66 as Radians, 1.44);
42
+ * // F ≈ 3.087, and 1.44 * sinh(F) - F ≈ 12.66
43
+ * ```
44
+ *
45
+ * @see {@link hyperbolicTimeOfFlight}
46
+ * @see https://en.wikipedia.org/wiki/Hyperbolic_trajectory#Hyperbolic_anomaly Hyperbolic anomaly
47
+ */
48
+ export declare const solveKeplerHyperbolic: (Mh: number, e: number, tolerance?: number, maxIter?: number) => number;
49
+ //# sourceMappingURL=solve-kepler-hyperbolic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"solve-kepler-hyperbolic.d.ts","sourceRoot":"","sources":["../../../src/categories/kepler/solve-kepler-hyperbolic.ts"],"names":[],"mappings":"AAiBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,eAAO,MAAM,qBAAqB,GAChC,IAAI,MAAM,EACV,GAAG,MAAM,EACT,kBAAiB,EACjB,gBAAY,KACX,MAsCF,CAAC"}
@@ -0,0 +1,90 @@
1
+ /** sinh x - x, from its Taylor series for small x to avoid cancellation. */
2
+ const sinhMinusX = (x) => {
3
+ if (Math.abs(x) > 0.5)
4
+ return Math.sinh(x) - x;
5
+ const x2 = x * x;
6
+ let term = (x * x2) / 6;
7
+ let sum = term;
8
+ for (let k = 5; Math.abs(term) > 1e-17 * Math.abs(sum); k += 2) {
9
+ term *= x2 / ((k - 1) * k);
10
+ sum += term;
11
+ }
12
+ return sum;
13
+ };
14
+ /**
15
+ * Solve **Kepler's equation for a hyperbola**: find the hyperbolic anomaly $ F $ from the hyperbolic mean anomaly $ M_h $.
16
+ *
17
+ * $$
18
+ * M_h = e \sinh F - F
19
+ * $$
20
+ *
21
+ * solved with Newton's method:
22
+ *
23
+ * $$
24
+ * F_{n+1} = F_n - \frac{e \sinh F_n - F_n - M_h}{e \cosh F_n - 1}, \qquad F_0 = \min\left(\operatorname{asinh}\frac{|M_h|}{e - 1},\ \sqrt[3]{\frac{6|M_h|}{e}}\right)
25
+ * $$
26
+ *
27
+ * **Units**
28
+ * - Inputs: `Mh` in **radians**, `e` dimensionless.
29
+ * - Output: $ F $ in **radians** (dimensionless, unbounded).
30
+ *
31
+ * ::: info Notes
32
+ *
33
+ * - The equation is odd in $ F $, so the solver works on $ |M_h| $ and restores the sign. Negative values are before periapsis.
34
+ * - $ F_0 $ is an upper bound on the root, since $ e\sinh F - F $ is at least $ (e-1)\sinh F $ and at least $ (e-1)F + eF^3/6 $. The function is increasing and convex for $ F > 0 $, so Newton's method converges monotonically from there, even close to $ e = 1 $ where the derivative $ e\cosh F - 1 $ is small near periapsis.
35
+ * - Unlike an ellipse, a hyperbola isn't periodic: $ M_h $ isn't reduced to one turn.
36
+ * - {@link solveKeplerHighEccentricity} also accepts $ e > 1 $, but this solver throws when it doesn't converge instead of returning its last estimate.
37
+ *
38
+ * :::
39
+ *
40
+ * @param Mh - Hyperbolic mean anomaly $ M_h $ in **radians** (finite).
41
+ * @param e - Eccentricity $ e $ (finite, > 1).
42
+ * @param tolerance - Stop when a step is smaller than `tolerance * max(1, |F|)`. Defaults to `1e-14`.
43
+ * @param maxIter - Maximum number of Newton steps. Defaults to `50`.
44
+ * @returns The hyperbolic anomaly $ F $ in **radians**, with the sign of `Mh`.
45
+ * @throws {TypeError} If any input is not a finite number.
46
+ * @throws {RangeError} If `e <= 1`, `tolerance <= 0` or `maxIter < 1`.
47
+ * @throws {Error} If the iteration doesn't converge within `maxIter` steps.
48
+ * @group Kepler Solvers
49
+ *
50
+ * @example
51
+ * ```ts
52
+ * import type { Radians } from '@interstellar-tools/types';
53
+ *
54
+ * const F = solveKeplerHyperbolic(12.66 as Radians, 1.44);
55
+ * // F ≈ 3.087, and 1.44 * sinh(F) - F ≈ 12.66
56
+ * ```
57
+ *
58
+ * @see {@link hyperbolicTimeOfFlight}
59
+ * @see https://en.wikipedia.org/wiki/Hyperbolic_trajectory#Hyperbolic_anomaly Hyperbolic anomaly
60
+ */
61
+ export const solveKeplerHyperbolic = (Mh, e, tolerance = 1e-14, maxIter = 50) => {
62
+ for (const [name, x] of [
63
+ ['Mh', Mh],
64
+ ['e', e],
65
+ ['tolerance', tolerance],
66
+ ['maxIter', maxIter]
67
+ ]) {
68
+ if (!Number.isFinite(x))
69
+ throw new TypeError(`${name} must be a finite number. Received: ${x}`);
70
+ }
71
+ if (e <= 1)
72
+ throw new RangeError(`e must be > 1. Received: ${e}`);
73
+ if (tolerance <= 0)
74
+ throw new RangeError(`tolerance must be > 0. Received: ${tolerance}`);
75
+ if (maxIter < 1)
76
+ throw new RangeError(`maxIter must be >= 1. Received: ${maxIter}`);
77
+ const M = Math.abs(Mh);
78
+ // Start above the root, where Newton's method can't overshoot
79
+ let F = Math.min(Math.asinh(M / (e - 1)), Math.cbrt((6 * M) / e));
80
+ for (let iter = 0; iter < maxIter; iter++) {
81
+ // e sinh F - F - M, written so nothing cancels when e ≈ 1 and F is small
82
+ const f = (e - 1) * F + e * sinhMinusX(F) - M;
83
+ const step = f / (e * Math.cosh(F) - 1);
84
+ F -= step;
85
+ if (Math.abs(step) <= tolerance * Math.max(1, Math.abs(F)))
86
+ return Math.sign(Mh) * F;
87
+ }
88
+ throw new Error(`solveKeplerHyperbolic did not converge in ${maxIter} steps. Received: Mh=${Mh}, e=${e}`);
89
+ };
90
+ //# sourceMappingURL=solve-kepler-hyperbolic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"solve-kepler-hyperbolic.js","sourceRoot":"","sources":["../../../src/categories/kepler/solve-kepler-hyperbolic.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ import type { CwState, Vector3DTupleType } from '@interstellar-tools/types';
2
+ export interface CwTwoImpulseTransferInterface {
3
+ /** First burn, at the start, in m/s (LVLH). */
4
+ dv1: Vector3DTupleType;
5
+ /** Second burn, on arrival, in m/s (LVLH). */
6
+ dv2: Vector3DTupleType;
7
+ }
8
+ /**
9
+ * Compute the **two burns of a Clohessy–Wiltshire rendezvous**: from a relative state to a target state in a given time.
10
+ *
11
+ * $$
12
+ * \mathbf v_0^+ = \Phi_{rv}^{-1}\left(\mathbf r_f - \Phi_{rr}\,\mathbf r_0\right), \quad
13
+ * \Delta\mathbf v_1 = \mathbf v_0^+ - \mathbf v_0, \quad
14
+ * \Delta\mathbf v_2 = \mathbf v_f - \left(\Phi_{vr}\,\mathbf r_0 + \Phi_{vv}\,\mathbf v_0^+\right)
15
+ * $$
16
+ *
17
+ * with the blocks of $ \Phi(t) $ from {@link cwStateTransition}.
18
+ *
19
+ * **Units**
20
+ * - Inputs: states in **m** and **m/s**, `n` in **rad/s**, `t` in **s**.
21
+ * - Output: both burns in **m/s**, as vectors in the LVLH frame.
22
+ *
23
+ * ::: info Notes
24
+ *
25
+ * - The first burn puts the deputy on a path that reaches the target position after `t`; the second matches the target velocity there. For a rendezvous with the chief, the target state is all zeros.
26
+ * - Some transfer times can't be targeted: in the orbital plane, every whole number of orbits ($ nt = 2\pi k $), and out of plane, every half orbit, where the cross-track motion returns to $ \pm z_0 $ whatever the burn. At a half orbit the cross-track burn is zero if the target is already on that path, and otherwise the function throws.
27
+ * - Valid near a circular reference orbit, for small separations.
28
+ *
29
+ * :::
30
+ *
31
+ * @param state0 - Deputy's relative state before the first burn `[x, y, z, xDot, yDot, zDot]` (finite).
32
+ * @param target - State to arrive at `[x, y, z, xDot, yDot, zDot]` (finite); all zeros to rendezvous with the chief.
33
+ * @param n - Mean motion of the circular reference orbit in **rad/s** (finite, > 0).
34
+ * @param t - Transfer time in **s** (finite, > 0).
35
+ * @returns The two burns `dv1` and `dv2` in **m/s**.
36
+ * @throws {TypeError} If any input is not a finite number.
37
+ * @throws {RangeError} If `n <= 0`, `t <= 0`, or the transfer time can't be targeted.
38
+ * @group Manoeuvres
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * import type { CwState } from '@interstellar-tools/types';
43
+ *
44
+ * // 1 km behind the chief, at rest: rendezvous in a quarter of an orbit
45
+ * const n = 0.00113;
46
+ * const { dv1, dv2 } = cwTwoImpulseTransfer(
47
+ * [0, -1000, 0, 0, 0, 0],
48
+ * [0, 0, 0, 0, 0, 0],
49
+ * n,
50
+ * Math.PI / 2 / n
51
+ * );
52
+ * ```
53
+ *
54
+ * @see {@link cwPropagate}
55
+ * @see https://en.wikipedia.org/wiki/Clohessy%E2%80%93Wiltshire_equations Clohessy–Wiltshire equations
56
+ */
57
+ export declare const cwTwoImpulseTransfer: (state0: CwState, target: CwState, n: number, t: number) => CwTwoImpulseTransferInterface;
58
+ //# sourceMappingURL=cw-two-impulse-transfer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cw-two-impulse-transfer.d.ts","sourceRoot":"","sources":["../../../src/categories/manoeuvres/cw-two-impulse-transfer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAK5E,MAAM,WAAW,6BAA6B;IAC5C,+CAA+C;IAC/C,GAAG,EAAE,iBAAiB,CAAC;IACvB,8CAA8C;IAC9C,GAAG,EAAE,iBAAiB,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,OAAO,EACf,QAAQ,OAAO,EACf,GAAG,MAAM,EACT,GAAG,MAAM,KACR,6BA+DF,CAAC"}
@@ -0,0 +1,104 @@
1
+ import { applyMatrix3 } from '../helpers/apply-matrix-3.js';
2
+ import { cwStateTransition } from '../orbits/cw-state-transition.js';
3
+ /**
4
+ * Compute the **two burns of a Clohessy–Wiltshire rendezvous**: from a relative state to a target state in a given time.
5
+ *
6
+ * $$
7
+ * \mathbf v_0^+ = \Phi_{rv}^{-1}\left(\mathbf r_f - \Phi_{rr}\,\mathbf r_0\right), \quad
8
+ * \Delta\mathbf v_1 = \mathbf v_0^+ - \mathbf v_0, \quad
9
+ * \Delta\mathbf v_2 = \mathbf v_f - \left(\Phi_{vr}\,\mathbf r_0 + \Phi_{vv}\,\mathbf v_0^+\right)
10
+ * $$
11
+ *
12
+ * with the blocks of $ \Phi(t) $ from {@link cwStateTransition}.
13
+ *
14
+ * **Units**
15
+ * - Inputs: states in **m** and **m/s**, `n` in **rad/s**, `t` in **s**.
16
+ * - Output: both burns in **m/s**, as vectors in the LVLH frame.
17
+ *
18
+ * ::: info Notes
19
+ *
20
+ * - The first burn puts the deputy on a path that reaches the target position after `t`; the second matches the target velocity there. For a rendezvous with the chief, the target state is all zeros.
21
+ * - Some transfer times can't be targeted: in the orbital plane, every whole number of orbits ($ nt = 2\pi k $), and out of plane, every half orbit, where the cross-track motion returns to $ \pm z_0 $ whatever the burn. At a half orbit the cross-track burn is zero if the target is already on that path, and otherwise the function throws.
22
+ * - Valid near a circular reference orbit, for small separations.
23
+ *
24
+ * :::
25
+ *
26
+ * @param state0 - Deputy's relative state before the first burn `[x, y, z, xDot, yDot, zDot]` (finite).
27
+ * @param target - State to arrive at `[x, y, z, xDot, yDot, zDot]` (finite); all zeros to rendezvous with the chief.
28
+ * @param n - Mean motion of the circular reference orbit in **rad/s** (finite, > 0).
29
+ * @param t - Transfer time in **s** (finite, > 0).
30
+ * @returns The two burns `dv1` and `dv2` in **m/s**.
31
+ * @throws {TypeError} If any input is not a finite number.
32
+ * @throws {RangeError} If `n <= 0`, `t <= 0`, or the transfer time can't be targeted.
33
+ * @group Manoeuvres
34
+ *
35
+ * @example
36
+ * ```ts
37
+ * import type { CwState } from '@interstellar-tools/types';
38
+ *
39
+ * // 1 km behind the chief, at rest: rendezvous in a quarter of an orbit
40
+ * const n = 0.00113;
41
+ * const { dv1, dv2 } = cwTwoImpulseTransfer(
42
+ * [0, -1000, 0, 0, 0, 0],
43
+ * [0, 0, 0, 0, 0, 0],
44
+ * n,
45
+ * Math.PI / 2 / n
46
+ * );
47
+ * ```
48
+ *
49
+ * @see {@link cwPropagate}
50
+ * @see https://en.wikipedia.org/wiki/Clohessy%E2%80%93Wiltshire_equations Clohessy–Wiltshire equations
51
+ */
52
+ export const cwTwoImpulseTransfer = (state0, target, n, t) => {
53
+ for (const [name, state] of [
54
+ ['state0', state0],
55
+ ['target', target]
56
+ ]) {
57
+ for (const x of state)
58
+ if (!Number.isFinite(x))
59
+ throw new TypeError(`${name} must have finite components. Received: ${x}`);
60
+ }
61
+ if (!Number.isFinite(t))
62
+ throw new TypeError(`t must be a finite number. Received: ${t}`);
63
+ if (t <= 0)
64
+ throw new RangeError(`t must be > 0. Received: ${t}`);
65
+ const { rr, rv, vr, vv } = cwStateTransition(n, t);
66
+ const r0 = [state0[0], state0[1], state0[2]];
67
+ const v0 = [state0[3], state0[4], state0[5]];
68
+ const fromR0 = applyMatrix3(rr, r0);
69
+ // Position the first burn's velocity has to cover
70
+ const dx = target[0] - fromR0[0];
71
+ const dy = target[1] - fromR0[1];
72
+ const dz = target[2] - fromR0[2];
73
+ // In-plane: invert the 2×2 block of Φrv
74
+ const [[a, b], [c, d]] = rv;
75
+ const det = a * d - b * c;
76
+ if (Math.abs(det) * n * n <= 1e-10)
77
+ throw new RangeError(`The transfer time is a whole number of orbits (nt = 2πk), which can't be targeted in the orbital plane. Received: nt=${n * t}`);
78
+ const xDot = (d * dx - b * dy) / det;
79
+ const yDot = (-c * dx + a * dy) / det;
80
+ // Out of plane: z(t) = c z0 + (s / n) zDot0
81
+ const sOverN = rv[2][2];
82
+ let zDot;
83
+ if (Math.abs(sOverN) * n > 1e-10) {
84
+ zDot = dz / sOverN;
85
+ }
86
+ else if (Math.abs(dz) <= 1e-9 * Math.max(1, Math.abs(target[2]))) {
87
+ zDot = v0[2];
88
+ }
89
+ else {
90
+ throw new RangeError(`At a half orbit (nt = πk) the cross-track position can't be changed. Received: nt=${n * t}`);
91
+ }
92
+ const v0Plus = [xDot, yDot, zDot];
93
+ const fromR = applyMatrix3(vr, r0);
94
+ const fromV = applyMatrix3(vv, v0Plus);
95
+ return {
96
+ dv1: [xDot - v0[0], yDot - v0[1], zDot - v0[2]],
97
+ dv2: [
98
+ target[3] - (fromR[0] + fromV[0]),
99
+ target[4] - (fromR[1] + fromV[1]),
100
+ target[5] - (fromR[2] + fromV[2])
101
+ ]
102
+ };
103
+ };
104
+ //# sourceMappingURL=cw-two-impulse-transfer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cw-two-impulse-transfer.js","sourceRoot":"","sources":["../../../src/categories/manoeuvres/cw-two-impulse-transfer.ts"],"names":[],"mappings":"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"}