@interstellar-tools/equations 1.0.0 → 1.2.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 (85) 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/helpers/misc.d.ts +18 -0
  14. package/dist/categories/helpers/misc.d.ts.map +1 -1
  15. package/dist/categories/helpers/misc.js +24 -0
  16. package/dist/categories/helpers/misc.js.map +1 -1
  17. package/dist/categories/kepler/solve-kepler-hyperbolic.d.ts +49 -0
  18. package/dist/categories/kepler/solve-kepler-hyperbolic.d.ts.map +1 -0
  19. package/dist/categories/kepler/solve-kepler-hyperbolic.js +90 -0
  20. package/dist/categories/kepler/solve-kepler-hyperbolic.js.map +1 -0
  21. package/dist/categories/manoeuvres/burn-time.d.ts +63 -0
  22. package/dist/categories/manoeuvres/burn-time.d.ts.map +1 -0
  23. package/dist/categories/manoeuvres/burn-time.js +87 -0
  24. package/dist/categories/manoeuvres/burn-time.js.map +1 -0
  25. package/dist/categories/manoeuvres/gravity-loss.d.ts +48 -0
  26. package/dist/categories/manoeuvres/gravity-loss.d.ts.map +1 -0
  27. package/dist/categories/manoeuvres/gravity-loss.js +74 -0
  28. package/dist/categories/manoeuvres/gravity-loss.js.map +1 -0
  29. package/dist/categories/manoeuvres/initial-mass-for-delta-v.d.ts +60 -0
  30. package/dist/categories/manoeuvres/initial-mass-for-delta-v.d.ts.map +1 -0
  31. package/dist/categories/manoeuvres/initial-mass-for-delta-v.js +79 -0
  32. package/dist/categories/manoeuvres/initial-mass-for-delta-v.js.map +1 -0
  33. package/dist/categories/manoeuvres/mass-flow-rate.d.ts +57 -0
  34. package/dist/categories/manoeuvres/mass-flow-rate.d.ts.map +1 -0
  35. package/dist/categories/manoeuvres/mass-flow-rate.js +73 -0
  36. package/dist/categories/manoeuvres/mass-flow-rate.js.map +1 -0
  37. package/dist/categories/manoeuvres/rocket-thrust.d.ts +48 -0
  38. package/dist/categories/manoeuvres/rocket-thrust.d.ts.map +1 -0
  39. package/dist/categories/manoeuvres/rocket-thrust.js +62 -0
  40. package/dist/categories/manoeuvres/rocket-thrust.js.map +1 -0
  41. package/dist/categories/manoeuvres/thrust-to-weight.d.ts +57 -0
  42. package/dist/categories/manoeuvres/thrust-to-weight.d.ts.map +1 -0
  43. package/dist/categories/manoeuvres/thrust-to-weight.js +73 -0
  44. package/dist/categories/manoeuvres/thrust-to-weight.js.map +1 -0
  45. package/dist/categories/orbits/elements-to-state.d.ts +61 -0
  46. package/dist/categories/orbits/elements-to-state.d.ts.map +1 -0
  47. package/dist/categories/orbits/elements-to-state.js +107 -0
  48. package/dist/categories/orbits/elements-to-state.js.map +1 -0
  49. package/dist/categories/orbits/hyperbolic-eccentricity.d.ts +56 -0
  50. package/dist/categories/orbits/hyperbolic-eccentricity.d.ts.map +1 -0
  51. package/dist/categories/orbits/hyperbolic-eccentricity.js +72 -0
  52. package/dist/categories/orbits/hyperbolic-eccentricity.js.map +1 -0
  53. package/dist/categories/orbits/hyperbolic-semi-major-axis.d.ts +53 -0
  54. package/dist/categories/orbits/hyperbolic-semi-major-axis.d.ts.map +1 -0
  55. package/dist/categories/orbits/hyperbolic-semi-major-axis.js +66 -0
  56. package/dist/categories/orbits/hyperbolic-semi-major-axis.js.map +1 -0
  57. package/dist/categories/orbits/hyperbolic-time-of-flight.d.ts +64 -0
  58. package/dist/categories/orbits/hyperbolic-time-of-flight.d.ts.map +1 -0
  59. package/dist/categories/orbits/hyperbolic-time-of-flight.js +86 -0
  60. package/dist/categories/orbits/hyperbolic-time-of-flight.js.map +1 -0
  61. package/dist/categories/orbits/inclination-from-launch-azimuth.d.ts +64 -0
  62. package/dist/categories/orbits/inclination-from-launch-azimuth.d.ts.map +1 -0
  63. package/dist/categories/orbits/inclination-from-launch-azimuth.js +76 -0
  64. package/dist/categories/orbits/inclination-from-launch-azimuth.js.map +1 -0
  65. package/dist/categories/orbits/launch-azimuth-for-inclination.d.ts +71 -0
  66. package/dist/categories/orbits/launch-azimuth-for-inclination.d.ts.map +1 -0
  67. package/dist/categories/orbits/launch-azimuth-for-inclination.js +87 -0
  68. package/dist/categories/orbits/launch-azimuth-for-inclination.js.map +1 -0
  69. package/dist/categories/orbits/rotating-launch-azimuth.d.ts +49 -0
  70. package/dist/categories/orbits/rotating-launch-azimuth.d.ts.map +1 -0
  71. package/dist/categories/orbits/rotating-launch-azimuth.js +65 -0
  72. package/dist/categories/orbits/rotating-launch-azimuth.js.map +1 -0
  73. package/dist/categories/orbits/state-to-elements.d.ts +82 -0
  74. package/dist/categories/orbits/state-to-elements.d.ts.map +1 -0
  75. package/dist/categories/orbits/state-to-elements.js +131 -0
  76. package/dist/categories/orbits/state-to-elements.js.map +1 -0
  77. package/dist/categories/orbits/surface-rotation-speed.d.ts +61 -0
  78. package/dist/categories/orbits/surface-rotation-speed.d.ts.map +1 -0
  79. package/dist/categories/orbits/surface-rotation-speed.js +74 -0
  80. package/dist/categories/orbits/surface-rotation-speed.js.map +1 -0
  81. package/dist/index.d.ts +19 -0
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +19 -0
  84. package/dist/index.js.map +1 -1
  85. 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"}
@@ -69,6 +69,24 @@ export declare const sub: (a: Vector3DTupleType, b: Vector3DTupleType) => Vector
69
69
  * ```
70
70
  */
71
71
  export declare const dot: (a: Vector3DTupleType, b: Vector3DTupleType) => number;
72
+ /**
73
+ * Compute the **cross product** of two 3D vectors.
74
+ *
75
+ * $$
76
+ * \mathbf{a}\times\mathbf{b} = \begin{pmatrix} a_y b_z - a_z b_y \\ a_z b_x - a_x b_z \\ a_x b_y - a_y b_x \end{pmatrix}
77
+ * $$
78
+ *
79
+ * @param a - First vector.
80
+ * @param b - Second vector.
81
+ * @returns Cross product, perpendicular to both (units: product of the input component units).
82
+ * @group Helpers
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * cross([1, 0, 0], [0, 1, 0]); // [0, 0, 1]
87
+ * ```
88
+ */
89
+ export declare const cross: (a: Vector3DTupleType, b: Vector3DTupleType) => Vector3DTupleType;
72
90
  /**
73
91
  * Normalize an angle to the range **[0, 2π)**.
74
92
  *
@@ -1 +1 @@
1
- {"version":3,"file":"misc.d.ts","sourceRoot":"","sources":["../../../src/categories/helpers/misc.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEnE;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,IAAI,GAAI,GAAG,iBAAiB,WAExC,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,KAAK,GAAI,GAAG,iBAAiB,EAAE,GAAG,MAAM,KAAG,iBAEvD,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,GAAG,GACd,GAAG,iBAAiB,EACpB,GAAG,iBAAiB,KACnB,iBAEF,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,GAAG,GAAI,GAAG,iBAAiB,EAAE,GAAG,iBAAiB,WAE7D,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,OAAO,GAAI,GAAG,MAAM,KAAG,MAEnC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,QAAQ,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,EAAE,GAAG,MAAM,WAIvD,CAAC"}
1
+ {"version":3,"file":"misc.d.ts","sourceRoot":"","sources":["../../../src/categories/helpers/misc.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEnE;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,IAAI,GAAI,GAAG,iBAAiB,WAExC,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,KAAK,GAAI,GAAG,iBAAiB,EAAE,GAAG,MAAM,KAAG,iBAEvD,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,GAAG,GACd,GAAG,iBAAiB,EACpB,GAAG,iBAAiB,KACnB,iBAEF,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,GAAG,GAAI,GAAG,iBAAiB,EAAE,GAAG,iBAAiB,WAE7D,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,KAAK,GAChB,GAAG,iBAAiB,EACpB,GAAG,iBAAiB,KACnB,iBAMF,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,OAAO,GAAI,GAAG,MAAM,KAAG,MAEnC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,QAAQ,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,EAAE,GAAG,MAAM,WAIvD,CAAC"}
@@ -77,6 +77,30 @@ export const sub = (a, b) => {
77
77
  export const dot = (a, b) => {
78
78
  return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
79
79
  };
80
+ /**
81
+ * Compute the **cross product** of two 3D vectors.
82
+ *
83
+ * $$
84
+ * \mathbf{a}\times\mathbf{b} = \begin{pmatrix} a_y b_z - a_z b_y \\ a_z b_x - a_x b_z \\ a_x b_y - a_y b_x \end{pmatrix}
85
+ * $$
86
+ *
87
+ * @param a - First vector.
88
+ * @param b - Second vector.
89
+ * @returns Cross product, perpendicular to both (units: product of the input component units).
90
+ * @group Helpers
91
+ *
92
+ * @example
93
+ * ```ts
94
+ * cross([1, 0, 0], [0, 1, 0]); // [0, 0, 1]
95
+ * ```
96
+ */
97
+ export const cross = (a, b) => {
98
+ return [
99
+ a[1] * b[2] - a[2] * b[1],
100
+ a[2] * b[0] - a[0] * b[2],
101
+ a[0] * b[1] - a[1] * b[0]
102
+ ];
103
+ };
80
104
  /**
81
105
  * Normalize an angle to the range **[0, 2π)**.
82
106
  *
@@ -1 +1 @@
1
- {"version":3,"file":"misc.js","sourceRoot":"","sources":["../../../src/categories/helpers/misc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AAGvD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,CAAoB,EAAE,EAAE;IAC3C,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACtC,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,CAAoB,EAAE,CAAS,EAAqB,EAAE;IAC1E,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AACxC,CAAC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,CACjB,CAAoB,EACpB,CAAoB,EACD,EAAE;IACrB,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjD,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,CAAoB,EAAE,CAAoB,EAAE,EAAE;IAChE,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACjD,CAAC,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAS,EAAU,EAAE;IAC3C,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC;AAC1C,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS,EAAE,EAAE;IAC1D,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAEtB,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;AAClC,CAAC,CAAC"}
1
+ {"version":3,"file":"misc.js","sourceRoot":"","sources":["../../../src/categories/helpers/misc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AAGvD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,CAAoB,EAAE,EAAE;IAC3C,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACtC,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,CAAoB,EAAE,CAAS,EAAqB,EAAE;IAC1E,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AACxC,CAAC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,CACjB,CAAoB,EACpB,CAAoB,EACD,EAAE;IACrB,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjD,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,CAAoB,EAAE,CAAoB,EAAE,EAAE;IAChE,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACjD,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CACnB,CAAoB,EACpB,CAAoB,EACD,EAAE;IACrB,OAAO;QACL,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;KAC1B,CAAC;AACJ,CAAC,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAS,EAAU,EAAE;IAC3C,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC;AAC1C,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS,EAAE,EAAE;IAC1D,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAEtB,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;AAClC,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,63 @@
1
+ /**
2
+ * Compute the **burn time** needed for a given delta-v, at constant thrust and mass flow.
3
+ *
4
+ * $$
5
+ * t_b = \frac{m_0 - m_f}{\dot m} = \frac{m_0\, I_{sp}\, g_0}{F}\left(1 - e^{-\Delta v/(I_{sp} g_0)}\right)
6
+ * $$
7
+ *
8
+ * Where:
9
+ * - $ m_0 $ is the mass at ignition (kg)
10
+ * - $ \Delta v $ is the delta-v of the burn (m/s)
11
+ * - $ F $ is the thrust (N)
12
+ * - $ I_{sp} $ is the specific impulse (s)
13
+ * - $ g_0 $ is standard gravity (m/s²)
14
+ *
15
+ * **Units**
16
+ * - Inputs: `m0` in **kg**, `dv` in **m/s**, `F` in **N**, `Isp` in **s**, `g0` in **m/s²**.
17
+ * - Output: $ t_b $ in **s**.
18
+ *
19
+ * ::: info Notes
20
+ *
21
+ * - The propellant used, $ m_0 - m_f $, comes from the rocket equation; the burn time is that mass divided by the {@link massFlowRate}.
22
+ * - Assumes constant thrust and specific impulse. A throttled engine, like Apollo's descent engine, needs the burn split into steps.
23
+ * - `dv = 0` gives a burn time of 0.
24
+ *
25
+ * :::
26
+ *
27
+ * ::: practice Apollo 11's lunar module, leaving the Moon
28
+ *
29
+ * **439 s**
30
+ *
31
+ * _Ascent stage, 4 888 kg, for 1 850.2 m/s_
32
+ *
33
+ * The flown burn took 434.9 s, 1% less: the thrust and specific impulse used here are the pre-flight predictions.
34
+ *
35
+ * ```ts
36
+ * burnTime(4888, 1850.2, 15_409, 309); // ≈ 439.3 s
37
+ * ```
38
+ *
39
+ * :::
40
+ *
41
+ * @param m0 - Mass at ignition $ m_0 $ in **kg** (finite, > 0).
42
+ * @param dv - Delta-v of the burn $ \Delta v $ in **m/s** (finite, >= 0).
43
+ * @param F - Thrust $ F $ in **N** (finite, > 0).
44
+ * @param Isp - Specific impulse $ I_{sp} $ in **seconds** (finite, > 0).
45
+ * @param g0 - Standard gravity $ g_0 $ in **m/s²** (finite, > 0). Defaults to `9.80665`.
46
+ * @returns Burn time $ t_b $ in **s**.
47
+ * @throws {TypeError} If any input is not a finite number.
48
+ * @throws {RangeError} If `m0 <= 0`, `dv < 0`, `F <= 0`, `Isp <= 0` or `g0 <= 0`.
49
+ * @group Manoeuvres
50
+ *
51
+ * @example
52
+ * ```ts
53
+ * // A 1200 kg spacecraft, 500 m/s with a 400 N engine at Isp = 320 s
54
+ * const t = burnTime(1200, 500, 400, 320);
55
+ * // t ≈ 1200 * 3138.1 / 400 * (1 - e^(-500/3138.1)) ≈ 1387 s
56
+ * ```
57
+ *
58
+ * @see {@link massFlowRate}
59
+ * @see {@link rocketDeltaVFromIsp}
60
+ * @see https://en.wikipedia.org/wiki/Tsiolkovsky_rocket_equation Tsiolkovsky rocket equation
61
+ */
62
+ export declare const burnTime: (m0: number, dv: number, F: number, Isp: number, g0?: number) => number;
63
+ //# sourceMappingURL=burn-time.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"burn-time.d.ts","sourceRoot":"","sources":["../../../src/categories/manoeuvres/burn-time.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AACH,eAAO,MAAM,QAAQ,GACnB,IAAI,MAAM,EACV,IAAI,MAAM,EACV,GAAG,MAAM,EACT,KAAK,MAAM,EACX,WAAY,KACX,MA0BF,CAAC"}