routing_engine

Engine-agnostic routing interface for Dart with OSRM and Valhalla implementations.

When to use this package

Use routing_engine when you want one route API that can target OSRM, Valhalla, or a custom backend without rewriting app logic.

Features

  • Abstract interface: RoutingEngine defines calculateRoute, isAvailable, info, dispose
  • OSRM engine: sub-frame latency (4.9ms for 10km), polyline5 decoding
  • Valhalla engine: multi-modal routing, isochrone support, Japanese language
  • Engine identity: EngineInfo reports name, version, and query latency
  • Build-time selection: swap engines without code changes

Install

dependencies:
  routing_engine: ^0.1.2

Quick Start

import 'package:routing_engine/routing_engine.dart';

// Create an engine
final engine = OsrmRoutingEngine(baseUrl: 'http://localhost:5000');

// Check availability
if (await engine.isAvailable()) {
  // Calculate a route
  final result = await engine.calculateRoute(RouteRequest(
    origin: LatLng(35.1709, 136.9066),   // Sakae Station
    destination: LatLng(34.9551, 137.1771), // Higashiokazaki Station
  ));

  print('${result.totalDistanceKm} km, ${result.maneuvers.length} turns');
  print('Engine: ${result.engineInfo.name} '
      '(${result.engineInfo.queryLatency.inMilliseconds}ms)');
}

// Clean up
await engine.dispose();

Local Valhalla (canonical Machine E path)

final engine = ValhallaRoutingEngine.local();

if (await engine.isAvailable()) {
  final route = await engine.calculateRoute(const RouteRequest(
    origin: LatLng(35.1709, 136.9066),
    destination: LatLng(34.9551, 137.1771),
  ));

  print('Local Valhalla: ${route.engineInfo.queryLatency.inMilliseconds}ms');
}

ValhallaRoutingEngine.local() targets http://localhost:8005, which matches the canonical Machine E local runtime path proven in SNGNav. The plain ValhallaRoutingEngine() constructor still preserves the historical http://localhost:8002 default for compatibility. Override host, port, availabilityTimeout, or routeTimeout when needed.

Integration Pattern

In a Flutter app, routing_engine typically sits behind a button or bloc event: choose the backend once, fetch the route asynchronously, then render the summary and maneuver list. Keep the engine creation close to app start so you can swap OSRM, Valhalla, or a local backend without touching the route screen.

import 'package:flutter/material.dart';
import 'package:latlong2/latlong.dart';
import 'package:routing_engine/routing_engine.dart';

class RoutePreviewCard extends StatefulWidget {
  const RoutePreviewCard({super.key});

  @override
  State<RoutePreviewCard> createState() => _RoutePreviewCardState();
}

class _RoutePreviewCardState extends State<RoutePreviewCard> {
  late final RoutingEngine engine;
  Future<RouteResult>? pendingRoute;

  @override
  void initState() {
    super.initState();
    engine = ValhallaRoutingEngine.local();
    pendingRoute = engine.calculateRoute(const RouteRequest(
      origin: LatLng(35.1709, 136.9066),
      destination: LatLng(34.9551, 137.1771),
    ));
  }

  @override
  void dispose() {
    engine.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<RouteResult>(
      future: pendingRoute,
      builder: (context, snapshot) {
        final route = snapshot.data;
        if (route == null) {
          return const Text('Calculating route...');
        }

        return Card(
          child: ListTile(
            title: Text(route.summary),
            subtitle: Text(
              '${route.totalDistanceKm.toStringAsFixed(1)} km, '
              '${route.maneuvers.length} maneuvers via '
              '${route.engineInfo.name}',
            ),
          ),
        );
      },
    );
  }
}

When you later adopt routing_bloc, keep this same seam: the bloc owns the async lifecycle, routing_engine stays the backend abstraction.

Implement a custom engine

class MyRoutingEngine implements RoutingEngine {
  @override
  EngineInfo get info => const EngineInfo(
    name: 'my-engine', version: '1.0.0',
    queryLatency: Duration(milliseconds: 10),
  );

  @override
  Future<bool> isAvailable() async => true;

  @override
  Future<RouteResult> calculateRoute(RouteRequest request) async {
    // Your routing logic here
  }

  @override
  Future<void> dispose() async {}
}

API Overview

Type Purpose
RoutingEngine Abstract interface for route calculation, availability checks, and cleanup.
RouteRequest Defines origin, destination, and optional waypoints for a route query.
RouteResult Returns maneuvers, geometry, distance, duration, and engine metadata.
EngineInfo Reports engine name, version, and observed query latency.
OsrmRoutingEngine / ValhallaRoutingEngine Concrete implementations for OSRM and Valhalla backends.

See Also

  • kalman_dr — Dead reckoning through GPS loss (tunnels, urban canyons)
  • driving_weather — Weather condition model for driving (snow, ice, visibility)
  • driving_consent — Privacy consent with Jidoka semantics (UNKNOWN = DENIED)
  • fleet_hazard — Fleet telemetry hazard model and geographic clustering
  • driving_conditions — Pure Dart computation models for road surface, visibility, and safety score simulation
  • navigation_safety — Flutter navigation safety state machine and safety overlay
  • map_viewport_bloc — Flutter viewport and layer composition state machine
  • routing_bloc — Flutter route lifecycle state machine and progress UI
  • offline_tiles — Flutter offline tile manager with MBTiles fallback

Part of SNGNav

routing_engine is one of the 10 packages in SNGNav, an offline-first, driver-assisting navigation reference product for embedded Linux.

Local Integration Test

Run the real-network local Valhalla test only when a local server is up:

cd packages/routing_engine
RUN_LOCAL_VALHALLA_TEST=1 dart test test/valhalla_local_integration_test.dart

Optional override:

VALHALLA_BASE_URL=http://machine-e:8005 RUN_LOCAL_VALHALLA_TEST=1 dart test test/valhalla_local_integration_test.dart

Benchmark Utility

Run the exact-payload Valhalla benchmark used for local/public latency comparison:

cd packages/routing_engine
dart run tool/valhalla_benchmark.dart

Optional environment overrides:

LOCAL_VALHALLA_BASE_URL=http://localhost:8005 \
PUBLIC_VALHALLA_BASE_URL=https://valhalla1.openstreetmap.de \
RUN_PUBLIC_VALHALLA_BENCHMARK=1 \
dart run tool/valhalla_benchmark.dart

License

BSD-3-Clause — see LICENSE.

Libraries

routing_engine
Engine-agnostic routing interface with OSRM and Valhalla implementations.