navigation_safety
Show drivers what matters before it's too late. Safety alerts that stay on top of your navigation UI — always visible, never controlling.
Use navigation_safety when you need a navigation session state machine with a
safety overlay that renders alerts (ice, low visibility, GPS loss) without
blocking the driver's view or controlling the vehicle.
Features
NavigationBlocfor navigation session lifecycle: idle, navigating, deviated, arrived.SafetyOverlaywidget that stays at the top of the UI stack when alerts are active.- Pure Dart
_coreexports forSafetyScore,AlertSeverity, andNavigationSafetyConfig. - Configurable severity thresholds for score-based safety alerts.
- Composable with
routing_blocandvoice_guidancewithout coupling to either.
Install
dependencies:
navigation_safety: ^0.3.0
Quick Start
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:navigation_safety/navigation_safety.dart';
import 'package:routing_engine/routing_engine.dart';
class MyNavScreen extends StatelessWidget {
const MyNavScreen({super.key});
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => NavigationBloc(),
child: Scaffold(
body: Stack(
children: const [
Placeholder(),
SafetyOverlay(),
],
),
),
);
}
}
API Overview
| API | Purpose |
|---|---|
NavigationBloc |
Navigation session lifecycle and alert state |
NavigationState |
Session state, maneuver progress, active alert |
NavigationEvent |
Navigation start/stop, maneuver advance, alert input |
SafetyOverlay |
Safety alert presentation layer |
SafetyScore |
Pure Dart score model for grip, visibility, fleet confidence |
NavigationSafetyConfig |
Pure Dart threshold configuration |
AlertSeverity |
info, warning, critical |
OODA Latency Budget
| Phase | Budget | Owner |
|---|---|---|
| Observe | < 200 ms | Sensor streams |
| Orient | < 500 ms | NavigationBloc |
| Display | < 300 ms | SafetyOverlay |
| Total to display | < 1 second | SNGNav domain |
SafetyOverlay Rules
| Rule | Requirement |
|---|---|
| 1 | Always rendered - never removed from the widget tree |
| 2 | Always on top - Z=5 (topmost) |
| 3 | Passthrough when inactive - no input blocking |
| 4 | Modal when active - blocks interaction until acknowledged |
| 5 | Independent state - not reset by unrelated navigation transitions |
Threshold Configuration
import 'package:navigation_safety/navigation_safety_core.dart';
final config = NavigationSafetyConfig(
safeScoreFloor: 0.80,
infoScoreFloor: 0.50,
warningScoreFloor: 0.30,
criticalTemperatureCelsius: -5,
warningVisibilityMeters: 200,
);
final score = SafetyScore(
overall: 0.42,
gripScore: 0.35,
visibilityScore: 0.40,
fleetConfidenceScore: 0.75,
);
final severity = score.toAlertSeverity(config);
Safety Boundary (SOTIF scope)
This package is responsible for display. You are responsible for score computation.
If your score is uncertain, pass 0.0 — the package will alert conservatively.
This package must not be used to issue vehicle control commands or to imply ADAS
certification. Classification: ASIL-QM (display-only). No actuator path.
SafetyScore Computation
SafetyScore.overall is compared against thresholds in NavigationSafetyConfig:
overall < warningScoreFloor → AlertSeverity.critical
overall < infoScoreFloor → AlertSeverity.warning
overall < safeScoreFloor → AlertSeverity.info
otherwise → no alert
The component scores (gripScore, visibilityScore, fleetConfidenceScore) are
inputs you compute from your sensor data. The package does not read sensors — it
displays what you give it. Each component is clamped to [0.0, 1.0].
Contributing a Signal
You can extend this package to cover a new threat scenario in about 3 hours:
- Read
lib/src/models/safety_score.dart(72 lines) andlib/src/models/navigation_safety_config.dart - Add one field to
SafetyScorefor your scenario (e.g.,infrastructureRiskScore) - Add a corresponding threshold to
NavigationSafetyConfig - Update
toAlertSeverity()to check your new field - Write 3 tests: boundary value, clamp behaviour, severity mapping
- Open a PR referencing the scenario ID from CONTRIBUTING.md
No KUKSA, Valhalla, or embedded Linux knowledge required. The SOTIF boundary above is what protects you — you only need to compute a float and pass it in.
See CONTRIBUTING.md for the list of open scenario slots.
Works With
| Package | How |
|---|---|
| driving_weather | Weather conditions feed into safety score computation |
| driving_conditions | Road surface and grip data drive alert severity |
| map_viewport_bloc | Safety overlay sits at Z5 in the viewport layer stack |
See Also
- kalman_dr — Dead reckoning through GPS loss
- routing_bloc — Route lifecycle state machine
- driving_consent — Privacy consent with Jidoka semantics
Part of SNGNav — 11 packages for offline-first navigation on Flutter.
License
BSD-3-Clause — see LICENSE.
Libraries
- Safety-focused navigation session and overlay package.
- Pure Dart core exports — transitional compat shim.