import { LiteralUnion } from 'type-fest'; import { PartialPositionUpdate, PositionAnchor, RelativePositionUpdate } from '../fusion/types'; /** * Built-in sensor IDs */ declare const BUILT_IN_SENSOR_IDS: readonly ["geolocation", "deviceorientation", "devicemotion", "manual", "fusion"]; /** * Built-in sensor IDs. */ export type BuiltInSensorId = (typeof BUILT_IN_SENSOR_IDS)[number]; /** * Utility type that rejects built-in IDs when they are known as literals. * * TypeScript cannot represent "any string except these specific literals" as a standalone type * (i.e., `Exclude` evaluates to `string`). This helper is meant for APIs like * `SensorRegistry.register()` where the sensor's `id` is typically a string literal type. */ export type CustomSensorId = Id extends BuiltInSensorId ? never : Id; /** * Sensor ID - either a built-in ID or a custom string ID. */ export type SensorId = LiteralUnion; /** * Event payloads for internal sensor communication. * * These are INTERNAL events used between sensors and the FusionEngine. * They are NOT the same as the external `position-update` event that * app developers subscribe to on the BlueDot class. * * ## Event Flow * * ``` * Sensors ──► SensorRegistry ──► FusionEngine ──► BlueDot ──► App * │ │ │ │ * │ absolute-update │ │ │ position-update * │ relative-update │ │ │ (external API) * │ (internal) │ │ │ * ``` * * ## Event Types * * - **`absolute-update`**: Sensors providing global coordinates (GPS lat/lon, compass heading) * - **`relative-update`**: Sensors providing displacement from a reference (PDR steps: dx/dy meters) * - **`anchor-set`**: Sensors setting a high-confidence position anchor (VPS, AI Localizer) * - **`anchor-clear`**: Sensors clearing their anchor * - **`error`**: Sensor errors * * The FusionEngine processes these differently: * - Absolute updates → `ekf.updatePosition(lat, lon, noise, timestamp)` * - Relative updates → `ekf.updateOdometry(dx, dy, noise, timestamp)` */ export type SensorEventPayloads = { /** * Emitted when a sensor provides an absolute position or heading update. * * "Absolute" means the data represents a global/world coordinate or direction, * not a displacement from a previous position. * * Examples of absolute updates: * - GPS position (latitude, longitude) * - Compass heading (0-360 degrees from north) * - Gyroscope angular velocity (for heading integration) * - VPS/AI Localizer position (high-confidence anchor) * * The FusionEngine routes these to `ekf.updatePosition()` for lat/lon data, * or to the HeadingFusionFilter for heading/angular velocity data. * * @see {@link relative-update} for displacement-based updates */ 'absolute-update': { /** Which sensor produced this update */ sensorId: SensorId; /** The position/heading data (fields are optional - sensors provide what they have) */ update: PartialPositionUpdate; }; /** * Emitted when a sensor provides a relative displacement update. * * "Relative" means the data represents movement FROM a reference position, * not an absolute world coordinate. Used for Pedestrian Dead Reckoning (PDR). * * Examples of relative updates: * - Step detection: "moved 0.7 meters in direction of current heading" * - Inertial navigation: "displaced (dx, dy) meters since last update" * * The FusionEngine routes these to `ekf.updateOdometry()`. * * **Important**: Relative updates are only useful when an anchor is active. * Without an anchor, there's no reference point to apply the displacement to. * The FusionEngine will ignore relative updates when `anchorState === 'none'`. * * @see {@link absolute-update} for global coordinate updates */ 'relative-update': { /** Which sensor produced this update */ sensorId: SensorId; /** The displacement data */ update: RelativePositionUpdate; }; /** * Emitted when a sensor encounters an error. */ error: { /** Which sensor encountered the error */ sensorId: SensorId; /** The error (may be a GeolocationPositionError for geolocation sensor) */ error: Error | GeolocationPositionError; }; /** * Emitted when a sensor sets a position anchor. * * Anchors are high-confidence absolute positions from calibration sources * (VPS, AI Localizer, QR code scan, manual correction). When an anchor is * active, it serves as the reference point for position fusion. * * The FusionEngine resets the EKF state and uses the anchor as ground truth. */ 'anchor-set': { /** Which sensor is setting the anchor */ sensorId: SensorId; /** The anchor position data */ anchor: PositionAnchor; /** Optional config override for this anchor (e.g., extended anchorOnlyPeriod for forcePosition) */ configOverride?: { anchorOnlyPeriodMs: number; }; }; /** * Emitted when a sensor clears its anchor. * * After clearing, the FusionEngine will fall back to other position sources. */ 'anchor-clear': { /** Which sensor is clearing the anchor */ sensorId: SensorId; }; }; export {};