ootk 7.1.0 → 8.0.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/README.md +115 -76
- package/dist/main.cjs +5784 -1806
- package/dist/main.d.cts +3119 -603
- package/dist/main.d.ts +3119 -603
- package/dist/main.js +5734 -1806
- package/package.json +12 -8
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
> An Orbital Object Toolkit in Your Web Browser
|
|
9
9
|
|
|
10
|
-
**ootk** is a collection libraries for doing math related to orbital objects written in TypeScript. **ootk** was
|
|
10
|
+
**ootk** is a collection of libraries for doing math related to orbital objects written in TypeScript. **ootk** was
|
|
11
11
|
developed to simplify the math and let you focus on using the results.
|
|
12
12
|
|
|
13
13
|
Most of the functionality was originally written for [KeepTrack](https://github.com/thkruz/keeptrack.space) and then
|
|
@@ -21,81 +21,118 @@ Install the library with [NPM](https://www.npmjs.com/):
|
|
|
21
21
|
npm i ootk
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
```ts
|
|
27
|
-
import { DetailedSatellite, DetailedSensor, Degrees, Kilometers, SpaceObjectType, TleLine1, TleLine2 } from "ootk";
|
|
28
|
-
|
|
29
|
-
// Using api.keeptrack.space API
|
|
30
|
-
fetch('https://api.keeptrack.space/v1/sat/25544')
|
|
31
|
-
.then((res) => res.json())
|
|
32
|
-
.then((satData) => {
|
|
33
|
-
const satellite = new DetailedSatellite({
|
|
34
|
-
id: satData.id,
|
|
35
|
-
tle1: satData.tle1 as TleLine1,
|
|
36
|
-
tle2: satData.tle2 as TleLine2,
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
// Get the satellite's position at the current time
|
|
40
|
-
const eci = satellite.eci();
|
|
41
|
-
|
|
42
|
-
// Log the satellite's position - y component only
|
|
43
|
-
console.log(eci.position.y);
|
|
44
|
-
|
|
45
|
-
// Access other satellite properties
|
|
46
|
-
console.log(satellite.inclination); // inclination in degrees
|
|
47
|
-
console.log(satellite.eccentricity); // eccentricity
|
|
48
|
-
console.log(satellite.period); // period in minutes
|
|
49
|
-
|
|
50
|
-
// Get LLA (Latitude, Longitude, Altitude)
|
|
51
|
-
const lla = satellite.lla();
|
|
52
|
-
|
|
53
|
-
console.log(lla); // { lat: degrees, lon: degrees, alt: kilometers }
|
|
24
|
+
ootk requires Node.js 20 or later (or any modern browser bundler). It ships as ES modules with a CommonJS
|
|
25
|
+
build and full TypeScript types.
|
|
54
26
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
alt: 0.060966 as Kilometers,
|
|
59
|
-
minAz: 347 as Degrees,
|
|
60
|
-
maxAz: 227 as Degrees,
|
|
61
|
-
minEl: 3 as Degrees,
|
|
62
|
-
maxEl: 85 as Degrees,
|
|
63
|
-
minRng: 0 as Kilometers,
|
|
64
|
-
maxRng: 5556 as Kilometers,
|
|
65
|
-
name: 'Cape Cod',
|
|
66
|
-
type: SpaceObjectType.PHASED_ARRAY_RADAR,
|
|
67
|
-
});
|
|
27
|
+
> **Upgrading from ootk 7?** Version 8 fixes a number of silently wrong results and changes a few API contracts
|
|
28
|
+
> (`mag2db` is now `pow2db`, Lambert `posigrade` is now `shortWay`, zenith field-of-view roll, CDM units and more).
|
|
29
|
+
> Read the [v8 migration guide](./docs/migration-v8.md) before upgrading.
|
|
68
30
|
|
|
69
|
-
|
|
70
|
-
const rae = sensor.rae(satellite);
|
|
71
|
-
|
|
72
|
-
// Log the azimuth from sensor to satellite
|
|
73
|
-
console.log(rae.az);
|
|
74
|
-
|
|
75
|
-
// Check if a satellite is in the sensor's field of view right now
|
|
76
|
-
const isSatInFov = sensor.isSatInFov(satellite);
|
|
77
|
-
|
|
78
|
-
console.log(isSatInFov); // true or false
|
|
79
|
-
|
|
80
|
-
// Calculate passes for a satellite (in 30 second intervals)
|
|
81
|
-
const passes = sensor.calculatePasses(30, satellite);
|
|
82
|
-
|
|
83
|
-
console.log(passes); // Array of pass information
|
|
31
|
+
### Example Usage
|
|
84
32
|
|
|
85
|
-
|
|
86
|
-
|
|
33
|
+
Units are carried in the types. The branded types (`Degrees`, `Radians`, `Kilometers`, `TleLine1`, ...) tell you
|
|
34
|
+
what each parameter expects and make the compiler catch a mix-up: `GroundStation`, sensor and `FieldOfView`
|
|
35
|
+
parameters are in degrees, while lower-level classes such as `Geodetic`, `RAE` and `ClassicalElements` take
|
|
36
|
+
radians. Distances are kilometres throughout.
|
|
87
37
|
|
|
88
|
-
|
|
89
|
-
|
|
38
|
+
```ts
|
|
39
|
+
import {
|
|
40
|
+
Degrees,
|
|
41
|
+
GroundStation,
|
|
42
|
+
Kilometers,
|
|
43
|
+
PassType,
|
|
44
|
+
PhasedArrayRadar,
|
|
45
|
+
Satellite,
|
|
46
|
+
SensorType,
|
|
47
|
+
TleLine1,
|
|
48
|
+
TleLine2,
|
|
49
|
+
} from 'ootk';
|
|
50
|
+
|
|
51
|
+
// A satellite from a TLE. SGP4 is only accurate near the TLE epoch, so use a
|
|
52
|
+
// current TLE (or a date close to its epoch, as here).
|
|
53
|
+
const iss = new Satellite({
|
|
54
|
+
name: 'ISS',
|
|
55
|
+
tle1: '1 25544U 98067A 24028.54545847 .00031576 00000-0 57240-3 0 9991' as TleLine1,
|
|
56
|
+
tle2: '2 25544 51.6418 292.2590 0002595 167.5319 252.0460 15.49326324436741' as TleLine2,
|
|
57
|
+
});
|
|
58
|
+
const date = new Date('2024-01-28T12:00:00Z');
|
|
59
|
+
|
|
60
|
+
console.log(iss.inclination); // deg
|
|
61
|
+
console.log(iss.period); // min
|
|
62
|
+
|
|
63
|
+
// Position: eci() is TEME in km and km/s; lla() is degrees and km. Both return
|
|
64
|
+
// null if SGP4 fails (for example a decayed orbit), so check the result.
|
|
65
|
+
const eci = iss.eci(date);
|
|
66
|
+
const lla = iss.lla(date);
|
|
67
|
+
|
|
68
|
+
if (eci && lla) {
|
|
69
|
+
console.log(eci.position.x, eci.velocity.x);
|
|
70
|
+
console.log(lla.lat, lla.lon, lla.alt);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// A ground site. Latitude and longitude are degrees, altitude km above WGS-84.
|
|
74
|
+
const capeCod = new GroundStation({
|
|
75
|
+
name: 'Cape Cod',
|
|
76
|
+
lat: 41.754785 as Degrees,
|
|
77
|
+
lon: -70.539151 as Degrees,
|
|
78
|
+
alt: 0.060966 as Kilometers,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// Look angles from the site (azimuth and elevation in degrees, range in km).
|
|
82
|
+
const rae = iss.rae(capeCod, date);
|
|
83
|
+
|
|
84
|
+
if (rae) {
|
|
85
|
+
console.log(rae.az, rae.el, rae.rng);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// A sensor is a component attached to a platform. Its field of view is a cone
|
|
89
|
+
// around each face boresight; halfAngle is required.
|
|
90
|
+
const radar = new PhasedArrayRadar({
|
|
91
|
+
id: 1,
|
|
92
|
+
name: 'Cape Cod Radar',
|
|
93
|
+
sensorType: SensorType.PHASED_ARRAY_RADAR,
|
|
94
|
+
beamwidth: 2 as Degrees,
|
|
95
|
+
boresightAz: [47 as Degrees, 167 as Degrees],
|
|
96
|
+
boresightEl: [20 as Degrees, 20 as Degrees],
|
|
97
|
+
fieldOfView: {
|
|
98
|
+
halfAngle: 60 as Degrees,
|
|
99
|
+
minRange: 200 as Kilometers,
|
|
100
|
+
maxRange: 5556 as Kilometers,
|
|
101
|
+
minElevation: 3 as Degrees,
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
capeCod.addSensor(radar);
|
|
106
|
+
radar.setParent(capeCod);
|
|
107
|
+
|
|
108
|
+
console.log(radar.canObserve(iss, date)); // inside the field of view right now?
|
|
109
|
+
|
|
110
|
+
// Pass events over the next 24 hours (1 s steps): ENTER and EXIT look angles.
|
|
111
|
+
const passes = radar.calculatePasses(iss, 24 * 60 * 60, date);
|
|
112
|
+
|
|
113
|
+
for (const pass of passes) {
|
|
114
|
+
if (pass.type === PassType.ENTER) {
|
|
115
|
+
console.log(`Enter ${pass.time.toISOString()} az ${pass.az.toFixed(1)} el ${pass.el.toFixed(1)}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
90
118
|
```
|
|
91
119
|
|
|
120
|
+
More runnable scripts live in [`examples/`](./examples) (orbital elements, coordinate transforms, time systems,
|
|
121
|
+
passes, sensors, observations, Doppler, integrators, IOD, Lambert, maneuvers, conjunction assessment, covariance,
|
|
122
|
+
Sun and Moon). Each one is walked through on the documentation site.
|
|
123
|
+
|
|
92
124
|
## :books: Documentation
|
|
93
125
|
|
|
94
|
-
|
|
126
|
+
The documentation site is built from [`docs/`](./docs) with VitePress (`pnpm run docs:dev`):
|
|
95
127
|
|
|
96
|
-
- **[Getting Started Guide](./docs/getting-started.md)** -
|
|
97
|
-
- **[User Guide](./docs/user-guide.md)** -
|
|
98
|
-
- **[
|
|
128
|
+
- **[Getting Started Guide](./docs/getting-started.md)** - installation and first steps
|
|
129
|
+
- **[User Guide](./docs/user-guide.md)** - reference for the main features
|
|
130
|
+
- **[Advanced Features](./docs/advanced-features-guide.md)** - force models, numerical propagation, covariance,
|
|
131
|
+
conjunction assessment, orbit determination and optimizers
|
|
132
|
+
- **[Lambert and Satellite Integration](./docs/lambert-satellite-integration-guide.md)** - from Lambert solutions to
|
|
133
|
+
propagated satellites
|
|
134
|
+
- **[Migrating to v8](./docs/migration-v8.md)** - every breaking change in 8.0.0, with before/after code
|
|
135
|
+
- **[Documentation Index](./docs/README.md)** - all documentation pages
|
|
99
136
|
|
|
100
137
|
The documentation covers:
|
|
101
138
|
- Installation and setup
|
|
@@ -109,7 +146,7 @@ The documentation covers:
|
|
|
109
146
|
|
|
110
147
|
## :desktop_computer: Building
|
|
111
148
|
|
|
112
|
-
1. Install [Node.js](https://nodejs.org/) and [pnpm](https://pnpm.io/) (`corepack enable pnpm` is enough
|
|
149
|
+
1. Install [Node.js](https://nodejs.org/) and [pnpm](https://pnpm.io/) (`corepack enable pnpm` is enough; the
|
|
113
150
|
required version is pinned by the `packageManager` field in `package.json`);
|
|
114
151
|
|
|
115
152
|
2. Install all required packages by running the following command from repository's root directory:
|
|
@@ -126,12 +163,14 @@ The documentation covers:
|
|
|
126
163
|
|
|
127
164
|
## :gem: Scripts
|
|
128
165
|
|
|
129
|
-
- `build`
|
|
130
|
-
- `
|
|
131
|
-
- `lint
|
|
132
|
-
- `
|
|
133
|
-
- `test` runs
|
|
134
|
-
- `test:
|
|
166
|
+
- `build` bundles `src/main.ts` with tsup into ES module and CommonJS builds (plus type declarations) in `dist`.
|
|
167
|
+
- `typecheck` runs `tsc --noEmit` over `src` and `test`.
|
|
168
|
+
- `lint` lints the `src` directory with [ESLint](https://eslint.org/); `lint:fix` also applies automatic fixes.
|
|
169
|
+
- `test` runs the unit tests with [Vitest](https://vitest.dev/).
|
|
170
|
+
- `test:coverage` runs the unit tests and writes a coverage report.
|
|
171
|
+
- `test:integration` builds the package and runs the integration tests against `dist`.
|
|
172
|
+
- `docs:dev` serves the VitePress documentation site locally; `docs:build` builds it.
|
|
173
|
+
- `bench` builds the package and runs the benchmarks in `benchmark/`.
|
|
135
174
|
|
|
136
175
|
## :man_teacher: Contributing
|
|
137
176
|
|
|
@@ -153,7 +192,7 @@ Make sure that your changes don't break the existing code by running:
|
|
|
153
192
|
pnpm test
|
|
154
193
|
```
|
|
155
194
|
|
|
156
|
-
Check that your code follows the rules
|
|
195
|
+
Check that your code follows the rules in `eslint.config.js`:
|
|
157
196
|
|
|
158
197
|
```bash
|
|
159
198
|
pnpm run lint
|
|
@@ -174,5 +213,5 @@ the previous work of the following:
|
|
|
174
213
|
|
|
175
214
|
## :balance_scale: License
|
|
176
215
|
|
|
177
|
-
I have placed the code under the [AGPL License](LICENSE.
|
|
216
|
+
I have placed the code under the [AGPL License](LICENSE.MD) in order to ensure that good ideas can be shared and that
|
|
178
217
|
the code is open for everyone to use. [Learn more here](https://www.gnu.org/philosophy/philosophy.html).
|