space-data-module-sdk 0.8.15 → 0.8.17
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/bin/space-data-module.js +24 -6
- package/docs/_shell/consumer-assets.html +5 -0
- package/docs/browser-wasmedge-isomorphic.html +261 -0
- package/docs/byo-wasm-quickstart.html +226 -0
- package/docs/byo-wasm-quickstart.md +204 -0
- package/docs/conformance.html +162 -0
- package/docs/conformance.md +20 -4
- package/docs/emception-shared-memory-verdict.md +209 -0
- package/docs/events-abi.html +313 -0
- package/docs/events-abi.md +530 -0
- package/docs/families/analytics.html +178 -0
- package/docs/families/analytics.md +104 -0
- package/docs/families/attitude.html +157 -0
- package/docs/families/attitude.md +36 -0
- package/docs/families/behavior.html +157 -0
- package/docs/families/behavior.md +36 -0
- package/docs/families/breakup.html +157 -0
- package/docs/families/breakup.md +36 -0
- package/docs/families/conjunction.html +186 -0
- package/docs/families/conjunction.md +121 -0
- package/docs/families/data-source.html +323 -0
- package/docs/families/effects.html +157 -0
- package/docs/families/effects.md +36 -0
- package/docs/families/environment.html +170 -0
- package/docs/families/environment.md +73 -0
- package/docs/families/estimation.html +192 -0
- package/docs/families/estimation.md +158 -0
- package/docs/families/gnc.html +157 -0
- package/docs/families/gnc.md +36 -0
- package/docs/families/maneuver.html +209 -0
- package/docs/families/maneuver.md +206 -0
- package/docs/families/obstruction.html +191 -0
- package/docs/families/obstruction.md +96 -0
- package/docs/families/propagator.html +347 -0
- package/docs/families/propulsion.html +157 -0
- package/docs/families/propulsion.md +36 -0
- package/docs/families/reentry.html +157 -0
- package/docs/families/reentry.md +36 -0
- package/docs/families/rf.html +193 -0
- package/docs/families/rf.md +136 -0
- package/docs/families/scheduler.html +157 -0
- package/docs/families/scheduler.md +36 -0
- package/docs/families/sensor.html +157 -0
- package/docs/families/sensor.md +36 -0
- package/docs/families/signature.html +157 -0
- package/docs/families/signature.md +36 -0
- package/docs/flatsql-host-contract.html +176 -0
- package/docs/flatsql-streaming-standard.html +375 -0
- package/docs/gpu-module-abi.html +233 -0
- package/docs/harness-family-matrix.md +135 -0
- package/docs/index.html +216 -85
- package/docs/isomorphic-pthreads.html +228 -0
- package/docs/isomorphic-pthreads.md +84 -0
- package/docs/isomorphic-sdn-runtime-plan.html +274 -0
- package/docs/language-runtime-matrix.html +182 -0
- package/docs/llms.txt +86 -0
- package/docs/module-bundle-runtime-plan.html +146 -0
- package/docs/module-publication-standard.html +503 -0
- package/docs/node-red-default-node-parity.html +201 -0
- package/docs/propagator-abi.md +97 -12
- package/docs/protect-and-sign.html +181 -0
- package/docs/protect-and-sign.md +120 -0
- package/docs/protocol-installation.html +296 -0
- package/docs/provider-access-abi.md +25 -0
- package/docs/publication-submission.html +158 -0
- package/docs/publication-submission.md +78 -0
- package/docs/secrets-capability.html +206 -0
- package/docs/styles.css +860 -167
- package/docs/testing-harness.html +408 -0
- package/docs/tri-runtime-parity-gate.html +182 -0
- package/docs/tri-runtime-parity.html +203 -0
- package/include/orbpro/orbpro_estimation_abi.h +883 -0
- package/include/orbpro/orbpro_event_runner.h +951 -0
- package/include/orbpro/orbpro_events_abi.h +565 -0
- package/include/orbpro/orbpro_propagator_abi.h +75 -0
- package/package.json +13 -4
- package/schemas/orbpro/Estimation.fbs +244 -0
- package/schemas/orbpro/Events.fbs +501 -0
- package/schemas/orbpro/Propagator.fbs +136 -9
- package/schemas/orbpro/reference-frame-crosswalk.json +108 -0
- package/schemas/orbpro/reference-frame.lock.json +98 -0
- package/src/browser.js +13 -0
- package/src/conformance/estimationReference.js +81 -0
- package/src/conformance/estimationSuite.js +134 -0
- package/src/conformance/index.js +39 -2
- package/src/generated/orbpro/events-abi.js +206 -0
- package/src/generated/orbpro/events-abi.ts +319 -0
- package/src/generated/orbpro/propagator/reference-frame.js +17 -0
- package/src/generated/orbpro/propagator/reference-frame.ts +91 -1
- package/src/generated/orbpro/propagator-abi.js +38 -0
- package/src/generated/orbpro/propagator-abi.ts +67 -0
- package/src/generated/spacedatastandards/plg/CCT.d.ts +94 -0
- package/src/generated/spacedatastandards/plg/CCT.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/CCT.js +208 -0
- package/src/generated/spacedatastandards/plg/CCT.ts +281 -0
- package/src/generated/spacedatastandards/plg/CCTCategory.d.ts +98 -0
- package/src/generated/spacedatastandards/plg/CCTCategory.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/CCTCategory.js +177 -0
- package/src/generated/spacedatastandards/plg/CCTCategory.ts +269 -0
- package/src/generated/spacedatastandards/plg/CCTCategoryRollup.d.ts +54 -0
- package/src/generated/spacedatastandards/plg/CCTCategoryRollup.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/CCTCategoryRollup.js +106 -0
- package/src/generated/spacedatastandards/plg/CCTCategoryRollup.ts +144 -0
- package/src/generated/spacedatastandards/plg/PLG.d.ts +46 -2
- package/src/generated/spacedatastandards/plg/PLG.d.ts.map +1 -1
- package/src/generated/spacedatastandards/plg/PLG.js +78 -5
- package/src/generated/spacedatastandards/plg/PLG.ts +90 -5
- package/src/generated/spacedatastandards/plg/capabilityClass.d.ts +181 -0
- package/src/generated/spacedatastandards/plg/capabilityClass.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/capabilityClass.js +183 -0
- package/src/generated/spacedatastandards/plg/capabilityClass.ts +208 -0
- package/src/generated/spacedatastandards/plg/main.d.ts +4 -0
- package/src/generated/spacedatastandards/plg/main.d.ts.map +1 -1
- package/src/generated/spacedatastandards/plg/main.js +4 -0
- package/src/generated/spacedatastandards/plg/main.ts +4 -0
- package/src/generated/spacedatastandards/plg/pluginCategory.d.ts +40 -2
- package/src/generated/spacedatastandards/plg/pluginCategory.d.ts.map +1 -1
- package/src/generated/spacedatastandards/plg/pluginCategory.js +40 -2
- package/src/generated/spacedatastandards/plg/pluginCategory.ts +40 -2
- package/src/host/browserModuleHarness.js +8 -0
- package/src/host/wasiThreadHost.js +189 -14
- package/src/index.d.ts +18 -1
- package/src/standards/sharedCatalog.js +7 -0
- package/src/transport/index.js +16 -0
- package/src/transport/records.js +1015 -3
- package/templates/estimation-module/README.md +24 -0
- package/templates/estimation-module/build.mjs +32 -0
- package/templates/estimation-module/package.json +12 -0
- package/templates/estimation-module/plugin-manifest.json +34 -0
- package/templates/estimation-module/src/reference_estimation.cpp +53 -0
|
@@ -41,31 +41,94 @@ attribute "abi_c_prefix";
|
|
|
41
41
|
/// enum field. Writing these by hand is how padding bytes go stale.
|
|
42
42
|
attribute "abi_c_helper_prefix";
|
|
43
43
|
|
|
44
|
-
// !!
|
|
45
|
-
//
|
|
46
|
-
//
|
|
44
|
+
// !! FIVE INCOMPATIBLE `ReferenceFrame` VOCABULARIES CROSS THIS SEAM, PLUS AN
|
|
45
|
+
// !! AXIS-TYPE VOCABULARY THAT IS NOT A ReferenceFrame AT ALL !!
|
|
46
|
+
// This is the `orbpro.propagator` one, and it is the ONE that crosses the ABI.
|
|
47
|
+
// The NUMERIC values below are NOT interchangeable with any of the others;
|
|
48
|
+
// translate by NAMED TOKEN at every seam.
|
|
47
49
|
//
|
|
48
|
-
// (A) orbpro.propagator (THIS) TEME=0 J2000=1 ICRF=2 ECEF=3 MCI=4 MCMF=5
|
|
50
|
+
// (A) orbpro.propagator (THIS) TEME=0 J2000=1 ICRF=2 ECEF=3 MCI=4 MCMF=5,
|
|
51
|
+
// then the appended axis roster at 6+
|
|
49
52
|
// (B) orbpro.plugins ECI=0 ECEF=1 TEME=2 ICRF=3
|
|
50
53
|
// (PropagatorState.fbs / "PRST" — the wire the compiled sgp4, hpop,
|
|
51
54
|
// conjunction-assessment and sensor-shader modules already emit)
|
|
52
|
-
// (C)
|
|
55
|
+
// (C) OrbPro engine ReferenceFrame.js — NINE members, not two:
|
|
56
|
+
// FIXED=0 INERTIAL=1 TEME=2 VVLH=3 ENU=4 NED=5 NEU=6 RIC=7 LVLH=8
|
|
57
|
+
// (verified on OrbPro 417320c5c5. The long-standing claim in this block
|
|
58
|
+
// that it was "Cesium.ReferenceFrame FIXED=0 INERTIAL=1" was stale, and
|
|
59
|
+
// stale in the direction that mattered: it hid seven live members.)
|
|
53
60
|
// (D) ConjunctionCommon.fbs ECI=1
|
|
61
|
+
// (E) foundation/frames `AxisType` (space-data-network-modules) — an
|
|
62
|
+
// ORIENTATION RULE roster, mirroring SDS `rfmAxisType`. It is not a
|
|
63
|
+
// ReferenceFrame and must never be numerically equated with one: a
|
|
64
|
+
// coordinate system is an axis set AND an origin, and this enum carries
|
|
65
|
+
// no origin.
|
|
54
66
|
//
|
|
55
67
|
// ECI==0, TEME==0 and FIXED==0 all collide, and ECEF is 1 in (B) but 3 here.
|
|
56
68
|
// (B)'s values are frozen by compiled WASM artifacts in the field, so
|
|
57
69
|
// collapsing (A) and (B) is a wire break, not a Wave-0 edit — see
|
|
58
|
-
// graph/tasks/sdk-reference-frame-enum-unification.md
|
|
59
|
-
// for a correct seam is
|
|
70
|
+
// graph/tasks/sdk-reference-frame-enum-unification.md, which also owns the
|
|
71
|
+
// (A)-vs-(C) inversion at 0/1. The reference pattern for a correct seam is
|
|
72
|
+
// propagator.hpop/index.js createSourceFromState.
|
|
60
73
|
//
|
|
61
|
-
//
|
|
74
|
+
// The crosswalk between all of these is DATA, in
|
|
75
|
+
// schemas/orbpro/reference-frame-crosswalk.json, and
|
|
76
|
+
// scripts/check-reference-frame-uniqueness.mjs holds it to this enum.
|
|
77
|
+
//
|
|
78
|
+
// Ruling: graph/findings/official-harness-shapes.md §4.2 / §8.2; Janus consult
|
|
79
|
+
// 2026-08-30 (gmat-08-frames-and-state-representations).
|
|
80
|
+
//
|
|
81
|
+
// VALUES 0-5 ARE FROZEN AND ARE NEVER RENUMBERED. New members are APPENDED.
|
|
82
|
+
// ECEF/MCI/MCMF are body-bound legacy instances of the generic pair at 11/12 —
|
|
83
|
+
// ECEF is BODY_FIXED about the Earth, MCI is BODY_INERTIAL about Mars, MCMF is
|
|
84
|
+
// BODY_FIXED about Mars. They are retained, and the generic members are NOT a
|
|
85
|
+
// second spelling of them.
|
|
62
86
|
enum ReferenceFrame : ubyte (abi, abi_c_name: "OrbProReferenceFrame", abi_c_prefix: "ORBPRO_FRAME_") {
|
|
63
87
|
TEME = 0,
|
|
64
88
|
J2000 = 1,
|
|
65
89
|
ICRF = 2,
|
|
66
90
|
ECEF = 3,
|
|
67
91
|
MCI = 4,
|
|
68
|
-
MCMF = 5
|
|
92
|
+
MCMF = 5,
|
|
93
|
+
/// Mean ecliptic and equinox of J2000. (The mean EQUATOR and equinox of
|
|
94
|
+
/// J2000 is J2000 = 1 and is not repeated here.)
|
|
95
|
+
MJ2000EC = 6,
|
|
96
|
+
/// Mean equator of date.
|
|
97
|
+
MOD = 7,
|
|
98
|
+
/// True equator of date.
|
|
99
|
+
TOD = 8,
|
|
100
|
+
/// Mean ecliptic of date.
|
|
101
|
+
MOE = 9,
|
|
102
|
+
/// True ecliptic of date.
|
|
103
|
+
TOE = 10,
|
|
104
|
+
/// Axes rotating with a named body, per its published rotation elements.
|
|
105
|
+
BODY_FIXED = 11,
|
|
106
|
+
/// Non-rotating axes on a named body's equator and prime meridian.
|
|
107
|
+
BODY_INERTIAL = 12,
|
|
108
|
+
/// Axes built from the relative geometry of two named objects. The three
|
|
109
|
+
/// live RTN triads — RIC, RSW and RTN — are THIS member with an axes spec,
|
|
110
|
+
/// not three members; so are LVLH and VVLH.
|
|
111
|
+
OBJECT_REFERENCED = 13,
|
|
112
|
+
/// Axes built by aligning one vector and constraining a second.
|
|
113
|
+
LOCAL_ALIGNED_CONSTRAINED = 14,
|
|
114
|
+
/// A named body's equatorial plane at the epoch.
|
|
115
|
+
EQUATOR = 15,
|
|
116
|
+
/// Solar-ecliptic magnetospheric (GSE).
|
|
117
|
+
GSE = 16,
|
|
118
|
+
/// Solar magnetospheric (GSM).
|
|
119
|
+
GSM = 17,
|
|
120
|
+
/// Local horizon axes at a surface site.
|
|
121
|
+
TOPOCENTRIC = 18,
|
|
122
|
+
/// Axes fixed by a body's spin axis and its direction to the Sun.
|
|
123
|
+
BODY_SPIN_SUN = 19,
|
|
124
|
+
/// Axes declared by a loaded ephemeris/orientation kernel.
|
|
125
|
+
SPICE_DEFINED = 20,
|
|
126
|
+
/// LEGACY, retained and NAMED rather than left implicit: mean equator of
|
|
127
|
+
/// date on the IAU-76/FK5 theory. Differs from MOD at the milliarcsecond
|
|
128
|
+
/// level; the two are not interchangeable.
|
|
129
|
+
MOD_FK5 = 21,
|
|
130
|
+
/// LEGACY, retained and NAMED: true equator of date on IAU-76/FK5.
|
|
131
|
+
TOD_FK5 = 22
|
|
69
132
|
}
|
|
70
133
|
|
|
71
134
|
/// StateVector.flags is a BITFIELD carrying any OR-combination of these, so it
|
|
@@ -102,6 +165,70 @@ enum PropagatorSourceKind : ubyte {
|
|
|
102
165
|
SDP8 = 12
|
|
103
166
|
}
|
|
104
167
|
|
|
168
|
+
/// The negative return codes every propagator export shares.
|
|
169
|
+
///
|
|
170
|
+
/// These were documented in docs/propagator-abi.md and declared NOWHERE, so
|
|
171
|
+
/// every module hand-typed them as literals and the contract lived only in
|
|
172
|
+
/// prose. A propagator that returns -1 for everything is unconformable — the
|
|
173
|
+
/// host cannot tell a bad entity index from an uninitialized module, so it
|
|
174
|
+
/// cannot place the failure on the degradation ladder — and the cheapest way
|
|
175
|
+
/// to end up there is having no names to return.
|
|
176
|
+
///
|
|
177
|
+
/// VALUES ARE FROZEN. New classes are appended downward.
|
|
178
|
+
enum ErrorCode : byte (abi, abi_c_name: "OrbProPropagatorError", abi_c_prefix: "ORBPRO_PROP_") {
|
|
179
|
+
OK = 0,
|
|
180
|
+
/// No elements or ephemeris ingested yet.
|
|
181
|
+
NOT_INITIALIZED = -1,
|
|
182
|
+
/// Entity index at or beyond the entity count.
|
|
183
|
+
BAD_ENTITY_INDEX = -2,
|
|
184
|
+
/// The caller passed a null output pointer.
|
|
185
|
+
NULL_OUTPUT = -3,
|
|
186
|
+
/// Malformed or short input buffer.
|
|
187
|
+
BAD_INPUT = -4,
|
|
188
|
+
/// The solve failed to converge.
|
|
189
|
+
NOT_CONVERGED = -5,
|
|
190
|
+
/// The elements describe no closed orbit, or the result is not a number.
|
|
191
|
+
UNPHYSICAL = -6,
|
|
192
|
+
/// The ephemeris container is not one this module reads, or AUTO could not
|
|
193
|
+
/// identify it, or its declared frame has no member on the ReferenceFrame
|
|
194
|
+
/// roster.
|
|
195
|
+
UNSUPPORTED_FORMAT = -7,
|
|
196
|
+
/// The requested epoch lies outside every segment the loaded ephemeris
|
|
197
|
+
/// covers. A refusal, never a silent extrapolation: a caller cannot detect
|
|
198
|
+
/// an extrapolated state from the value alone.
|
|
199
|
+
EPOCH_OUT_OF_RANGE = -8
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/// The container an ephemeris-driven propagator was handed on
|
|
203
|
+
/// `plugin_init_ephemeris`. A format is DATA, not identity: one ephemeris
|
|
204
|
+
/// provider reads every member below behind this discriminator rather than
|
|
205
|
+
/// shipping one artifact per container, because the interpolation, the time
|
|
206
|
+
/// scale handling and the frame rotation are shared and splitting them
|
|
207
|
+
/// re-creates the five-mirror drift this file exists to end.
|
|
208
|
+
///
|
|
209
|
+
/// AUTO is the honest default: every container here is self-identifying in its
|
|
210
|
+
/// first bytes (`DAF/SPK ` / `NAIF/DAF`, the OEM version keyword, the STK
|
|
211
|
+
/// `stk.v.` banner, the SP3 `#d` line, the Code-500 fixed header block), so a
|
|
212
|
+
/// caller that does not know what it fetched says so rather than guessing. A
|
|
213
|
+
/// module that cannot identify the bytes returns UNSUPPORTED_FORMAT; it never
|
|
214
|
+
/// falls back to a default container.
|
|
215
|
+
///
|
|
216
|
+
/// VALUES ARE FROZEN AND ARE NEVER RENUMBERED. New containers are APPENDED.
|
|
217
|
+
enum EphemerisFormat : ubyte (abi, abi_c_name: "OrbProEphemerisFormat", abi_c_prefix: "ORBPRO_EPHEM_FORMAT_") {
|
|
218
|
+
/// Identify the container from its own leading bytes.
|
|
219
|
+
AUTO = 0,
|
|
220
|
+
/// CCSDS Orbit Ephemeris Message, keyword-value notation.
|
|
221
|
+
CCSDS_OEM_KVN = 1,
|
|
222
|
+
/// NAIF Double Precision Array File carrying SPK segments.
|
|
223
|
+
SPK_DAF = 2,
|
|
224
|
+
/// Fixed-record binary ephemeris, 500-word logical records.
|
|
225
|
+
CODE500 = 3,
|
|
226
|
+
/// Ephemeris interchange text with a scenario epoch and typed data blocks.
|
|
227
|
+
STK_EPHEMERIS = 4,
|
|
228
|
+
/// Precise orbit product, revision d.
|
|
229
|
+
SP3_D = 5
|
|
230
|
+
}
|
|
231
|
+
|
|
105
232
|
/// Orbital state vector — 64 bytes, 8-byte aligned. Mirrors
|
|
106
233
|
/// `OrbProStateVector` in orbpro-integration/sdk/include/orbpro_propagator.h
|
|
107
234
|
/// byte for byte:
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
{
|
|
2
|
+
"note": "Every ReferenceFrame-shaped vocabulary that crosses a seam with the orbpro.propagator ABI enum, and how each of its members maps ONTO that enum BY NAMED TOKEN. Numeric identity is never asserted across repositories: ECI==0, TEME==0 and FIXED==0 all collide, and ECEF is 1 in orbpro.plugins but 3 in the ABI. scripts/check-reference-frame-uniqueness.mjs holds this file and schemas/orbpro/Propagator.fbs to each other, and re-reads any listed source that is present on disk.",
|
|
3
|
+
"authority": "schemas/orbpro/Propagator.fbs :: enum ReferenceFrame",
|
|
4
|
+
"vocabularies": [
|
|
5
|
+
{
|
|
6
|
+
"id": "orbpro.plugins",
|
|
7
|
+
"description": "PropagatorState.fbs / \"PRST\" \u2014 the wire the compiled sgp4, hpop, conjunction-assessment and sensor-shader modules already emit. Its values are FROZEN by artifacts in the field; collapsing it into the ABI enum is a wire break, tracked as sdk-reference-frame-enum-unification.",
|
|
8
|
+
"repo": "space-data-network-modules",
|
|
9
|
+
"source": "propagator/sgp4/schemas/PropagatorState.fbs",
|
|
10
|
+
"members": {
|
|
11
|
+
"ECI": "ICRF",
|
|
12
|
+
"ECEF": "ECEF",
|
|
13
|
+
"TEME": "TEME",
|
|
14
|
+
"ICRF": "ICRF"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"id": "orbpro.engine",
|
|
19
|
+
"description": "The OrbPro engine's ReferenceFrame.js. NINE members, not the two this SDK's comment block claimed until 2026-08-30. FIXED/INERTIAL are INVERTED against the ABI's 0/1 \u2014 a live semantic difference, not a numbering accident \u2014 and reconciling that is sdk-reference-frame-enum-unification's job, not this crosswalk's. The four local orbital triads collapse onto OBJECT_REFERENCED with an axes spec.",
|
|
20
|
+
"repo": "OrbPro",
|
|
21
|
+
"source": "packages/engine/Source/Core/ReferenceFrame.js",
|
|
22
|
+
"members": {
|
|
23
|
+
"FIXED": "ECEF",
|
|
24
|
+
"INERTIAL": "ICRF",
|
|
25
|
+
"TEME": "TEME",
|
|
26
|
+
"VVLH": "OBJECT_REFERENCED",
|
|
27
|
+
"ENU": "TOPOCENTRIC",
|
|
28
|
+
"NED": "TOPOCENTRIC",
|
|
29
|
+
"NEU": "TOPOCENTRIC",
|
|
30
|
+
"RIC": "OBJECT_REFERENCED",
|
|
31
|
+
"LVLH": "OBJECT_REFERENCED"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"id": "orbpro.conjunction",
|
|
36
|
+
"description": "ConjunctionCommon.fbs, carried by the conjunction module.",
|
|
37
|
+
"repo": "space-data-network-modules",
|
|
38
|
+
"source": "analysis/conjunction-assessment/schemas/ConjunctionCommon.fbs",
|
|
39
|
+
"members": {
|
|
40
|
+
"UNKNOWN": null,
|
|
41
|
+
"ECI": "ICRF",
|
|
42
|
+
"ECEF": "ECEF",
|
|
43
|
+
"TEME": "TEME",
|
|
44
|
+
"ICRF": "ICRF"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"id": "modules.foundation.frames",
|
|
49
|
+
"description": "foundation/frames AxisType, mirroring SDS rfmAxisType. It is an ORIENTATION RULE roster and carries no origin, so it is not a ReferenceFrame; the mapping below is the axis half only, and a consumer still needs the RFMOrigin to have a coordinate system.",
|
|
50
|
+
"repo": "space-data-network-modules",
|
|
51
|
+
"source": "foundation/frames/src/axis_engine.hpp",
|
|
52
|
+
"members": {
|
|
53
|
+
"UNSPECIFIED": null,
|
|
54
|
+
"MJ2000EQ": "J2000",
|
|
55
|
+
"MJ2000EC": "MJ2000EC",
|
|
56
|
+
"ICRF": "ICRF",
|
|
57
|
+
"TEME": "TEME",
|
|
58
|
+
"MOD": "MOD",
|
|
59
|
+
"TOD": "TOD",
|
|
60
|
+
"MOE": "MOE",
|
|
61
|
+
"TOE": "TOE",
|
|
62
|
+
"BODY_FIXED": "BODY_FIXED",
|
|
63
|
+
"BODY_INERTIAL": "BODY_INERTIAL",
|
|
64
|
+
"OBJECT_REFERENCED": "OBJECT_REFERENCED",
|
|
65
|
+
"LOCAL_ALIGNED_CONSTRAINED": "LOCAL_ALIGNED_CONSTRAINED",
|
|
66
|
+
"EQUATOR": "EQUATOR",
|
|
67
|
+
"GSE": "GSE",
|
|
68
|
+
"GSM": "GSM",
|
|
69
|
+
"TOPOCENTRIC": "TOPOCENTRIC",
|
|
70
|
+
"BODY_SPIN_SUN": "BODY_SPIN_SUN",
|
|
71
|
+
"SPICE_DEFINED": "SPICE_DEFINED",
|
|
72
|
+
"MOD_FK5": "MOD_FK5",
|
|
73
|
+
"TOD_FK5": "TOD_FK5",
|
|
74
|
+
"ITRF": "ECEF"
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"id": "modules.hpop.coords",
|
|
79
|
+
"description": "The HPOP propagator's internal chain vocabulary.",
|
|
80
|
+
"repo": "space-data-network-modules",
|
|
81
|
+
"source": "propagator/hpop/lib/coords_types.h",
|
|
82
|
+
"members": {
|
|
83
|
+
"TEME": "TEME",
|
|
84
|
+
"GCRF": "ICRF",
|
|
85
|
+
"ITRF": "ECEF",
|
|
86
|
+
"J2000": "J2000",
|
|
87
|
+
"ECEF": "ECEF",
|
|
88
|
+
"TOD": "TOD",
|
|
89
|
+
"MOD": "MOD"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
],
|
|
93
|
+
"rtnConvention": {
|
|
94
|
+
"abiMember": "OBJECT_REFERENCED",
|
|
95
|
+
"note": "The three live RTN triads collapse to ONE ABI member plus an axes spec. RIC, RSW and RTN name the SAME triad (x radial, z orbit normal, y completing); LVLH and VVLH are relabellings of it produced by naming a different primary. None of them is a separate ReferenceFrame, and adding a second RTN-named ABI member is a defect this check refuses.",
|
|
96
|
+
"aliases": [
|
|
97
|
+
"RIC",
|
|
98
|
+
"RSW",
|
|
99
|
+
"RTN",
|
|
100
|
+
"LVLH",
|
|
101
|
+
"VVLH",
|
|
102
|
+
"QSW",
|
|
103
|
+
"NTW",
|
|
104
|
+
"TNW",
|
|
105
|
+
"UVW"
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
{
|
|
2
|
+
"note": "The committed numbering of the ONE ReferenceFrame enum that crosses the ABI seam. scripts/check-reference-frame-uniqueness.mjs holds schemas/orbpro/Propagator.fbs to this file: values 0-5 are FROZEN and no member may ever be renamed, renumbered or removed. Appending a member means appending a row here in the same commit.",
|
|
3
|
+
"frozenThrough": 5,
|
|
4
|
+
"members": [
|
|
5
|
+
{
|
|
6
|
+
"name": "TEME",
|
|
7
|
+
"value": 0
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"name": "J2000",
|
|
11
|
+
"value": 1
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "ICRF",
|
|
15
|
+
"value": 2
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "ECEF",
|
|
19
|
+
"value": 3
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"name": "MCI",
|
|
23
|
+
"value": 4
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"name": "MCMF",
|
|
27
|
+
"value": 5
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"name": "MJ2000EC",
|
|
31
|
+
"value": 6
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"name": "MOD",
|
|
35
|
+
"value": 7
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"name": "TOD",
|
|
39
|
+
"value": 8
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"name": "MOE",
|
|
43
|
+
"value": 9
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"name": "TOE",
|
|
47
|
+
"value": 10
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"name": "BODY_FIXED",
|
|
51
|
+
"value": 11
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"name": "BODY_INERTIAL",
|
|
55
|
+
"value": 12
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"name": "OBJECT_REFERENCED",
|
|
59
|
+
"value": 13
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"name": "LOCAL_ALIGNED_CONSTRAINED",
|
|
63
|
+
"value": 14
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"name": "EQUATOR",
|
|
67
|
+
"value": 15
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"name": "GSE",
|
|
71
|
+
"value": 16
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"name": "GSM",
|
|
75
|
+
"value": 17
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"name": "TOPOCENTRIC",
|
|
79
|
+
"value": 18
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"name": "BODY_SPIN_SUN",
|
|
83
|
+
"value": 19
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"name": "SPICE_DEFINED",
|
|
87
|
+
"value": 20
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"name": "MOD_FK5",
|
|
91
|
+
"value": 21
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"name": "TOD_FK5",
|
|
95
|
+
"value": 22
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
}
|
package/src/browser.js
CHANGED
|
@@ -29,6 +29,19 @@ export {
|
|
|
29
29
|
zeroWasmBytes,
|
|
30
30
|
isSharedArrayBufferLike,
|
|
31
31
|
} from "./host/browserModuleHarness.js";
|
|
32
|
+
// The wasi-threads BROWSER WORKER ANCHOR. A bundling consumer MUST tell the SDK
|
|
33
|
+
// where its build serves the host worker chain from — `import.meta.url` inside a
|
|
34
|
+
// bundle points at the bundle, not at the package layout, and the worker 404s
|
|
35
|
+
// (fail-loud: WasiThreadWorkerUnreachableError). Either call
|
|
36
|
+
// `setBrowserWasiThreadWorkerBase(...)` once in the host shim, or pass
|
|
37
|
+
// `wasiThreadWorkerBaseUrl` to `createBrowserModuleHarness`.
|
|
38
|
+
export {
|
|
39
|
+
setBrowserWasiThreadWorkerBase,
|
|
40
|
+
getBrowserWasiThreadWorkerBase,
|
|
41
|
+
resolveBrowserWorkerUrl,
|
|
42
|
+
DEFAULT_BROWSER_WORKER_URL,
|
|
43
|
+
WasiThreadWorkerUnreachableError,
|
|
44
|
+
} from "./host/wasiThreadHost.js";
|
|
32
45
|
// The runtime-target gate is reachable so a consumer can catch the refusal by
|
|
33
46
|
// CLASS (`error instanceof RuntimeTargetError`) rather than by matching a
|
|
34
47
|
// message string, and can ask the same question the loaders ask before it
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A deterministic, non-physics reference receipt for exercising the
|
|
3
|
+
* estimation-family conformance evaluator. Real modules replace every value
|
|
4
|
+
* with measurements produced by their compiled WASM artifact. Keeping the
|
|
5
|
+
* evaluator's own known-good input here lets the negative controls prove that
|
|
6
|
+
* each required lane can fail without shipping a second JS estimator.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const reference = {
|
|
10
|
+
schemaVersion: 1,
|
|
11
|
+
family: "estimation",
|
|
12
|
+
artifact: { sha256: "reference-estimation-artifact" },
|
|
13
|
+
runtime: {
|
|
14
|
+
browser: { outputSha256: "reference-output" },
|
|
15
|
+
wasmedge: { outputSha256: "reference-output" },
|
|
16
|
+
threads: {
|
|
17
|
+
"1": "reference-output",
|
|
18
|
+
"2": "reference-output",
|
|
19
|
+
"4": "reference-output",
|
|
20
|
+
"8": "reference-output",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
batch: {
|
|
24
|
+
positionAbsoluteErrorM: 0.25,
|
|
25
|
+
positionRelativeError: 4e-8,
|
|
26
|
+
covarianceRssRelativeError: 0.02,
|
|
27
|
+
residualRmsRelativeError: 2e-8,
|
|
28
|
+
rejectedExpected: [7, 19],
|
|
29
|
+
rejectedActual: [7, 19],
|
|
30
|
+
iterationCount: 4,
|
|
31
|
+
iterationCovarianceCount: 4,
|
|
32
|
+
iterationCovariancesSpd: true,
|
|
33
|
+
},
|
|
34
|
+
filter: {
|
|
35
|
+
positionErrorM: 0.65,
|
|
36
|
+
smootherPositionErrorM: 0.21,
|
|
37
|
+
smootherCovarianceMonotone: true,
|
|
38
|
+
neesMean: 6.02,
|
|
39
|
+
nees95Lower: 5.34,
|
|
40
|
+
nees95Upper: 6.70,
|
|
41
|
+
sncCovarianceGrowthRatio: 1.21,
|
|
42
|
+
dmcCovarianceGrowthRatio: 1.58,
|
|
43
|
+
ekfUkfCovarianceDifference: 0.08,
|
|
44
|
+
},
|
|
45
|
+
measurements: {
|
|
46
|
+
rangeMaxRelativeError: 6e-16,
|
|
47
|
+
rangeRateMaxRelativeError: 5e-16,
|
|
48
|
+
azElMaxRelativeError: 5e-16,
|
|
49
|
+
raDecMaxRelativeError: 5e-16,
|
|
50
|
+
lightTimeMagnitudeErrorM: 2e-10,
|
|
51
|
+
sagnacMagnitudeErrorM: 2e-10,
|
|
52
|
+
},
|
|
53
|
+
media: {
|
|
54
|
+
hopfieldSaastamoinenMaxRelativeError: 6e-5,
|
|
55
|
+
mariniMaxRelativeError: 7e-5,
|
|
56
|
+
p531PublishedPrecisionError: 0,
|
|
57
|
+
},
|
|
58
|
+
iod: {
|
|
59
|
+
gaussPrintedPrecisionError: 0,
|
|
60
|
+
laplacePrintedPrecisionError: 0,
|
|
61
|
+
gibbsPrintedPrecisionError: 0,
|
|
62
|
+
herrickGibbsPrintedPrecisionError: 0,
|
|
63
|
+
},
|
|
64
|
+
simulator: {
|
|
65
|
+
runs: 200,
|
|
66
|
+
stateInsideThreeSigmaFraction: 0.965,
|
|
67
|
+
recoveredNoiseSigmaRelativeError: 0.031,
|
|
68
|
+
},
|
|
69
|
+
invariants: {
|
|
70
|
+
covarianceSymmetric: true,
|
|
71
|
+
covariancePositiveDefinite: true,
|
|
72
|
+
residualOrthogonalityMax: 3e-11,
|
|
73
|
+
actualOcmCovariance: true,
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const ESTIMATION_REFERENCE_EVIDENCE = Object.freeze(reference);
|
|
78
|
+
|
|
79
|
+
export function makeEstimationReferenceEvidence() {
|
|
80
|
+
return structuredClone(reference);
|
|
81
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/** Estimation-family conformance receipt evaluator. No physics lives here. */
|
|
2
|
+
|
|
3
|
+
import { computeVerdict } from "./propagatorSuite.js";
|
|
4
|
+
|
|
5
|
+
const pass = (id, tier, detail) => ({ id, tier, required: true, status: "pass", detail });
|
|
6
|
+
const fail = (id, tier, detail) => ({ id, tier, required: true, status: "fail", detail });
|
|
7
|
+
|
|
8
|
+
function check(checks, id, tier, condition, detail, failure = detail) {
|
|
9
|
+
checks.push(condition ? pass(id, tier, detail) : fail(id, tier, failure));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function finiteAtMost(value, limit) {
|
|
13
|
+
return Number.isFinite(value) && value <= limit;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function sameSet(left = [], right = []) {
|
|
17
|
+
const a = [...new Set(left)].sort((x, y) => x - y);
|
|
18
|
+
const b = [...new Set(right)].sort((x, y) => x - y);
|
|
19
|
+
return a.length === b.length && a.every((value, index) => value === b[index]);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function runEstimationSuite(evidence) {
|
|
23
|
+
const checks = [];
|
|
24
|
+
const runtimeHashes = [
|
|
25
|
+
evidence?.runtime?.browser?.outputSha256,
|
|
26
|
+
evidence?.runtime?.wasmedge?.outputSha256,
|
|
27
|
+
evidence?.runtime?.threads?.["1"],
|
|
28
|
+
evidence?.runtime?.threads?.["2"],
|
|
29
|
+
evidence?.runtime?.threads?.["4"],
|
|
30
|
+
evidence?.runtime?.threads?.["8"],
|
|
31
|
+
];
|
|
32
|
+
check(checks, "tier0/tri-runtime-byte-identity", "0",
|
|
33
|
+
runtimeHashes.every(Boolean) && new Set(runtimeHashes).size === 1,
|
|
34
|
+
"browser, WasmEdge and worker widths 1/2/4/8 emitted byte-identical results",
|
|
35
|
+
"missing or divergent browser/WasmEdge/thread-width output digests");
|
|
36
|
+
|
|
37
|
+
const batch = evidence?.batch ?? {};
|
|
38
|
+
check(checks, "tierA/batch-state", "A",
|
|
39
|
+
finiteAtMost(batch.positionAbsoluteErrorM, 1) &&
|
|
40
|
+
finiteAtMost(batch.positionRelativeError, 1e-3),
|
|
41
|
+
`absolute=${batch.positionAbsoluteErrorM} m relative=${batch.positionRelativeError}`,
|
|
42
|
+
"batch state exceeds 1 m absolute or 1e-3 relative");
|
|
43
|
+
check(checks, "tierA/batch-covariance", "A",
|
|
44
|
+
finiteAtMost(batch.covarianceRssRelativeError, 0.05),
|
|
45
|
+
`RSS position sigma relative error=${batch.covarianceRssRelativeError}`,
|
|
46
|
+
"batch covariance RSS differs from authority by more than 5%");
|
|
47
|
+
check(checks, "tierA/batch-residual-rms", "A",
|
|
48
|
+
finiteAtMost(batch.residualRmsRelativeError, 1e-6),
|
|
49
|
+
`residual RMS relative error=${batch.residualRmsRelativeError}`,
|
|
50
|
+
"batch residual RMS differs from authority by more than 1e-6 relative");
|
|
51
|
+
check(checks, "tierA/sigma-edit-set", "A",
|
|
52
|
+
sameSet(batch.rejectedExpected, batch.rejectedActual),
|
|
53
|
+
`exact rejected set [${batch.rejectedActual ?? []}]`,
|
|
54
|
+
"sigma editing rejected a different observation set");
|
|
55
|
+
check(checks, "tierC/batch-iteration-covariance", "C",
|
|
56
|
+
Number.isInteger(batch.iterationCount) && batch.iterationCount > 0 &&
|
|
57
|
+
batch.iterationCovarianceCount === batch.iterationCount &&
|
|
58
|
+
batch.iterationCovariancesSpd === true,
|
|
59
|
+
`${batch.iterationCovarianceCount}/${batch.iterationCount} iteration covariances are SPD`,
|
|
60
|
+
"batch iteration covariance history is missing, incomplete, or not SPD");
|
|
61
|
+
|
|
62
|
+
const filter = evidence?.filter ?? {};
|
|
63
|
+
check(checks, "tierA/filter-and-smoother-state", "A",
|
|
64
|
+
finiteAtMost(filter.positionErrorM, 1) &&
|
|
65
|
+
finiteAtMost(filter.smootherPositionErrorM, 0.5),
|
|
66
|
+
`filter=${filter.positionErrorM} m smoother=${filter.smootherPositionErrorM} m`,
|
|
67
|
+
"filter exceeds 1 m or RTS smoother exceeds 0.5 m");
|
|
68
|
+
check(checks, "tierC/smoother-covariance", "C",
|
|
69
|
+
filter.smootherCovarianceMonotone === true,
|
|
70
|
+
"smoothed covariance is no larger than filtered covariance at every epoch");
|
|
71
|
+
check(checks, "tierC/nees-100-run", "C",
|
|
72
|
+
Number.isFinite(filter.neesMean) && filter.neesMean >= filter.nees95Lower &&
|
|
73
|
+
filter.neesMean <= filter.nees95Upper,
|
|
74
|
+
`NEES mean=${filter.neesMean} band=[${filter.nees95Lower},${filter.nees95Upper}]`,
|
|
75
|
+
"100-run NEES lies outside the declared chi-square 95% band");
|
|
76
|
+
check(checks, "tierC/process-noise", "C",
|
|
77
|
+
Number.isFinite(filter.sncCovarianceGrowthRatio) && filter.sncCovarianceGrowthRatio !== 1 &&
|
|
78
|
+
Number.isFinite(filter.dmcCovarianceGrowthRatio) && filter.dmcCovarianceGrowthRatio !== 1,
|
|
79
|
+
`SNC ratio=${filter.sncCovarianceGrowthRatio} DMC ratio=${filter.dmcCovarianceGrowthRatio}`,
|
|
80
|
+
"SNC or DMC failed to change covariance growth");
|
|
81
|
+
check(checks, "tierC/ekf-ukf-not-aliased", "C",
|
|
82
|
+
Number.isFinite(filter.ekfUkfCovarianceDifference) && filter.ekfUkfCovarianceDifference > 0,
|
|
83
|
+
`covariance history distance=${filter.ekfUkfCovarianceDifference}`,
|
|
84
|
+
"EKF and UKF covariance histories are identical");
|
|
85
|
+
|
|
86
|
+
const measurement = evidence?.measurements ?? {};
|
|
87
|
+
for (const [name, key] of [["range", "rangeMaxRelativeError"],
|
|
88
|
+
["range-rate", "rangeRateMaxRelativeError"], ["az-el", "azElMaxRelativeError"],
|
|
89
|
+
["ra-dec", "raDecMaxRelativeError"]]) {
|
|
90
|
+
check(checks, `tierA/measurement-${name}`, "A", finiteAtMost(measurement[key], 1e-6),
|
|
91
|
+
`max relative error=${measurement[key]}`, `${name} exceeds 1e-6 relative`);
|
|
92
|
+
}
|
|
93
|
+
check(checks, "tierA/light-time", "A", finiteAtMost(measurement.lightTimeMagnitudeErrorM, 1e-6),
|
|
94
|
+
`magnitude error=${measurement.lightTimeMagnitudeErrorM} m`);
|
|
95
|
+
check(checks, "tierA/sagnac", "A", finiteAtMost(measurement.sagnacMagnitudeErrorM, 1e-6),
|
|
96
|
+
`magnitude error=${measurement.sagnacMagnitudeErrorM} m`);
|
|
97
|
+
|
|
98
|
+
const media = evidence?.media ?? {};
|
|
99
|
+
check(checks, "tierA/troposphere-hopfield-saastamoinen", "A",
|
|
100
|
+
finiteAtMost(media.hopfieldSaastamoinenMaxRelativeError, 1e-4),
|
|
101
|
+
`relative error=${media.hopfieldSaastamoinenMaxRelativeError}`);
|
|
102
|
+
check(checks, "tierA/troposphere-marini", "A",
|
|
103
|
+
finiteAtMost(media.mariniMaxRelativeError, 1e-4),
|
|
104
|
+
`relative error=${media.mariniMaxRelativeError}`);
|
|
105
|
+
check(checks, "tierB/ionosphere-p531", "B", media.p531PublishedPrecisionError === 0,
|
|
106
|
+
"P.531 table value reproduced to published precision");
|
|
107
|
+
|
|
108
|
+
for (const [name, key] of [["gauss", "gaussPrintedPrecisionError"],
|
|
109
|
+
["laplace", "laplacePrintedPrecisionError"], ["gibbs", "gibbsPrintedPrecisionError"],
|
|
110
|
+
["herrick-gibbs", "herrickGibbsPrintedPrecisionError"]]) {
|
|
111
|
+
check(checks, `tierB/iod-${name}`, "B", evidence?.iod?.[key] === 0,
|
|
112
|
+
"Vallado worked example reproduced to printed precision");
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const simulator = evidence?.simulator ?? {};
|
|
116
|
+
check(checks, "tierC/simulator-coverage", "C",
|
|
117
|
+
simulator.runs >= 200 && simulator.stateInsideThreeSigmaFraction >= 0.95,
|
|
118
|
+
`${simulator.stateInsideThreeSigmaFraction} inside 3-sigma over ${simulator.runs} runs`);
|
|
119
|
+
check(checks, "tierC/simulator-noise-recovery", "C",
|
|
120
|
+
finiteAtMost(simulator.recoveredNoiseSigmaRelativeError, 0.05),
|
|
121
|
+
`noise sigma relative error=${simulator.recoveredNoiseSigmaRelativeError}`);
|
|
122
|
+
|
|
123
|
+
const invariants = evidence?.invariants ?? {};
|
|
124
|
+
check(checks, "tierC/covariance-spd", "C",
|
|
125
|
+
invariants.covarianceSymmetric === true && invariants.covariancePositiveDefinite === true,
|
|
126
|
+
"covariance is symmetric positive definite");
|
|
127
|
+
check(checks, "tierC/residual-orthogonality", "C",
|
|
128
|
+
finiteAtMost(invariants.residualOrthogonalityMax, 1e-6),
|
|
129
|
+
`max normalized normal-equation projection=${invariants.residualOrthogonalityMax}`);
|
|
130
|
+
check(checks, "tierC/ocm-covariance", "C", invariants.actualOcmCovariance === true,
|
|
131
|
+
"the emitted OCM carries the estimator covariance");
|
|
132
|
+
|
|
133
|
+
return { checks, verdict: computeVerdict(checks) };
|
|
134
|
+
}
|