Documentation menu
ai.mapmap:core (Android) reference
Generated from the published ai.mapmap:core 0.8.0 sources (core-0.8.0-sources.jar on Maven Central) by
website/scripts/sdk-reference-native.mjs. Do not edit by hand: change the doc comments in the SDK, or the examples inwebsite/content/sdk-reference/android.examples.md, and regenerate.
Every public declaration of the Android library at release 0.8.0, from its published sources jar: the hand-written ai.mapmap API and the generated uniffi.mapmap and uniffi.ferrostar bindings to the Rust core. The guide is Android (Kotlin) in SDKs & installation and the hand-written Android API reference. Requires minSdk 26.
Other SDK references: @mapmap/maps, @mapmap/points, @mapmap/core, @mapmap/tile, @mapmap/react-native, @mapmap/voice, MapMapKit.
316 public declarations across 3 packages: 42 written by hand, 274 in the generated Rust bindings.
How to read this page
Each entry gives the declaration as written in the release source (in Kotlin without identifier backticks or the kotlin. package prefix), its doc comment, and its public members. The Default column shows a value only where the source writes one (an initialiser, a parameter's default, or a doc comment that states it); otherwise it is blank. Types and classes written by hand carry a minimal example. The generated bindings are the Rust core's types as UniFFI exposes them; their descriptions are the Rust doc comments.
Setup used by the examples
// build.gradle.kts
dependencies {
implementation("ai.mapmap:core:0.8.0")
}
Contents
- ai.mapmap: 42 declarations
- uniffi.mapmap: 106 declarations
- uniffi.ferrostar: 168 declarations
ai.mapmap
Classes (ai.mapmap)
AndroidLocationProvider, AudioFocusPolicy, ChannelSource, ChannelSync.Installed, ChannelSync.Updated, ChannelSync.UpToDate, CorpusFormatException, DriveCorpus, DriveFix, DriveHeader, HttpChannelFetcher, HttpProbeUploader, LocationSample, NavigationEngine, NavigationState, ReplayLocationProvider, SignedChannelIndex, TerritoryStore, TtsStartup, TtsStartup.InitActions, ValhallaMobileRouter, VoiceGuidance, VoiceProsody.Prosody
AndroidLocationProvider
Class · ai/mapmap/nav/AndroidLocationProvider.kt
public class AndroidLocationProvider(context: Context, private val minIntervalMs: Long = 1_000L, private val minDistanceM: Float = 0f) : LocationProvider
Live LocationProvider on the platform location stack, no Google Play
Services dependency.
Uses LocationManager.FUSED_PROVIDER (the platform fused provider,
API 31+) and falls back to LocationManager.GPS_PROVIDER on older
devices. Requires ACCESS_FINE_LOCATION to be granted before the flow
is collected; the SDK manifest deliberately declares no permissions.
Background collection is subject to the platform's background-location limits and OEM battery management, see android/README.md ("Location permissions and device caveats") before shipping fleet builds.
@param minIntervalMs minimum interval between fixes; 1 Hz default matches vehicular guidance expectations.
| Property | Type | Default | Description |
|---|---|---|---|
val locations | Flow<LocationSample> |
Nested: AndroidLocationProvider.Companion.
Example
import ai.mapmap.nav.AndroidLocationProvider
import android.content.Context
// Needs ACCESS_FINE_LOCATION granted first.
suspend fun printFixes(context: Context) {
AndroidLocationProvider(context, minIntervalMs = 1_000L).locations.collect { fix ->
println("${fix.lat}, ${fix.lon} ±${fix.horizontalAccuracyM}")
}
}
AudioFocusPolicy
Class · ai/mapmap/nav/VoiceGuidance.kt
public class AudioFocusPolicy
Pure audio-focus bookkeeping, unit-testable on any JVM. Transient
focus is held across the set of outstanding utterances (TextToSpeech
queues with QUEUE_ADD, so several can be in flight) and abandoned
only when the last one ends. Focus counts as held only when the
platform actually granted the request; a denied request is never
"abandoned" later, and the next utterance retries it.
| Property | Type | Default | Description |
|---|---|---|---|
var focusHeld | Boolean | false | Whether a granted transient focus request is currently held. |
val outstandingCount | Int | Utterances queued but not yet finished. |
Initialisers and methods
public fun shouldRequestFocus(): Boolean: Before speaking: whether a focus request should be made now.public fun onSpeakQueued(utteranceId: String, flushedQueue: Boolean, granted: Boolean?): RecordutteranceIdbeing handed to the engine.flushedQueueis true forQUEUE_FLUSHprompts (everything previously queued is discarded without callbacks);grantedis the focus-request result, or null when no request was made because focus is held.public fun onUtteranceEnded(utteranceId: String?): Boolean: Record an utterance ending (done, error or stop). Returnstruewhen focus should be abandoned now, the last outstanding utterance ended while focus was held.public fun reset(): Boolean: Everything stopped/muted. Returnstruewhen focus should be abandoned.
Example
import ai.mapmap.nav.AudioFocusPolicy
// The audio-focus bookkeeping VoiceGuidance runs: request once per burst, abandon after the last utterance.
val focus = AudioFocusPolicy()
fun speak(id: String) {
val request = focus.shouldRequestFocus()
focus.onSpeakQueued(id, flushedQueue = false, granted = if (request) true else null)
}
fun done(id: String) {
if (focus.onUtteranceEnded(id)) println("abandon audio focus")
}
ChannelSource
Class · ai/mapmap/territory/ChannelSource.kt
public data class ChannelSource(val indexUrl: String, val indexSigUrl: String, val layerBaseUrl: String)
Where a signed territory channel lives over HTTPS: its index, the index's
detached signature, and the base every channel-relative layer path
(territories/<id>/<version>/...) is resolved against.
Nothing fetched from here is trusted: the core verifies the index
signature, the manifest signature and every layer hash against the keys
pinned in the TerritoryStore.
| Property | Type | Default | Description |
|---|---|---|---|
val indexUrl | String | ||
val indexSigUrl | String | ||
val layerBaseUrl | String |
Nested: ChannelSource.Companion.
ChannelSync.Installed
Class · ai/mapmap/territory/TerritoryStore.kt
public data class Installed(val result: ChannelInstallResult) : ChannelSync
The territory was not installed; the channel's latest version now is.
| Property | Type | Default | Description |
|---|---|---|---|
val result | ChannelInstallResult |
ChannelSync.Updated
Class · ai/mapmap/territory/TerritoryStore.kt
public data class Updated(val result: UpdateResult) : ChannelSync
An older version was installed; it was updated in place.
| Property | Type | Default | Description |
|---|---|---|---|
val result | UpdateResult |
ChannelSync.UpToDate
Class · ai/mapmap/territory/TerritoryStore.kt
public data class UpToDate(val territory: TerritoryInfo) : ChannelSync
Already on the channel's latest version; nothing was downloaded.
| Property | Type | Default | Description |
|---|---|---|---|
val territory | TerritoryInfo |
CorpusFormatException
Class · ai/mapmap/replay/DriveCorpus.kt
public class CorpusFormatException(message: String) : IllegalArgumentException(message)
A .drive.jsonl document violated the corpus format.
DriveCorpus
Class · ai/mapmap/replay/DriveCorpus.kt
public data class DriveCorpus(val header: DriveHeader, val fixes: List<DriveFix>)
Parser for the .drive.jsonl replay corpus format produced by the
workspace's sn-replay crate (see crates/sn-replay/src/corpus.rs).
Line 1 is a JSON header (format_version, name, description,
route_fixture, seed, optional generator); every following
non-blank line is one GPS fix (t_ms, lat, lon, optional
speed_mps, bearing_deg, horizontal_accuracy_m). The Kotlin parser
enforces the same invariants as the Rust one: supported format version,
non-empty name, at least one fix, strictly increasing t_ms, and sane
coordinate/channel ranges.
| Property | Type | Default | Description |
|---|---|---|---|
val header | DriveHeader | ||
val fixes | List<DriveFix> |
Nested: DriveCorpus.Companion.
DriveFix
Class · ai/mapmap/replay/DriveCorpus.kt
public data class DriveFix(val tMs: Long, val lat: Double, val lon: Double, val speedMps: Double?, val bearingDeg: Double?, val horizontalAccuracyM: Double?)
One GPS fix line of a corpus. tMs is milliseconds since drive start.
| Property | Type | Default | Description |
|---|---|---|---|
val tMs | Long | ||
val lat | Double | ||
val lon | Double | ||
val speedMps | Double? | ||
val bearingDeg | Double? | ||
val horizontalAccuracyM | Double? |
DriveHeader
Class · ai/mapmap/replay/DriveCorpus.kt
public data class DriveHeader(val formatVersion: Int, val name: String, val description: String, val routeFixture: String, val seed: Long)
Header line of a .drive.jsonl corpus.
| Property | Type | Default | Description |
|---|---|---|---|
val formatVersion | Int | ||
val name | String | ||
val description | String | ||
val routeFixture | String | ||
val seed | Long |
HttpChannelFetcher
Class · ai/mapmap/territory/ChannelSource.kt
public class HttpChannelFetcher(public val source: ChannelSource, private val apiKey: String? = null, private val cancel: CancelToken? = null, private val onBytes: ((Long) -> Unit)? = null) : LayerFetcher
A blocking HTTPS LayerFetcher for a ChannelSource, on
HttpURLConnection (no extra dependency). Call it off the main thread;
TerritoryStore does.
@param apiKey sent as Authorization: Bearer <apiKey> (the hosted
gateway meters layer downloads against the key's allowance); null
for an open mirror.
@param cancel polled between chunks, so a tripped token stops a transfer
in progress, not only the next one.
@param onBytes called with the running total of bytes received.
| Property | Type | Default | Description |
|---|---|---|---|
val source | ChannelSource | ||
var lastFailedStatus | Int? | null | HTTP status of the last failed request, or null. 401/403 auth, 402 allowance, 404 not found. |
val bytesReceived | Long | Total bytes received by this fetcher so far. |
Initialisers and methods
public fun fetchIndex(): SignedChannelIndex: GET the signed index and its signature, exact bytes.override fun fetch(relPath: String, expectedBlake3: String, destPath: String)
Example
import ai.mapmap.territory.ChannelSource
import ai.mapmap.territory.HttpChannelFetcher
// What TerritoryStore.sync(territoryId, source, apiKey) builds for you; use it directly when
// you drive installFromChannel or checkForUpdate yourself. Blocking: call off the main thread.
fun fetchIndex() {
val fetcher = HttpChannelFetcher(ChannelSource.gateway(), apiKey = "snk_…")
val index = fetcher.fetchIndex()
println("${index.json.length} bytes, ${fetcher.bytesReceived} received")
}
HttpProbeUploader
Class · ai/mapmap/nav/ProbeContribution.kt
public class HttpProbeUploader @JvmOverloads constructor(baseUrl: String, private val apiKey: String, private val maxAttempts: Int = 4, private val backoffMillis: (Int) -> Long = { attempt -> attempt * 1_000L }, private val executor: ExecutorService = Executors.newSingleThreadExecutor { r -> Thread(r, "mapmap-probe-upload").apply { isDaemon = true } }, private val onResult: (ProbeUploadOutcome) -> Unit = {}) : ProbeUploader, AutoCloseable
Default ProbeUploader: POSTs each body to {baseUrl}/v1/probe with a
bearer key, on a small daemon executor, using only the JDK HTTP client, the
SDK takes on no third-party HTTP dependency. Transient failures (IO or 5xx)
are retried with bounded backoff; permanent ones (400/403/501) are
dropped. Close it to release the executor.
@param baseUrl gateway origin, e.g. https://api.mapmap.ai (a trailing
slash is tolerated); @param maxAttempts total tries including the first;
@param backoffMillis attempt-number → delay before the next try.
Example
import ai.mapmap.nav.HttpProbeUploader
import ai.mapmap.nav.NavigationEngine
import ai.mapmap.nav.contributingProbe
import ai.mapmap.nav.LocationProvider
import uniffi.mapmap.ProbeConfig
// Opt-in aggregate probe upload (POST /v1/probe), retried with backoff.
suspend fun driveAndContribute(engine: NavigationEngine, provider: LocationProvider) {
val uploader = HttpProbeUploader("https://api.mapmap.ai", apiKey = "snk_…")
engine.navigate(provider)
.contributingProbe(ProbeConfig(enabled = true), uploader)
.collect { }
}
LocationSample
Class · ai/mapmap/nav/LocationProvider.kt
public data class LocationSample(val lat: Double, val lon: Double, val timestampMs: Long, val speedMps: Double? = null, val bearingDeg: Double? = null, val horizontalAccuracyM: Double? = null)
One position sample fed into guidance.
@property timestampMs milliseconds since the Unix epoch.
@property speedMps speed over ground, when the source reports it.
@property bearingDeg course over ground, degrees clockwise from true
north, [0, 360).
@property horizontalAccuracyM estimated 1-sigma horizontal accuracy in
metres. Pass the platform value whenever available, the core uses it
to gate step advance and deviation detection.
| Property | Type | Default | Description |
|---|---|---|---|
val lat | Double | ||
val lon | Double | ||
val timestampMs | Long | ||
val speedMps | Double? | null | |
val bearingDeg | Double? | null | |
val horizontalAccuracyM | Double? | null |
NavigationEngine
Class · ai/mapmap/nav/NavigationEngine.kt
public class NavigationEngine(private val routeResponseJson: String, private val config: GuidanceConfig = GuidanceConfig(), private val dispatcher: CoroutineDispatcher = Dispatchers.Default)
Turn-by-turn guidance over one computed route.
The Rust core's GuidanceSession (Ferrostar-based) is the navigation
state machine; this engine owns its lifecycle and adapts it to
coroutines: stream LocationSamples in from any LocationProvider,
collect NavigationStates out. The stream completes after Arrived.
An engine is bound to a single route, on OffRoute, compute a new
route and build a new engine (see NavigationState.needsReroute).
Ferrostar UI note: the Stadia Maps ferrostar Kotlin artefacts can sit
on top of this state (uniffi.ferrostar classes are packaged in this
SDK and served by the same native library), but our GuidanceSession
remains the state machine, see android/README.md, "Ferrostar boundary".
Initialisers and methods
public constructor(route: RouteResult, config: GuidanceConfig = GuidanceConfig(), dispatcher: CoroutineDispatcher = Dispatchers.Default): Build an engine from a route computed byai.mapmap.routing.OfflineRouting.route.public fun navigate(provider: LocationProvider, manualAdvance: Flow<Unit> = emptyFlow()): Flow<NavigationState>: Run guidance: feed every fix fromproviderinto a fresh native session and emit the resulting states. The flow is cold, each collection starts a new session at the first route step, and completes after arrival. Guidance maths runs ondispatcher. @param manualAdvance emitUnitto force-advance to the next step, the tunnel/no-GNSS escape hatch. Ignored before the first fix. @throws uniffi.mapmap.NavCoreException if the route response cannot start a session (e.g. malformed JSON).public fun totalSteps(): UInt: Total number of steps in the route (including arrival), for progress UIs. Opens a short-lived native session.
Example
import ai.mapmap.nav.AndroidLocationProvider
import ai.mapmap.nav.NavigationEngine
import ai.mapmap.nav.VoiceGuidance
import android.content.Context
import kotlinx.coroutines.flow.takeWhile
suspend fun drive(context: Context, routeResponseJson: String) {
val engine = NavigationEngine(routeResponseJson)
VoiceGuidance(context, language = "en-GB").use { voice ->
engine.navigate(AndroidLocationProvider(context))
.takeWhile { state -> !state.isArrived }
.collect { state -> voice.handle(state) }
}
}
NavigationState
Class · ai/mapmap/nav/NavigationState.kt
public data class NavigationState(val fix: LocationSample, val update: GuidanceUpdate)
One guidance emission: the fix that produced it plus the core's verdict.
GuidanceUpdate is the Rust core's sealed state, Navigating,
Arrived or OffRoute, and the single source of truth. This wrapper
only adds the triggering sample and display conveniences.
| Property | Type | Default | Description |
|---|---|---|---|
val fix | LocationSample | ||
val update | GuidanceUpdate | ||
val isArrived | Boolean | True once the core reports arrival at the destination. | |
val needsReroute | Boolean | True when the user has left the route entirely and the app should request a recalculation (build a new route + NavigationEngine). |
ReplayLocationProvider
Class · ai/mapmap/nav/ReplayLocationProvider.kt
public class ReplayLocationProvider(private val corpus: DriveCorpus, private val timeScale: Double = 1.0, private val epochStartMs: Long = 0L) : LocationProvider
Replays a .drive.jsonl corpus (the sn-replay QA format) as a
LocationProvider.
Fix timestamps in the corpus are relative to drive start; they are
rebased onto epochStartMs so guidance sees monotonic wall-clock-like
times.
@param corpus a parsed corpus (see DriveCorpus.parse).
@param timeScale playback speed: 1.0 = real time, 2.0 = twice as
fast, 0.0 = emit every fix immediately (unit tests).
@param epochStartMs epoch milliseconds assigned to the first fix.
| Property | Type | Default | Description |
|---|---|---|---|
val locations | Flow<LocationSample> |
Nested: ReplayLocationProvider.Companion.
Example
import ai.mapmap.nav.NavigationEngine
import ai.mapmap.nav.ReplayLocationProvider
import ai.mapmap.replay.DriveCorpus
import java.io.File
// Replay a recorded drive through guidance, ten times faster than real time.
suspend fun replay(corpusFile: File, routeResponseJson: String) {
val corpus = DriveCorpus.parse(corpusFile.readText())
NavigationEngine(routeResponseJson)
.navigate(ReplayLocationProvider(corpus, timeScale = 10.0))
.collect { state -> println(state.update) }
}
SignedChannelIndex
Class · ai/mapmap/territory/ChannelSource.kt
public data class SignedChannelIndex(val json: String, val signatureBase64: String)
The exact served bytes of a channel index and its detached signature.
| Property | Type | Default | Description |
|---|---|---|---|
val json | String | ||
val signatureBase64 | String |
TerritoryStore
Class · ai/mapmap/territory/TerritoryStore.kt
public class TerritoryStore(private val rootDir: File, private val verifyingKeyHex: String, private val dispatcher: CoroutineDispatcher = Dispatchers.IO, private val regionKeyHex: String? = null) : AutoCloseable
Coroutine-friendly store of signed offline territory packages.
Wraps the Rust TerritoryManager: every package is ed25519-signature and
BLAKE3-layer-hash verified before promotion, and nothing is trusted until
verification passes. All calls hop to dispatcher (IO by default), installs read whole archives and must never run on the main thread.
territories is a hot StateFlow of the installed set; it refreshes
after every mutating call and on refresh.
Installs are cancellable. The overloads taking a CancelToken (from the
core) can be stopped from any thread by calling cancel() on it, and they
also trip the token when the calling coroutine is cancelled, so a plain
job.cancel() works the way callers expect. A cancelled install returns
InstallOutcome.Cancelled / UpdateOutcome.Cancelled rather than
throwing: nothing was installed, staging is removed, the previous version
is untouched. Cancelling after completion changes nothing.
Custom regions (region- ids, cut by POST /v1/jobs/territory) are
signed by a separate region key. Pass its public half as regionKeyHex
(TerritoryKeys.HOSTED_REGION_KEY_HEX for the hosted gateway) to accept
them; the core then verifies region- ids against that key only and
every other id against the factory key only. Without it every region-
package is refused as a bad signature.
@param rootDir directory the store owns; created on first use.
@param verifyingKeyHex the factory signing key's public half, 64 hex
characters. Baked into the app at build time, treat it like a pin.
@param regionKeyHex the region signing key's public half, 64 hex
characters, or null to refuse custom regions. Pinned like the
factory key; never read from the network.
| Property | Type | Default | Description |
|---|---|---|---|
val acceptsCustomRegions | Boolean | Whether this store was given a region key, and so can install custom regions. | |
val territories | StateFlow<List<TerritoryInfo>> | The installed territories, refreshed after every mutating call. |
Initialisers and methods
public suspend fun refresh(): List<TerritoryInfo>: Re-read the installed set from disk and emit it onterritories.public suspend fun install(snpkg: File): TerritoryInfo: Install a packed.snpkgarchive. Verify-then-promote: a package that fails verification leaves no trace on disk. @throws NavCoreException.Verification if the signature or any layer hash does not verify.public suspend fun install(snpkg: File, cancel: CancelToken): InstallOutcome:installwith a cancellation handle. The core pollscancelbetween archive entries, before verification and before promotion; a tripped token (or a cancelled calling coroutine) yieldsInstallOutcome.Cancelledwith staging removed and nothing installed.public suspend fun installDirectory(packageDir: File): TerritoryInfo: Install an unpacked package directory (same verification rules).public suspend fun installDirectory(packageDir: File, cancel: CancelToken): InstallOutcome:installDirectorywith a cancellation handle; seeinstall.public suspend fun installFromChannel(territoryId: String, indexJson: String, indexSigBase64: String, fetcher: LayerFetcher, omit: List<MapLayerKind> = emptyList(), cancel: CancelToken = CancelToken()): ChannelInstallOutcome: InstallterritoryIdfrom its channel: the first-install counterpart ofapplyUpdate.indexJson/indexSigBase64are the exact served bytes of the channel index and its detached signature; the channel's latest version is installed, fetching only the layers not inomitthroughfetcher. Nothing is trusted but the pinned keys: the index signature, the manifest signature and every layer hash are checked, and the assembled package goes through the full verification pass before it is promoted. Interrupted installs resume (verified layers stay in the layer cache). A trippedcancel(or a cancelled calling coroutine) yieldsChannelInstallOutcome.Cancelledwith nothing installed. @throws NavCoreException.Verification if a signature or hash does not verify, including aregion-id on a store without a region key.public suspend fun sync(territoryId: String, indexJson: String, indexSigBase64: String, fetcher: LayerFetcher, omit: List<MapLayerKind> = emptyList(), cancel: CancelToken = CancelToken()): ChannelSync: BringterritoryIdto the channel's latest version, whichever way that takes: a first install from the channel when it is not installed, a signed differential update when an older version is, nothing when it is already current. Updates go throughcheckForUpdate/applyUpdate, so a channel can never move an installed territory backwards.public suspend fun sync(territoryId: String, source: ChannelSource, apiKey: String? = null, omit: List<MapLayerKind> = emptyList(), cancel: CancelToken = CancelToken(), onBytes: ((Long) -> Unit)? = null): ChannelSync:syncover HTTPS: fetch the signed index fromsourceand every layer relative to it with anHttpChannelFetcher.cancelalso stops a transfer in progress.public suspend fun installCustomRegion(territoryId: String, indexUrl: String, indexSigUrl: String, apiKey: String? = null, omit: List<MapLayerKind> = emptyList(), cancel: CancelToken = CancelToken(), onBytes: ((Long) -> Unit)? = null): ChannelSync: Install, or update, a custom region from theterritory_id,index_urlandindex_sig_urlof aPOST /v1/jobs/territoryresult. A re-cut of the same area after the country is republished is the same id at a newer version, so calling this again is the update. @throws IllegalStateException if this store has noregionKeyHex. @throws IllegalArgumentException ifterritoryIdis not aregion-id orindexUrlis not anindex.jsonURL.public suspend fun verify(territoryId: String): TerritoryInfo: Re-verify an installed territory from disk: the manifest signature (against the key its id is partitioned to), the hash of every layer it holds and the absence of every layer it omitted. The on-demand integrity check for after a restore or a crash. @throws NavCoreException.Verification when the install must be repaired or reinstalled.public suspend fun setActive(territoryId: String): Unit: MarkterritoryIdactive; persisted atomically by the core.public suspend fun active(): String?: The active territory id, if one is set and still installed.public suspend fun activeTerritory(): TerritoryInfo?: The active territory's full info, if any.public suspend fun layerPath(territoryId: String, kind: MapLayerKind): File: Absolute path of one layer of an installed territory, e.g.MapLayerKind.ValhallaTilesfor the on-device router,MapLayerKind.Pmtilesfor MapLibre.public suspend fun territoryStyle(territoryId: String, theme: StyleTheme = StyleTheme.LIGHT): String: A complete MapLibre style JSON for an installed territory with local (offline) references, mirroring the web SDK'sbuildStyle(). Load it straight into MapLibre, the territory tile source points at the installed PMTiles layer via apmtiles://<absolute path>URL, so the map renders with radios off. Packages without a baked style layer get the default MapMap theme compiled on the fly.public suspend fun openSearch(territoryId: String): TerritorySearch: Open the installed territory's bundled geocode index for fully offline on-device search. The returned handle holds the index open (mmap-backed), create it once per territory and reuse it across queries (calls are synchronous and disk-bound; keep them off the main thread):kotlin val search = store.openSearch("uk") val places = search.search("watford gap", near = null, limit = 10u)public suspend fun remove(territoryId: String): Unit: Remove an installed territory (clears the active marker if needed).public suspend fun planUpdate(newManifestJson: String): UpdatePlan: Plan a differential update against a newly served (signed) manifest JSON: which layers must be downloaded, and how many bytes.public suspend fun checkForUpdate(territoryId: String, indexJson: String, indexSigBase64: String, fetcher: LayerFetcher): AvailableUpdate?: Check the signed update channel for a newer version of an installed territory. Fail-closed: the channel index signature is verified before anything else,fetcheris never invoked for a channel that does not verify against this store's pinned key. @param indexJson the exact bytes served asindex.json. @param indexSigBase64 the content ofindex.json.sig. @param fetcher the app's download transport (OkHttp, an air-gapped mirror, …), the core decides what to fetch and re-verifies all content itself. @return the available update, ornullwhen already on the channel's latest version. @throws NavCoreException.Verification if the index or remote manifest signature does not verify.public suspend fun applyUpdate(territoryId: String, newManifestJson: String, newManifestSigBase64: String, fetcher: LayerFetcher): UpdateResult: Apply a differential update: unchanged layers are hard-linked from the current install, only changed layers are fetched throughfetcher, the staged package is fully re-verified, and the swap is atomic. Any failure, transport, hash mismatch, bad signature, leaves the installed territory untouched; the active flag survives.public suspend fun applyUpdate(territoryId: String, newManifestJson: String, newManifestSigBase64: String, fetcher: LayerFetcher, cancel: CancelToken): UpdateOutcome:applyUpdatewith a cancellation handle. The core pollscancelbefore every layer download, between archive entries while unpacking, before each hash pass and before promotion; a tripped token (or a cancelled calling coroutine) yieldsUpdateOutcome.Cancelled. The installed version is untouched and staging removed; layers already fetched and verified stay in the resumable cache, so a later attempt with the same manifest re-fetches only what is missing. The token cannot interruptfetcherwhile it is inside a transfer: give the fetcher the same token and have it pollisCancelled()between chunks (or abort its request). Whatever the fetcher then throws, a tripped token reportsUpdateOutcome.Cancelledrather than a transport error.override fun close()
Example
import ai.mapmap.territory.ChannelSource
import ai.mapmap.territory.TerritoryKeys
import ai.mapmap.territory.TerritoryStore
import java.io.File
suspend fun installUk(filesDir: File) {
TerritoryStore(
rootDir = File(filesDir, "territories"),
verifyingKeyHex = TerritoryKeys.HOSTED_FACTORY_KEY_HEX,
regionKeyHex = TerritoryKeys.HOSTED_REGION_KEY_HEX,
).use { store ->
// First install or update, whichever is needed, from the hosted channel.
val result = store.sync("uk", ChannelSource.gateway(), apiKey = "snk_…")
store.setActive("uk")
println(result)
}
}
TtsStartup
Class · ai/mapmap/nav/VoiceGuidance.kt
public class TtsStartup<T>(private val languageTag: String?)
Pure init-order state machine for the asynchronous TextToSpeech
engine, unit-testable on any JVM, like VoiceProsody.
The platform silently drops setLanguage calls made before the engine
has finished initialising, so the language is applied in the SUCCESS
callback, and before any prompt deferred during startup is flushed,
so the first prompt already speaks in the configured voice.
| Property | Type | Default | Description |
|---|---|---|---|
var ready | Boolean | false | Whether the engine reported TextToSpeech.SUCCESS yet. |
Initialisers and methods
public fun defer(announcement: T): Boolean: Deferannouncementuntil init completes. Returnstruewhen it was deferred (engine not ready, the latest prompt wins);falsewhen the engine is ready and the caller should speak it now.public fun onInitSuccess(): InitActions<T>: Handle the engine's SUCCESS callback. Idempotent per prompt.
Nested: TtsStartup.InitActions.
Example
import ai.mapmap.nav.TtsStartup
// The start-up queue VoiceGuidance uses while TextToSpeech initialises: the latest prompt wins.
val startup = TtsStartup<String>(languageTag = "en-GB")
fun announce(text: String) {
if (!startup.defer(text)) println("speak now: $text")
}
fun onTtsReady() {
val actions = startup.onInitSuccess()
actions.flush?.let { println("speak deferred: $it") }
}
TtsStartup.InitActions
Class · ai/mapmap/nav/VoiceGuidance.kt
public data class InitActions<T>(val languageToSet: String?, val flush: T?)
What to do on init SUCCESS, in order: set the language, then flush.
| Property | Type | Default | Description |
|---|---|---|---|
val languageToSet | String? | ||
val flush | T? |
ValhallaMobileRouter
Class · ai/mapmap/routing/ValhallaMobileRouter.kt
public class ValhallaMobileRouter(configPath: String) : OfflineRouter, AutoCloseable
OfflineRouter backed by the on-device Valhalla engine
(ai.mapmap:valhalla-engine: Rallista/valhalla-mobile's wrapper, MIT,
https://github.com/Rallista/valhalla-mobile, compiled against the
Valhalla release and patch series the server builds tiles with; see
tools/mobile-engine/engine.pin).
valhalla-mobile's actor exposes exactly the
route(requestJson) -> responseJson shape the Rust core's LocalRouter
callback expects; the call crosses into it through
ValhallaActorBridge (see that file for why the seam is Java).
The engine is a compileOnly dependency of the SDK: apps that use
this class must declare ai.mapmap:valhalla-engine themselves (see
android/README.md). Do not use io.github.rallista:valhalla-mobile
instead: its releases carry a different Valhalla than the factory tiles
(0.5.1 to 0.6.3: 3.6.3, which answers 171 "No suitable edges" on them).
Routing is CPU-bound native work: call it through
OfflineRouting.route, which hops off the main thread.
Holds one native engine for its lifetime; reuse one router across
routes and close it when done.
@param configPath absolute path of a valhalla.json whose
mjolnir.tile_dir points at the territory's Valhalla tile layer.
Initialisers and methods
override fun route(requestJson: String): Stringoverride fun close(): Unit: Release the native engine. Routing after this throws.
Nested: ValhallaMobileRouter.Companion.
Example
import ai.mapmap.MapMap
import ai.mapmap.routing.OfflineRouting
import ai.mapmap.routing.ValhallaMobileRouter
import ai.mapmap.territory.TerritoryStore
import uniffi.mapmap.CostingModel
import uniffi.mapmap.MapLayerKind
import uniffi.mapmap.RoutePoint
import java.io.File
// On-device routing over an installed territory's Valhalla tiles.
suspend fun routeOffline(store: TerritoryStore, cacheDir: File) {
val tiles = store.layerPath("uk", MapLayerKind.ValhallaTiles)
ValhallaMobileRouter.fromTileDir(tiles, scratchDir = cacheDir).use { router ->
val route = OfflineRouting.route(
router,
listOf(RoutePoint(51.5072, -0.1276), RoutePoint(51.4545, -2.5879)),
costing = CostingModel.TRUCK,
adr = MapMap.defaultAdrProfile(),
)
println(route)
}
}
VoiceGuidance
Class · ai/mapmap/nav/VoiceGuidance.kt
public class VoiceGuidance(context: Context, language: String? = null, private val baseRate: Float = 1.0f) : AutoCloseable
Spoken turn-by-turn guidance over the platform TextToSpeech engine
(offline-capable, no network required with a device voice installed).
Feed every NavigationState (or raw GuidanceUpdate) from
NavigationEngine.navigate:
kotlin val voice = VoiceGuidance(context) engine.navigate(provider) .onEach { voice.handle(it.update) } .collect { render(it) } // … voice.close()
The core schedules each spoken prompt by its trigger distance and
repeats it on every update until it is superseded, so the speaking rule
is: announce each utteranceId exactly once, the first time it appears.
Severity maps to prosody and earcons via VoiceProsody; critical
prompts flush the queue. Off-route plays the warning earcon once per
episode. Observe isSpeaking / onSpeakingChanged to reflect live
speaking state in UI (e.g. a pulsing voice icon). Audio focus is
requested transiently with ducking
(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK) around each
announcement, so music dims rather than stops.
| Property | Type | Default | Description |
|---|---|---|---|
var isSpeaking | Boolean | false | Whether an utterance is currently being spoken or queued. Mirrors the transitions delivered to onSpeakingChanged. Guarded by synchronized(focusPolicy) like the underlying bookkeeping. |
var onSpeakingChanged | ((Boolean) -> Unit)? | null | Invoked on every speaking-state transition: true when the first utterance of a burst is handed to the engine, false once the last outstanding one ends (done, error, stop, mute or close). End transitions arrive on the TTS engine's callback thread, hop to the main thread before touching UI. |
var muted | Boolean | false | Whether announcements are muted. Toggle freely mid-drive. |
var volume | Float | 1.0f | Announcement volume, 0.0–1.0 (applied to speech and earcons). |
Initialisers and methods
public fun handle(update: GuidanceUpdate): Consume one guidance update. Cheap; call it for every emission ofNavigationEngine.navigate.public fun handle(state: NavigationState): Unit: Convenience overload forNavigationEngine.navigateemissions.override fun close(): Release the TTS engine, earcon player and audio focus.
Example
import ai.mapmap.nav.VoiceGuidance
import android.content.Context
fun voice(context: Context): VoiceGuidance =
VoiceGuidance(context, language = "en-GB").apply {
volume = 0.8f
onSpeakingChanged = { speaking -> println("speaking: $speaking") }
}
// For every NavigationState from NavigationEngine.navigate: voice.handle(state). Close it when done.
VoiceProsody.Prosody
Class · ai/mapmap/nav/VoiceGuidance.kt
public data class Prosody(val rate: Float, val pitch: Float, val interrupt: Boolean)
Speech parameters for one severity level.
| Property | Type | Default | Description |
|---|---|---|---|
val rate | Float | ||
val pitch | Float | ||
val interrupt | Boolean |
Enums (ai.mapmap)
ProbeUploadOutcome
Enum · ai/mapmap/nav/ProbeContribution.kt
public enum class ProbeUploadOutcome
The outcome of one upload attempt, surfaced through
HttpProbeUploader's result callback for observability and tests.
| Case | Description |
|---|---|
ACCEPTED | 202, accepted and stored. |
REFUSED | 403, the key is not opted in; dropped, not retried. |
NOT_ENABLED | 501, server collection is not enabled (SN_PROBE_DIR unset); dropped. |
REJECTED | 400 or any other 4xx, malformed/unacceptable; dropped, not retried. |
GAVE_UP | IO error or 5xx after exhausting retries; given up on. |
Interfaces (ai.mapmap)
ChannelSync, LocationProvider, OfflineRouter, ProbeUploader
ChannelSync
Interface · ai/mapmap/territory/TerritoryStore.kt
public sealed interface ChannelSync
What TerritoryStore.sync did.
Nested: ChannelSync.Installed, ChannelSync.Updated, ChannelSync.UpToDate, ChannelSync.Cancelled.
LocationProvider
Interface · ai/mapmap/nav/LocationProvider.kt
public interface LocationProvider
A source of location fixes for NavigationEngine.
Implementations: AndroidLocationProvider (the platform's fused
provider) for live navigation, ReplayLocationProvider (a
.drive.jsonl corpus) for QA and demos. Any cold Flow of samples in
ascending timestamp order qualifies.
| Property | Type | Default | Description |
|---|---|---|---|
val locations | Flow<LocationSample> | The stream of fixes. Collected once per navigation session. |
OfflineRouter
Interface · ai/mapmap/routing/OfflineRouter.kt
public interface OfflineRouter : LocalRouter
An on-device routing engine.
This is the Rust core's LocalRouter callback interface with a Kotlin
name: implementations execute a Valhalla turn-by-turn request JSON
synchronously and return the raw response JSON (either a route response
or a Valhalla error body, the core parses and classifies both).
The production implementation is ValhallaMobileRouter; tests inject
fakes that return canned responses.
ProbeUploader
Interface · ai/mapmap/nav/ProbeContribution.kt
public interface ProbeUploader
Where a completed probe batch goes. Called off the navigation flow's hot
path: enqueue must be non-blocking and must never throw.
Initialisers and methods
public fun enqueue(body: String): Hand one probe body, the JSON string fromuniffi.mapmap.ProbeCollector.finishJson, off to be POSTed to/v1/probe. Fire-and-forget.
Objects (ai.mapmap)
AdrCompliance, AndroidLocationProvider.Companion, ChannelSource.Companion, ChannelSync.Cancelled, DriveCorpus.Companion, GuidanceDisplay, MapMap, OfflineRouting, ReplayLocationProvider.Companion, TerritoryKeys, ValhallaConfigWriter, ValhallaMobileRouter.Companion, VoiceProsody
AdrCompliance
Object · ai/mapmap/adr/AdrCompliance.kt
public object AdrCompliance
On-device ADR 8.6.4 dangerous-goods enforcement.
Two enforcement points, both running the same Rust domain model
(sn-adr, conservative ADR 8.6.4 reading):
- Pre-route, pass the
AdrProfiletoai.mapmap.routing.OfflineRouting.route; the core merges the restrictions into Valhalla truck costing, so forbidden tunnels and undersized roads are excluded before a route exists. - En-route, call
checkTunnelagainst a tunnel's category (e.g. from map data ahead of the vehicle) to gate entry while driving, andforbiddenCategoriesto badge the whole profile in the UI.
Initialisers and methods
public fun checkTunnel(profile: AdrProfile, category: AdrTunnelCategory): AdrDecision: May the vehicle described byprofilepass through a tunnel ofcategory? Blocked decisions carry a human-readable reason citing ADR 8.6.4.public fun forbiddenCategories(profile: AdrProfile): List<AdrTunnelCategory>: All tunnel categories the vehicle is forbidden from, ascending. Empty when unrestricted.public fun isTunnelRestricted(profile: AdrProfile): Boolean: True when the profile is barred from at least one tunnel category.public fun validateProfile(profile: AdrProfile): List<String>: Validate a profile's physical plausibility before it goes anywhere near routing. Returns a list of human-readable problems; empty means valid. Pure Kotlin, safe to call from previews and unit tests without the native library.
AndroidLocationProvider.Companion
Object · ai/mapmap/nav/AndroidLocationProvider.kt
public companion object
Initialisers and methods
public fun Location.toSample(): LocationSample: Map a platformLocationonto the SDK'sLocationSample.
ChannelSource.Companion
Object · ai/mapmap/territory/ChannelSource.kt
public companion object
No trailing slash; layer paths are appended after a /.
| Property | Type | Default | Description |
|---|---|---|---|
val DEFAULT_GATEWAY | String | "https://api.mapmap.ai" | The hosted gateway. |
Initialisers and methods
public fun gateway(baseUrl: String = DEFAULT_GATEWAY): ChannelSource: A gateway's country channel:GET /territories(the signed index) andGET /territories/index.sig.public fun customRegion(territoryId: String, indexUrl: String, indexSigUrl: String): ChannelSource: A custom region's own one-territory channel, from theindex_url/index_sig_urlof aPOST /v1/jobs/territoryresult. The gateway serves the index at<base>/v1/territories/<id>/index.jsonand the layers under<base>/territories/<id>/..., so the layer base is<base>. Any other.../index.json(a mirror of the region directory, laid out asSN_REGION_DIR/<id>/) resolves layers next to the index. @throws IllegalArgumentException ifterritoryIdis not a custom-region id orindexUrldoes not end inindex.json.public fun isCustomRegionId(territoryId: String): Boolean: WhetherterritoryIdhas the shape the gateway gives custom regions.
ChannelSync.Cancelled
Object · ai/mapmap/territory/TerritoryStore.kt
public data object Cancelled : ChannelSync
The CancelToken was tripped; nothing changed on disk.
DriveCorpus.Companion
Object · ai/mapmap/replay/DriveCorpus.kt
public companion object
| Property | Type | Default | Description |
|---|---|---|---|
val FORMAT_VERSION | Int | 1 | The corpus format version this parser accepts. |
Initialisers and methods
public fun parse(jsonl: String): DriveCorpus: Parse and validate a corpus from JSON-lines text. @throws CorpusFormatException describing the first violation, with its 1-based line number where applicable.
GuidanceDisplay
Object · ai/mapmap/nav/NavigationState.kt
public object GuidanceDisplay
Pure display mappers for GuidanceUpdate. Kept free of native calls so
they are unit-testable on any JVM.
Initialisers and methods
public fun instruction(update: GuidanceUpdate): String?: The instruction to show for the current update, if any.public fun severity(update: GuidanceUpdate): InstructionSeverity: How urgently the update should be surfaced (see the core'sInstructionSeverityfor the derivation). Off-route is aInstructionSeverity.WARNING, the driver has left the route and a recalculation is due; arrival is routine.public fun formatDistance(metres: Double): String: Format a distance in metres for guidance display: metres under 1 km (10 m steps under 100 m, 50 m steps above), kilometres with one decimal from 1 km.public fun summarise(update: GuidanceUpdate): String: One-line status suitable for a debug HUD or notification.
MapMap
Object · ai/mapmap/MapMap.kt
public object MapMap
Entry point for the MapMap Android SDK.
The SDK is a thin, idiomatic Kotlin layer over the Rust navigation core
(sn-nav-core, shipped as libsn_nav_core.so). The raw UniFFI bindings
live in uniffi.mapmap (and uniffi.ferrostar, which is linked
into the same native library); everything under ai.mapmap
is the supported surface:
ai.mapmap.territory.TerritoryStore, signed offline territory packages (install / verify / activate / update planning).ai.mapmap.routing.OfflineRouting, on-device Valhalla routing with ADR dangerous-goods enforcement merged into every request.ai.mapmap.adr.AdrCompliance, pre-route and en-route ADR 8.6.4 tunnel checks.ai.mapmap.nav.NavigationEngine, turn-by-turn guidance over a computed route, fed by anyai.mapmap.nav.LocationProvider.
Initialisers and methods
public fun ensureLoaded(): Eagerly load the native core and verify the bindings match it. Calling this is optional, the first native call loads the library lazily, but doing it at app start surfaces packaging problems (missing ABI, mismatched binding checksums) as an immediateUnsatisfiedLinkErrorinstead of a mid-drive crash.public fun defaultGuidanceConfig(): GuidanceConfig: AGuidanceConfigwith the core's documented defaults.public fun defaultAdrProfile(): AdrProfile: AnAdrProfilewith the core's documented defaults: EU maximum authorised dimensions (Council Directive 96/53/EC), no dangerous goods.
OfflineRouting
Object · ai/mapmap/routing/OfflineRouting.kt
public object OfflineRouting
On-device route computation.
The Rust core builds the Valhalla request (merging ADR dangerous-goods
and dimensional costing options, rejecting conflicts), the injected
OfflineRouter executes it against local tiles, and the core parses the
response into a RouteResult whose valhallaResponseJson feeds
ai.mapmap.nav.NavigationEngine.
Initialisers and methods
public fun requireCompatibleCosting(costing: CostingModel, adr: AdrProfile?): ADR profiles ride on Valhalla truck costing options; requesting any other costing model with an ADR profile is a contract violation the Rust core rejects. Checked here too so the failure is a fast, clearly-attributedIllegalArgumentExceptionrather than a routing error after the FFI hop.public suspend fun route(router: LocalRouter, waypoints: List<RoutePoint>, costing: CostingModel = CostingModel.AUTO, adr: AdrProfile? = null, dispatcher: CoroutineDispatcher = Dispatchers.Default): RouteResult: Compute a route on-device. @param router the on-device engine, usually aValhallaMobileRouter. @param waypoints at least twoRoutePoints, in visit order. @param costing the Valhalla costing model; must beCostingModel.TRUCKwhenadris supplied. @param adr optional dangerous-goods/dimensional profile, when set, the request is built with the restrictions merged in, so illegal roads and tunnels are excluded before the route exists. @throws NavCoreException.Routing when the engine returns a Valhalla error body (e.g. no route, no tiles for the area).public fun buildRequest(waypoints: List<RoutePoint>, costing: CostingModel = CostingModel.AUTO, adr: AdrProfile? = null): String: Build the raw Valhalla request JSON without executing it, for callers that drive the engine themselves or log requests for audit.public fun parseResponse(responseJson: String): RouteResult: Parse a raw engine response into aRouteResult.
ReplayLocationProvider.Companion
Object · ai/mapmap/nav/ReplayLocationProvider.kt
public companion object
Initialisers and methods
public fun DriveFix.toSample(epochStartMs: Long): LocationSample: Map one corpus fix to aLocationSamplerebased onepochStartMs.
TerritoryKeys
Object · ai/mapmap/territory/TerritoryKeys.kt
public object TerritoryKeys
The public halves of the keys that sign MapMap's hosted territory
packages, for pinning in an app. Both are ed25519 public keys as 64 hex
characters, the form TerritoryStore takes.
Pin them at build time; never read either from the network. An app that runs its own factory or region signer passes its own keys instead.
| Property | Type | Default | Description |
|---|---|---|---|
val HOSTED_FACTORY_KEY_HEX | String | "c2230696626a1ecbc61cf9ac141eabea5a3a1a15dab70d2acc110bec79108bcf" | The factory key: verifies every country package on the hosted channel (https://api.mapmap.ai/territories). Also published at mapmap.ai/docs/territories. |
val HOSTED_REGION_KEY_HEX | String | "6f60f17bc31be2f7696cb957b2188416741e09cb3e7bdec2719fe553213be107" | The region key: verifies custom regions (region- ids) cut by the hosted gateway (POST /v1/jobs/territory). The core accepts it for region- ids ONLY, and never the factory key for them, so a leaked region key cannot forge a country package. Pass it as TerritoryStore(regionKeyHex = ...). |
ValhallaConfigWriter
Object · ai/mapmap/routing/ValhallaConfigWriter.kt
public object ValhallaConfigWriter
Writes the valhalla.json the on-device Valhalla actor needs.
The document is Valhalla's own complete default config
(valhalla_build_config, MIT,
https://github.com/valhalla/valhalla/blob/master/scripts/valhalla_build_config),
bundled as valhalla-defaults.json next to this class, with the tile
source and a mobile-sized cache set on top. The actor reads many keys
(every service_limits section, loki, thor, meili) with no
compiled-in fallback: a config carrying only mjolnir makes every route
fail with "No such node (service_limits.isochrone.max_contours)", which
is what this writer produced before (found routing a custom region on a
device, CustomRegionDeviceTest). The iOS writer bundles the same file.
| Property | Type | Default | Description |
|---|---|---|---|
val DEFAULT_MAX_CACHE_BYTES | Long | 268_435_456L | Mobile default for mjolnir.max_cache_size (bytes). |
Initialisers and methods
public fun configJson(tileDir: File, maxCacheBytes: Long = DEFAULT_MAX_CACHE_BYTES): String: Render the config document for a routing-tile directory (the territory'suniffi.mapmap.MapLayerKind.ValhallaTileslayer).
ValhallaMobileRouter.Companion
Object · ai/mapmap/routing/ValhallaMobileRouter.kt
public companion object
Initialisers and methods
public fun fromConfig(configFile: File): ValhallaMobileRouter: Create a router from an existingvalhalla.jsonconfig file.public fun fromTileDir(tileDir: File, scratchDir: File): ValhallaMobileRouter: Create a router for a territory's Valhalla tile directory, writing a config file underscratchDir(e.g.context.cacheDir).kotlin val tiles = store.layerPath(id, MapLayerKind.ValhallaTiles) val router = ValhallaMobileRouter.fromTileDir(tiles, context.cacheDir)
VoiceProsody
Object · ai/mapmap/nav/VoiceGuidance.kt
public object VoiceProsody
Prosody and earcon policy per InstructionSeverity, pure and
unit-testable on any JVM (the platform wiring lives in VoiceGuidance).
The core derives severity (see InstructionSeverity in
crates/sn-nav-core): INFO for routine manoeuvres, WARNING when
approaching a restriction (toll, ferry, and off-route), CRITICAL for
prohibitions (ADR tunnel block, gate).
Initialisers and methods
public fun prosody(severity: InstructionSeverity, baseRate: Float = 1.0f): Prosody: Prosody forseverityatbaseRate(default 1.0).public fun earconRes(severity: InstructionSeverity): Int?: The earcon raw resource forseverity, ornullwhen the severity plays none by default (INFO stays silent so a chime does not precede every routine manoeuvre). Assets are generated byscripts/generate-earcons.py.
Nested: VoiceProsody.Prosody.
Functions (ai.mapmap)
Flow<NavigationState>.contributingProbe
Flow<NavigationState>.contributingProbe
Function · ai/mapmap/nav/ProbeContribution.kt
public fun Flow<NavigationState>.contributingProbe(config: ProbeConfig, uploader: ProbeUploader, routeRef: String? = null, territory: String? = null, vehicleClass: String? = null, now: () -> Long = System::currentTimeMillis): Flow<NavigationState>
Accumulates an aggregate probe batch from a navigation stream and uploads it
once the trip ends. A transparent pass-through when config is disabled
(the shipped default): no collector is constructed and nothing is uploaded,
so leaving collection off costs nothing.
Wire it right onto the guidance stream:
engine.navigate(provider) .contributingProbe( ProbeConfig(enabled = consentGranted), HttpProbeUploader("https://api.mapmap.ai", apiKey), routeRef = servedRouteToken, territory = "uk", vehicleClass = "truck_40t", ) .collect { render(it) }
Consent is the caller's responsibility: only pass enabled = true for a key
whose operator has set probe_opt_in and, for a consumer app, with the
user's opt-in consent. See docs/PROBE-SDK-INTEGRATION.md.
Only aggregates leave the device: the collector is architecturally incapable of emitting a trajectory, and the first/last stretch of every trip is discarded on-device.
@param routeRef opaque served-route token so the server can resolve segment indices; @param vehicleClass a costing class only (never a registration, VIN or driver id); @param now injectable clock for deterministic tests.
uniffi.mapmap
Classes (uniffi.mapmap)
AdrDecision, AdrDecision.Blocked, AdrProfile, AvailableUpdate, BannerLine, CancelToken, ChangedLayer, ChannelInstallOutcome, ChannelInstallOutcome.Installed, ChannelInstallResult, FasterRouteCandidate, FasterRouteConfig, FasterRouteRecommendation, FetchException, FetchException.Transport, GuidanceConfig, GuidanceSession, GuidanceUpdate, GuidanceUpdate.Navigating, GuidanceUpdate.OffRoute, InstallOutcome, InstallOutcome.Installed, LaneGuidance, LayerFetcherImpl, LocalRouterImpl, MapLayerKind, MapLayerKind.Extra, NavCoreException, NavCoreException.Guidance, NavCoreException.InvalidArgument, NavCoreException.LayerNotInstalled, NavCoreException.Routing, NavCoreException.Search, NavCoreException.Territory, NavCoreException.Verification, OdRecord, Place, ProbeBatch, ProbeCollector, ProbeConfig, ProbeEvent, ProbeEvent.EtaOutcome, ProbeEvent.OffRoute, RerouteAnchor, RerouteConfig, RerouteDecision, RerouteReason, RerouteReason.FasterRoute, RerouteReason.OffRoute, RerouteState, RerouteState.OffRouteSuspected, RerouteWaypoint, RouteManeuver, RoutePoint, RouteResult, RouteSummary, SegmentAggregate, SnappedFix, SpeedLimit, SpeedLimit.Known, SpokenPrompt, TerritoryInfo, TerritoryManager, TerritorySearch, UpdateOutcome, UpdateOutcome.Applied, UpdatePlan, UpdateResult, VisualBanner
AdrDecision
Class · uniffi/mapmap/mapmap.kt
sealed class AdrDecision
Outcome of a tunnel-entry check, mirroring [sn_adr::Decision].
Nested: AdrDecision.Allowed, AdrDecision.Blocked.
AdrDecision.Blocked
Class · uniffi/mapmap/mapmap.kt
data class Blocked(val reason: String) : AdrDecision()
Passage is forbidden.
| Property | Type | Default | Description |
|---|---|---|---|
val reason | String |
AdrProfile
Class · uniffi/mapmap/mapmap.kt
data class AdrProfile (var heightM: Double = 4.0, var widthM: Double = 2.55, var lengthM: Double = 16.5, var grossWeightT: Double = 40.0, var axleLoadT: Double? = null, var axleCount: UInt? = null, var hazmat: Boolean = false, var tunnelCode: AdrTunnelCode? = null)
Vehicle profile for ADR and dimensional enforcement, mirroring
[sn_adr::AdrVehicleProfile]. Defaults are the EU maximum authorised
dimensions (Council Directive 96/53/EC) with no dangerous goods.
| Property | Type | Default | Description |
|---|---|---|---|
var heightM | Double | 4.0 | |
var widthM | Double | 2.55 | |
var lengthM | Double | 16.5 | |
var grossWeightT | Double | 40.0 | |
var axleLoadT | Double? | null | |
var axleCount | UInt? | null | |
var hazmat | Boolean | false | |
var tunnelCode | AdrTunnelCode? | null |
AvailableUpdate
Class · uniffi/mapmap/mapmap.kt
data class AvailableUpdate (var version: String, var changedLayers: List<ChangedLayer>, var installedBytes: ULong, var manifestJson: String, var manifestSig: String)
An update the channel offers for an installed territory.
| Property | Type | Default | Description |
|---|---|---|---|
var version | String | ||
var changedLayers | List<ChangedLayer> | ||
var installedBytes | ULong | ||
var manifestJson | String | ||
var manifestSig | String |
BannerLine
Class · uniffi/mapmap/mapmap.kt
data class BannerLine (var text: String, var maneuverType: String?, var maneuverModifier: String?, var roundaboutExitDegrees: UShort?, var exitNumbers: List<String>, var lanes: List<LaneGuidance>)
One line of a visual banner (primary/secondary/sub).
| Property | Type | Default | Description |
|---|---|---|---|
var text | String | ||
var maneuverType | String? | ||
var maneuverModifier | String? | ||
var roundaboutExitDegrees | UShort? | ||
var exitNumbers | List<String> | ||
var lanes | List<LaneGuidance> |
CancelToken
Class · uniffi/mapmap/mapmap.kt
open class CancelToken: Disposable, AutoCloseable, CancelTokenInterface
A cancellation handle for an in-flight territory install or update.
The install calls on TerritoryManager block the calling thread for
as long as a multi-gigabyte package takes to download, unpack and
verify. Create a token, pass it to one of the _cancellable variants
running on a background thread, and call [CancelToken::cancel] from
the UI thread when the user taps Cancel. The install polls it at safe
points and returns [InstallOutcome::Cancelled] /
[UpdateOutcome::Cancelled] with its staging directory removed: no
partial package is left on disk, the previously installed version is
untouched, and layers that had already been verified stay in the
resumable cache for the next attempt. Cancelling after the call has
returned changes nothing.
The token cannot interrupt a LayerFetcher blocked in a transfer:
give the fetcher the same token and have it poll
[CancelToken::is_cancelled] between chunks (or abort its request when
the app cancels). Whatever the fetcher then returns, the install
reports Cancelled, not a transport error.
Initialisers and methods
constructor(): A fresh, uncancelled token.override fun destroy()override fun close()override fun cancel(): Request cancellation. Idempotent and safe from any thread.override fun isCancelled(): Boolean: Whether [Self::cancel] has been called.
ChangedLayer
Class · uniffi/mapmap/mapmap.kt
data class ChangedLayer (var kind: String, var path: String, var bytes: ULong)
One layer that a territory update must download.
| Property | Type | Default | Description |
|---|---|---|---|
var kind | String | ||
var path | String | ||
var bytes | ULong |
ChannelInstallOutcome
Class · uniffi/mapmap/mapmap.kt
sealed class ChannelInstallOutcome
How a channel install ended.
Nested: ChannelInstallOutcome.Installed, ChannelInstallOutcome.Cancelled.
ChannelInstallOutcome.Installed
Class · uniffi/mapmap/mapmap.kt
data class Installed(val result: uniffi.mapmap.ChannelInstallResult) : ChannelInstallOutcome()
The package verified and was promoted.
| Property | Type | Default | Description |
|---|---|---|---|
val result | uniffi.mapmap.ChannelInstallResult |
ChannelInstallResult
Class · uniffi/mapmap/mapmap.kt
data class ChannelInstallResult (var territory: TerritoryInfo, var layersFetched: UInt, var layersReused: UInt, var bytesDownloaded: ULong)
What [TerritoryManager::install_from_channel] did.
| Property | Type | Default | Description |
|---|---|---|---|
var territory | TerritoryInfo | ||
var layersFetched | UInt | ||
var layersReused | UInt | ||
var bytesDownloaded | ULong |
FasterRouteCandidate
Class · uniffi/mapmap/mapmap.kt
data class FasterRouteCandidate (var id: String?, var durationS: Double)
One candidate route for the remaining journey, summarised from the router's response (a primary route or an alternate).
| Property | Type | Default | Description |
|---|---|---|---|
var id | String? | ||
var durationS | Double |
FasterRouteConfig
Class · uniffi/mapmap/mapmap.kt
data class FasterRouteConfig (var checkIntervalS: Double = 120.0, var minSavingS: UInt = 180u, var minSavingFrac: Double = 0.08, var dismissSuppressS: Double = 600.0, var maneuverBlackoutS: Double = 60.0, var enabled: Boolean = true)
Faster-route evaluator configuration, flattened for FFI like
[crate::reroute::RerouteConfig].
| Property | Type | Default | Description |
|---|---|---|---|
var checkIntervalS | Double | 120.0 | |
var minSavingS | UInt | 180u | |
var minSavingFrac | Double | 0.08 | |
var dismissSuppressS | Double | 600.0 | |
var maneuverBlackoutS | Double | 60.0 | |
var enabled | Boolean | true |
FasterRouteRecommendation
Class · uniffi/mapmap/mapmap.kt
data class FasterRouteRecommendation (var savesS: UInt, var candidateIdx: UInt)
A recommendation to switch to a faster candidate route.
| Property | Type | Default | Description |
|---|---|---|---|
var savesS | UInt | ||
var candidateIdx | UInt |
FetchException
Class · uniffi/mapmap/mapmap.kt
sealed class FetchException: Exception()
A transport failure thrown by a foreign LayerFetcher
implementation.
Nested: FetchException.Transport, FetchException.ErrorHandler.
FetchException.Transport
Class · uniffi/mapmap/mapmap.kt
class Transport(override val message: String) : FetchException()
The download failed (network, storage, cancelled, …).
| Property | Type | Default | Description |
|---|---|---|---|
val message | String |
GuidanceConfig
Class · uniffi/mapmap/mapmap.kt
data class GuidanceConfig (var stepAdvanceDistanceM: UShort = 20u, var minimumHorizontalAccuracyM: UShort = 25u, var routeDeviationThresholdM: Double = 25.0, var snapCourseToRoute: Boolean = true, var waypointAdvanceRangeM: Double = 100.0)
Guidance behaviour configuration, flattened for FFI.
Maps onto Ferrostar's NavigationControllerConfig: a
distance-to-end-of-step advance condition, a static-threshold route
deviation tracker and course snapping.
| Property | Type | Default | Description |
|---|---|---|---|
var stepAdvanceDistanceM | UShort | 20u | |
var minimumHorizontalAccuracyM | UShort | 25u | |
var routeDeviationThresholdM | Double | 25.0 | |
var snapCourseToRoute | Boolean | true | |
var waypointAdvanceRangeM | Double | 100.0 |
GuidanceSession
Class · uniffi/mapmap/mapmap.kt
open class GuidanceSession: Disposable, AutoCloseable, GuidanceSessionInterface
A turn-by-turn guidance session (see [crate::guidance]).
Thread-safe: the mutable Ferrostar navigation state is guarded by a mutex, matching UniFFI's shared-object concurrency model.
Initialisers and methods
constructor(routeResponseJson: String, config: GuidanceConfig): Create a session from a Valhalla route response JSON (as returned byroute_offlineinvalhalla_response_json).override fun destroy()override fun close()@Throws(NavCoreException::class) override fun advanceToNextStep(): GuidanceUpdate: Manually advance to the next step (e.g. in a tunnel with no GNSS).override fun totalSteps(): UInt: Number of steps in the route, including the arrival step.@Throws(NavCoreException::class) override fun updateLocation(lat: Double, lon: Double, timestampMs: Long, speedMps: Double?, courseDeg: Double?, horizontalAccuracyM: Double?): GuidanceUpdate: Feed a location fix; returns the updated guidance state.horizontal_accuracy_mdefaults to0.0(trusted exactly) when absent; pass the platform's reported accuracy when available so step advance and deviation gating behave correctly.
GuidanceUpdate
Class · uniffi/mapmap/mapmap.kt
sealed class GuidanceUpdate
The guidance state reported after each location update, flattened for
FFI from Ferrostar's TripState.
The Navigating variant is deliberately larger than the others: it is
the steady-state payload and the FFI shape (UniFFI enums cannot box),
and one allocation per location fix is irrelevant next to the fix
cadence.
Nested: GuidanceUpdate.Navigating, GuidanceUpdate.Arrived, GuidanceUpdate.OffRoute.
GuidanceUpdate.Navigating
Class · uniffi/mapmap/mapmap.kt
data class Navigating(val stepIndex: UInt, val distanceToNextManeuverM: Double, val distanceRemainingM: Double, val durationRemainingS: Double, val currentInstruction: String, val deviationM: Double?, val visual: uniffi.mapmap.VisualBanner?, val spoken: uniffi.mapmap.SpokenPrompt?, val snapped: uniffi.mapmap.SnappedFix?, val severity: uniffi.mapmap.InstructionSeverity, val speedLimit: uniffi.mapmap.SpeedLimit?) : GuidanceUpdate()
Actively navigating.
| Property | Type | Default | Description |
|---|---|---|---|
val stepIndex | UInt | ||
val distanceToNextManeuverM | Double | ||
val distanceRemainingM | Double | ||
val durationRemainingS | Double | ||
val currentInstruction | String | ||
val deviationM | Double? | ||
val visual | uniffi.mapmap.VisualBanner? | ||
val spoken | uniffi.mapmap.SpokenPrompt? | ||
val snapped | uniffi.mapmap.SnappedFix? | ||
val severity | uniffi.mapmap.InstructionSeverity | ||
val speedLimit | uniffi.mapmap.SpeedLimit? |
GuidanceUpdate.OffRoute
Class · uniffi/mapmap/mapmap.kt
data class OffRoute(val deviationM: Double) : GuidanceUpdate()
The user has left the route entirely (beyond the configured deviation threshold from every remaining step). The platform layer should recalculate.
| Property | Type | Default | Description |
|---|---|---|---|
val deviationM | Double |
InstallOutcome
Class · uniffi/mapmap/mapmap.kt
sealed class InstallOutcome
How a cancellable install ended.
Nested: InstallOutcome.Installed, InstallOutcome.Cancelled.
InstallOutcome.Installed
Class · uniffi/mapmap/mapmap.kt
data class Installed(val territory: uniffi.mapmap.TerritoryInfo) : InstallOutcome()
The package verified and was promoted.
| Property | Type | Default | Description |
|---|---|---|---|
val territory | uniffi.mapmap.TerritoryInfo |
LaneGuidance
Class · uniffi/mapmap/mapmap.kt
data class LaneGuidance (var directions: List<String>, var active: Boolean, var activeDirection: String?)
One lane at the upcoming maneuver, for lane-diagram UIs.
| Property | Type | Default | Description |
|---|---|---|---|
var directions | List<String> | ||
var active | Boolean | ||
var activeDirection | String? |
LayerFetcherImpl
Class · uniffi/mapmap/mapmap.kt
open class LayerFetcherImpl: Disposable, AutoCloseable, LayerFetcher
The platform's download transport for over-the-air territory updates,
exported as a UniFFI callback interface like
[crate::routing::LocalRouter]: the core decides what to fetch and
cryptographically verifies everything; Kotlin/Swift decide how bytes
move (OkHttp, URLSession, an air-gapped mirror, …).
Initialisers and methods
override fun destroy()override fun close()@Throws(FetchException::class) override fun fetch(relPath: String, expectedBlake3: String, destPath: String): Download the channel-relativerel_path(e.g.territories/uk/2.0.0/layers/<addr>/valhalla.tar.zst) to the local filedest_path.expected_blake3is advisory (empty for signed metadata files); the core re-verifies all content itself.
LocalRouterImpl
Class · uniffi/mapmap/mapmap.kt
open class LocalRouterImpl: Disposable, AutoCloseable, LocalRouter
The injection point for the platform's on-device Valhalla binding.
valhalla-mobile (https://github.com/Rallista/valhalla-mobile) exposes
a route(request_json) -> response_json actor on both Android and iOS;
Kotlin/Swift implement this interface with that actor and pass it to
[crate::ffi::route_offline]. Exported as a UniFFI callback interface
(with_foreign) so the implementation lives in foreign code.
Initialisers and methods
override fun destroy()override fun close()override fun route(requestJson: String): String: Execute a Valhalla turn-by-turn request and return the raw response JSON (either a route response or a Valhalla error body).
MapLayerKind
Class · uniffi/mapmap/mapmap.kt
sealed class MapLayerKind
Map layer kind, mirroring [sn_package::LayerKind].
Nested: MapLayerKind.ValhallaTiles, MapLayerKind.Pmtiles, MapLayerKind.GeocodeIndex, MapLayerKind.PoiSidecar, MapLayerKind.Extra.
MapLayerKind.Extra
Class · uniffi/mapmap/mapmap.kt
data class Extra(val name: String) : MapLayerKind()
Any other layer kind, by its manifest string.
| Property | Type | Default | Description |
|---|---|---|---|
val name | String |
NavCoreException
Class · uniffi/mapmap/mapmap.kt
sealed class NavCoreException: Exception()
The flat error type crossing the FFI boundary.
Rich typed errors live on the Rust side (TerritoryError,
RoutingError, GuidanceError); foreign code gets a stable
category plus a human-readable message.
Nested: NavCoreException.Territory, NavCoreException.Verification, NavCoreException.Routing, NavCoreException.Guidance, NavCoreException.InvalidArgument, NavCoreException.Search, NavCoreException.LayerNotInstalled, NavCoreException.ErrorHandler.
NavCoreException.Guidance
Class · uniffi/mapmap/mapmap.kt
class Guidance(override val message: String) : NavCoreException()
Guidance session failure.
| Property | Type | Default | Description |
|---|---|---|---|
val message | String |
NavCoreException.InvalidArgument
Class · uniffi/mapmap/mapmap.kt
class InvalidArgument(override val message: String) : NavCoreException()
A caller-supplied argument was invalid.
| Property | Type | Default | Description |
|---|---|---|---|
val message | String |
NavCoreException.LayerNotInstalled
Class · uniffi/mapmap/mapmap.kt
class LayerNotInstalled(val territoryId: String, val kind: String, val detail: String) : NavCoreException()
The territory has a layer of that kind, but this install left it
out (see [TerritoryManager::install_from_channel]).
Its own case on purpose: it is not Territory (nothing failed),
not a corrupt install and not an unknown territory. The app knows
what it chose not to download, so this is the signal to offer the
download, not to report an error.
The human-readable sentence is detail, not message: a UniFFI
error variant with several fields, one of them named message,
generates a Kotlin class whose constructor property collides with
Throwable.message and does not compile. Single-field variants
(every other case here) are fine.
| Property | Type | Default | Description |
|---|---|---|---|
val territoryId | String | ||
val kind | String | ||
val detail | String | ||
val message | Human-readable description. |
NavCoreException.Routing
Class · uniffi/mapmap/mapmap.kt
class Routing(override val message: String) : NavCoreException()
Route request building or response parsing failure (including Valhalla error bodies from the on-device engine).
| Property | Type | Default | Description |
|---|---|---|---|
val message | String |
NavCoreException.Search
Class · uniffi/mapmap/mapmap.kt
class Search(override val message: String) : NavCoreException()
On-device geocode search failure (index missing, unreadable or of an unsupported schema version).
| Property | Type | Default | Description |
|---|---|---|---|
val message | String |
NavCoreException.Territory
Class · uniffi/mapmap/mapmap.kt
class Territory(override val message: String) : NavCoreException()
Territory storage or lifecycle failure.
| Property | Type | Default | Description |
|---|---|---|---|
val message | String |
NavCoreException.Verification
Class · uniffi/mapmap/mapmap.kt
class Verification(override val message: String) : NavCoreException()
A package failed cryptographic or integrity verification.
| Property | Type | Default | Description |
|---|---|---|---|
val message | String |
OdRecord
Class · uniffi/mapmap/mapmap.kt
data class OdRecord (var originCell: String, var destCell: String, var departBucket: String)
Coarse origin/destination for a trip. Both cells are geohashes of
suppressed (mid-trip) positions, so they are already
[ProbeConfig::trip_end_suppression_m] away from the true ends.
| Property | Type | Default | Description |
|---|---|---|---|
var originCell | String | ||
var destCell | String | ||
var departBucket | String |
Place
Class · uniffi/mapmap/mapmap.kt
data class Place (var id: String, var kind: PlaceKind, var name: String, var housenumber: String?, var street: String?, var locality: String?, var region: String?, var postcode: String?, var countryCode: String, var lat: Double, var lon: Double, var categories: List<String>, var importance: Float, var distanceM: Double?)
One on-device search result: the matched document's display and context fields plus its position.
| Property | Type | Default | Description |
|---|---|---|---|
var id | String | ||
var kind | PlaceKind | ||
var name | String | ||
var housenumber | String? | ||
var street | String? | ||
var locality | String? | ||
var region | String? | ||
var postcode | String? | ||
var countryCode | String | ||
var lat | Double | ||
var lon | Double | ||
var categories | List<String> | ||
var importance | Float | ||
var distanceM | Double? |
ProbeBatch
Class · uniffi/mapmap/mapmap.kt
data class ProbeBatch (var probeFormat: UInt, var territory: String?, var vehicleClass: String?, var routeRef: String?, var segments: List<SegmentAggregate>, var events: List<ProbeEvent>, var od: OdRecord?)
A completed trip's aggregates, ready for the platform layer to POST to the probe ingest endpoint. Contains no trajectory.
| Property | Type | Default | Description |
|---|---|---|---|
var probeFormat | UInt | ||
var territory | String? | ||
var vehicleClass | String? | ||
var routeRef | String? | ||
var segments | List<SegmentAggregate> | ||
var events | List<ProbeEvent> | ||
var od | OdRecord? |
ProbeCollector
Class · uniffi/mapmap/mapmap.kt
open class ProbeCollector: Disposable, AutoCloseable, ProbeCollectorInterface
On-device probe collector. Feed it every guidance update with the fix's
position, speed and timestamp; call finish at
arrival or trip abandonment to get the ProbeBatch to upload.
Interior mutability (a Mutex) lets the FFI methods take &self, matching
the [crate::guidance::GuidanceSession] object shape.
Initialisers and methods
constructor(config: ProbeConfig): Create a collector with the given configuration.override fun destroy()override fun close()override fun finish(arrived: Boolean, timestampMs: Long): ProbeBatch: Close the trip and return the batch to upload.arriveddistinguishes a completed trip from an abandoned one (both apply end suppression).override fun finishJson(arrived: Boolean, timestampMs: Long): String?: Close the trip and return the exact JSON body toPOST /v1/probe, orNonewhen the batch carries nothing worth uploading. This is the single canonical serialiser for the probe wire format, platform code should upload this verbatim rather than re-encoding the record, so the wire form can never drift from what the gateway ingests.override fun observe(update: GuidanceUpdate, fixLat: Double, fixLon: Double, speedMps: Double?, timestampMs: Long): Feed one guidance update and its fix.speed_mpsis the device's reported ground speed when available (preferred); passNoneto let the collector estimate it from successive positions.override fun setRouteRef(routeRef: String): Set the opaque served-route token so the server can resolve segments.override fun setTerritory(territory: String): Set the territory id stamped into the batch.override fun setVehicleClass(vehicleClass: String): Set the vehicle costing class stamped into the batch (a class only, never a vehicle or driver identifier).
ProbeConfig
Class · uniffi/mapmap/mapmap.kt
data class ProbeConfig (var enabled: Boolean = false, var tripEndSuppressionM: Double = 500.0, var minSegmentObservations: UInt = 1u, var timeBucketMinutes: UInt = 5u, var odCellPrecision: UByte = 5u, var collectOd: Boolean = true)
Probe collector configuration, flattened for FFI like
[crate::guidance::GuidanceConfig].
Collection is off by default: enabled must be set explicitly (and, in
deployment, gated on the fleet customer's opt-in). Everything a batch
contains follows from these knobs.
| Property | Type | Default | Description |
|---|---|---|---|
var enabled | Boolean | false | |
var tripEndSuppressionM | Double | 500.0 | |
var minSegmentObservations | UInt | 1u | |
var timeBucketMinutes | UInt | 5u | |
var odCellPrecision | UByte | 5u | |
var collectOd | Boolean | true |
ProbeEvent
Class · uniffi/mapmap/mapmap.kt
sealed class ProbeEvent
A coarse, time-bucketed event within a trip.
Nested: ProbeEvent.OffRoute, ProbeEvent.EtaOutcome.
ProbeEvent.EtaOutcome
Class · uniffi/mapmap/mapmap.kt
data class EtaOutcome(val predictedS: Double, val actualS: Double, val routeLenKmBucket: String) : ProbeEvent()
The realised trip duration against the engine's first estimate. Feeds ETA-accuracy calibration; carries no location.
| Property | Type | Default | Description |
|---|---|---|---|
val predictedS | Double | ||
val actualS | Double | ||
val routeLenKmBucket | String |
ProbeEvent.OffRoute
Class · uniffi/mapmap/mapmap.kt
data class OffRoute(val todBucket: String, val deviationBandM: UInt) : ProbeEvent()
The vehicle left the route (a confirmed off-route condition from guidance). Carries only the time bucket and a coarse deviation band.
| Property | Type | Default | Description |
|---|---|---|---|
val todBucket | String | ||
val deviationBandM | UInt |
RerouteAnchor
Class · uniffi/mapmap/mapmap.kt
data class RerouteAnchor (var lat: Double, var lon: Double, var courseDeg: Double?)
The point and course a recalculated route should depart from.
| Property | Type | Default | Description |
|---|---|---|---|
var lat | Double | ||
var lon | Double | ||
var courseDeg | Double? |
RerouteConfig
Class · uniffi/mapmap/mapmap.kt
data class RerouteConfig (var minConsecutiveOffrouteFixes: UInt = 3u, var minOffrouteDurationS: Double = 5.0, var minIntervalBetweenReroutesS: Double = 10.0, var enabled: Boolean = true)
Reroute controller configuration, flattened for FFI like
[crate::guidance::GuidanceConfig].
Both the count gate and the duration gate must pass for a reroute to be confirmed: a burst of fixes arriving in a fraction of a second should not out-vote the duration requirement, and a slow trickle of fixes should not out-vote the count requirement.
| Property | Type | Default | Description |
|---|---|---|---|
var minConsecutiveOffrouteFixes | UInt | 3u | |
var minOffrouteDurationS | Double | 5.0 | |
var minIntervalBetweenReroutesS | Double | 10.0 | |
var enabled | Boolean | true |
RerouteDecision
Class · uniffi/mapmap/mapmap.kt
data class RerouteDecision (var reason: RerouteReason, var anchor: RerouteAnchor, var waypointsRemaining: List<RerouteWaypoint>)
A confirmed reroute: where to route from, where to, and why.
| Property | Type | Default | Description |
|---|---|---|---|
var reason | RerouteReason | ||
var anchor | RerouteAnchor | ||
var waypointsRemaining | List<RerouteWaypoint> |
RerouteReason
Class · uniffi/mapmap/mapmap.kt
sealed class RerouteReason
Why a reroute was requested.
Nested: RerouteReason.OffRoute, RerouteReason.FasterRoute.
RerouteReason.FasterRoute
Class · uniffi/mapmap/mapmap.kt
data class FasterRoute(val savesS: UInt) : RerouteReason()
A periodic re-evaluation found a faster route for the remaining
journey (see [crate::faster_route::FasterRouteEvaluator]); the
driver accepted the switch. saves_s is the estimated saving in
seconds versus staying on the current route.
| Property | Type | Default | Description |
|---|---|---|---|
val savesS | UInt |
RerouteReason.OffRoute
Class · uniffi/mapmap/mapmap.kt
data class OffRoute(val deviationM: Double) : RerouteReason()
The vehicle left the route line; deviation_m is the distance from
the route at the confirming fix.
| Property | Type | Default | Description |
|---|---|---|---|
val deviationM | Double |
RerouteState
Class · uniffi/mapmap/mapmap.kt
sealed class RerouteState
The controller's state after the most recent update, for UI and telemetry.
Nested: RerouteState.Monitoring, RerouteState.OffRouteSuspected, RerouteState.RerouteNeeded, RerouteState.CoolingDown.
RerouteState.OffRouteSuspected
Class · uniffi/mapmap/mapmap.kt
data class OffRouteSuspected(val count: UInt) : RerouteState()
Off route, but not yet confirmed, the count and/or duration gate has
not been met. count is the run of consecutive off-route fixes so far.
| Property | Type | Default | Description |
|---|---|---|---|
val count | UInt |
RerouteWaypoint
Class · uniffi/mapmap/mapmap.kt
data class RerouteWaypoint (var lat: Double, var lon: Double, var isBreak: Boolean)
One onward waypoint of the active route.
| Property | Type | Default | Description |
|---|---|---|---|
var lat | Double | ||
var lon | Double | ||
var isBreak | Boolean |
RouteManeuver
Class · uniffi/mapmap/mapmap.kt
data class RouteManeuver (var instruction: String, var maneuverType: UInt, var verbalPreTransitionInstruction: String?, var verbalPostTransitionInstruction: String?, var streetNames: List<String>, var distanceM: Double, var durationS: Double, var beginShapeIndex: UInt, var endShapeIndex: UInt, var roundaboutExitCount: UInt?)
One maneuver of the primary route, in SI units with shape indices into
[RouteResult::geometry]. Parsed once by the core so integrators never
re-parse the raw Valhalla JSON themselves.
| Property | Type | Default | Description |
|---|---|---|---|
var instruction | String | ||
var maneuverType | UInt | ||
var verbalPreTransitionInstruction | String? | ||
var verbalPostTransitionInstruction | String? | ||
var streetNames | List<String> | ||
var distanceM | Double | ||
var durationS | Double | ||
var beginShapeIndex | UInt | ||
var endShapeIndex | UInt | ||
var roundaboutExitCount | UInt? |
RoutePoint
Class · uniffi/mapmap/mapmap.kt
data class RoutePoint (var lat: Double, var lon: Double)
A route waypoint.
| Property | Type | Default | Description |
|---|---|---|---|
var lat | Double | ||
var lon | Double |
RouteResult
Class · uniffi/mapmap/mapmap.kt
data class RouteResult (var summary: RouteSummary, var geometry: List<RoutePoint> = listOf(), var maneuvers: List<RouteManeuver> = listOf(), var valhallaResponseJson: String, var osrmResponseJson: String)
Result of an offline route computation.
| Property | Type | Default | Description |
|---|---|---|---|
var summary | RouteSummary | ||
var geometry | List<RoutePoint> | listOf() | |
var maneuvers | List<RouteManeuver> | listOf() | |
var valhallaResponseJson | String | ||
var osrmResponseJson | String |
RouteSummary
Class · uniffi/mapmap/mapmap.kt
data class RouteSummary (var distanceM: Double, var durationS: Double, var hasToll: Boolean, var hasHighway: Boolean, var hasFerry: Boolean)
SI summary of a parsed route.
| Property | Type | Default | Description |
|---|---|---|---|
var distanceM | Double | ||
var durationS | Double | ||
var hasToll | Boolean | ||
var hasHighway | Boolean | ||
var hasFerry | Boolean |
SegmentAggregate
Class · uniffi/mapmap/mapmap.kt
data class SegmentAggregate (var stepIndex: UInt, var todBucket: String, var observations: UInt, var meanSpeedKmh: Double, var p85SpeedKmh: Double, var stoppedS: Double, var limitDeltaKmh: Double?)
One aggregated road segment: statistics for a step_index within the
served route, in one day-of-week × time-of-day bucket.
| Property | Type | Default | Description |
|---|---|---|---|
var stepIndex | UInt | ||
var todBucket | String | ||
var observations | UInt | ||
var meanSpeedKmh | Double | ||
var p85SpeedKmh | Double | ||
var stoppedS | Double | ||
var limitDeltaKmh | Double? |
SnappedFix
Class · uniffi/mapmap/mapmap.kt
data class SnappedFix (var lat: Double, var lon: Double, var courseDeg: Double?)
The route-snapped position for the current update.
This is Ferrostar's snapped_user_location: the raw fix projected
onto the route line, with the course snapped to the route direction
when [GuidanceConfig::snap_course_to_route] is on (the default).
Drive follow-cameras (course-up / chase views) from this, never the
raw fix, the raw GPS trace jitters and drifts off the carriageway.
| Property | Type | Default | Description |
|---|---|---|---|
var lat | Double | ||
var lon | Double | ||
var courseDeg | Double? |
SpeedLimit
Class · uniffi/mapmap/mapmap.kt
sealed class SpeedLimit
The posted speed limit for the current edge, for a speed-limit badge and over-limit warnings.
This is surfaced from the OSRM annotation.maxspeed that Ferrostar threads
through its navigation state (TripState::Navigating.annotation_json) at
the current geometry index, in the Mapbox shape
(https://docs.mapbox.com/api/navigation/directions/#route-leg-object). It
appears only when the route actually carries speed-limit data: on-device
that means the Valhalla graph was built with OSM maxspeed (and admin data
for implicit limits) and the engine emitted per-maneuver limits, which the
translator forwarded (see [sn_valhalla::valhalla::SpeedLimit]). With
stock data there is no annotation and [GuidanceUpdate::Navigating] reports
no limit at all, values are never invented.
Nested: SpeedLimit.Known, SpeedLimit.Unlimited, SpeedLimit.Unknown.
SpeedLimit.Known
Class · uniffi/mapmap/mapmap.kt
data class Known(val kmh: Double) : SpeedLimit()
A known posted limit, normalised to kilometres per hour regardless of the unit the route expressed it in.
| Property | Type | Default | Description |
|---|---|---|---|
val kmh | Double |
SpokenPrompt
Class · uniffi/mapmap/mapmap.kt
data class SpokenPrompt (var text: String, var ssml: String?, var triggerDistanceM: Double, var utteranceId: String)
The spoken prompt to synthesise for the upcoming maneuver.
| Property | Type | Default | Description |
|---|---|---|---|
var text | String | ||
var ssml | String? | ||
var triggerDistanceM | Double | ||
var utteranceId | String |
TerritoryInfo
Class · uniffi/mapmap/mapmap.kt
data class TerritoryInfo (var territoryId: String, var displayName: String, var version: String, var dataTimestamp: String, var west: Double, var south: Double, var east: Double, var north: Double, var totalBytes: ULong, var installedBytes: ULong, var omittedKinds: List<MapLayerKind>, var path: String, var active: Boolean)
Summary of one installed territory.
| Property | Type | Default | Description |
|---|---|---|---|
var territoryId | String | ||
var displayName | String | ||
var version | String | ||
var dataTimestamp | String | ||
var west | Double | ||
var south | Double | ||
var east | Double | ||
var north | Double | ||
var totalBytes | ULong | ||
var installedBytes | ULong | ||
var omittedKinds | List<MapLayerKind> | ||
var path | String | ||
var active | Boolean |
TerritoryManager
Class · uniffi/mapmap/mapmap.kt
open class TerritoryManager: Disposable, AutoCloseable, TerritoryManagerInterface
Manages signed offline territory packages (see [crate::territory]).
Initialisers and methods
constructor(rootDir: String, verifyingKeyHex: String): Open a manager rooted atroot_dir, trusting packages signed by the ed25519 public key given as 64 hex characters (the factory signing key's public half, [sn_package::VerifyingKey::to_hex]).override fun destroy()override fun close()@Throws(NavCoreException::class) override fun active(): String?: The active territory id, if one is set and still installed.@Throws(NavCoreException::class) override fun applyUpdate(territoryId: String, newManifestJson: String, newManifestSigBase64: String, fetcher: LayerFetcher): UpdateResult: Apply a differential update: stage, fetch only the changed layers throughfetcher, verify everything and swap atomically. Any failure leaves the installed territory untouched; the active flag is preserved. Blocks until done and cannot be interrupted; see [Self::apply_update_cancellable].@Throws(NavCoreException::class) override fun applyUpdateCancellable(territoryId: String, newManifestJson: String, newManifestSigBase64: String, fetcher: LayerFetcher, cancel: CancelToken): UpdateOutcome: [Self::apply_update] with aCancelToken. Polled before every layer download, between archive entries while unpacking, before each hash pass and before promotion. A tripped token yields [UpdateOutcome::Cancelled]: the installed version is untouched, staging is removed, and layers that had already been fetched and verified stay in the resumable cache, so calling again with the same manifest re-fetches only what is missing. Givefetcherthe same token so it can stop an in-flight transfer (the token cannot interrupt foreign code on its own); whatever the fetcher then returns, a tripped token reportsCancelledrather than a transport error.@Throws(NavCoreException::class) override fun cachedLayerBytes(): ULong: Bytes parked in the resumable layer cache: downloads a failed install already paid for, which a retry will not pay for again. Surface this next to a "resume" affordance and in storage settings.@Throws(NavCoreException::class) override fun checkForUpdate(territoryId: String, indexJson: String, indexSigBase64: String, fetcher: LayerFetcher): AvailableUpdate?: Check the signed channel index for an update to an installed territory.index_jsonmust be the exact bytes served asindex.jsonandindex_sig_base64the content ofindex.json.sig; the remote manifest is fetched and verified throughfetcher. ReturnsNonewhen the device is already on the channel's latest version (or the channel does not list the territory).@Throws(NavCoreException::class) override fun clearLayerCache(): Discard every parked layer. The bytes are lost and a later install re-downloads (and on a metered channel re-pays for) them, so offer this only as a deliberate "free up space" action.@Throws(NavCoreException::class) override fun installDir(packageDir: String): TerritoryInfo: Install an unpacked package directory. Blocks until done and cannot be interrupted; see [Self::install_dir_cancellable].@Throws(NavCoreException::class) override fun installDirCancellable(packageDir: String, cancel: CancelToken): InstallOutcome: [Self::install_dir] with aCancelToken. Polled between copied files, before verification and before promotion.@Throws(NavCoreException::class) override fun installDirPartial(packageDir: String, omit: List<MapLayerKind>, cancel: CancelToken): InstallOutcome: Install an unpacked package directory, holding only the layers this app can use:omitnames the kinds to leave out (e.g.PmtilesandExtra("style")for an app with no map view). The install records what it left out, and every later verification requires those layers to be absent rather than exempting them from hashing, so the record cannot be forged into admitting tampered bytes. Asking for an omitted layer answers [NavCoreError::LayerNotInstalled], which is not an error state: it is "you chose not to download this". The selection is sticky: updates carry it forward, so an app that skipped the render layers never downloads them on an update either.@Throws(NavCoreException::class) override fun installFromChannel(territoryId: String, indexJson: String, indexSigBase64: String, omit: List<MapLayerKind>, fetcher: LayerFetcher, cancel: CancelToken): ChannelInstallOutcome: Install a territory from the channel, downloading only the layers this app can use. The first-install counterpart of [Self::apply_update], and the only path on which omitting layers saves bandwidth: a layer inomitis never requested, so it is never metered and never stored.index_json/index_sig_base64are the exact served bytes ofindex.jsonandindex.json.sig; the channel's latest version of the territory is installed. Nothing is trusted but the pinned key: the index signature, the manifest signature and every blob's BLAKE3 are checked, and the assembled directory goes through the same full verification pass as any other install before it is promoted. Interrupted installs resume: verified layers stay parked in the layer cache. Calling it again for a territory that is already installed is how a selection is widened later. Layers already on the device at the same content hash are linked, not re-downloaded, so adding the map to a router-only install costs the map alone.@Throws(NavCoreException::class) override fun installSnpkg(archivePath: String): TerritoryInfo: Install a packed.snpkgarchive (verify-then-promote; rejected packages leave no trace). Blocks until done and cannot be interrupted; see [Self::install_snpkg_cancellable].@Throws(NavCoreException::class) override fun installSnpkgCancellable(archivePath: String, cancel: CancelToken): InstallOutcome: [Self::install_snpkg] with aCancelToken. Polled between archive entries, before verification and before promotion; a tripped token yields [InstallOutcome::Cancelled] with staging removed and nothing installed.@Throws(NavCoreException::class) override fun installSnpkgPartial(archivePath: String, omit: List<MapLayerKind>, cancel: CancelToken): InstallOutcome: [Self::install_dir_partial] from a packed.snpkgarchive. The archive carries every layer, so this saves storage, not bandwidth: the omitted layers are unpacked and then dropped before verification. For the bandwidth saving use [Self::install_from_channel], which never fetches a blob it does not want.@Throws(NavCoreException::class) override fun layerPath(territoryId: String, kind: MapLayerKind): String: Absolute path of a layer inside an installed territory (e.g. the Valhalla tile tree for valhalla-mobile, the PMTiles file for MapLibre).@Throws(NavCoreException::class) override fun list(): List<TerritoryInfo>: List installed territories in territory-id order.@Throws(NavCoreException::class) override fun openSearch(territoryId: String): TerritorySearch: Open the installed territory's bundled geocode index for on-device search. The returnedTerritorySearchholds the index open (mmap-backed), create it once per territory and reuse it across queries.@Throws(NavCoreException::class) override fun planUpdate(newManifestJson: String): UpdatePlan: Plan a differential update from the installed manifest tonew_manifest_json(a signed manifest's JSON body, as served by the update channel).@Throws(NavCoreException::class) override fun remove(territoryId: String): Remove an installed territory (clears the active marker if needed).@Throws(NavCoreException::class) override fun setActive(territoryId: String): Mark a territory as active (persisted atomically).@Throws(NavCoreException::class) override fun territoryStyle(territoryId: String, theme: StyleTheme): String: A complete MapLibre style JSON for an installed territory with local (offline) references, mirroring the web SDK'sbuildStyle(). Load it straight into MapLibre, the territory tile source points at the installed PMTiles layer via apmtiles://<absolute path>URL, so the map renders with radios off. Packages without a baked style layer get the default MapMap theme compiled on the fly over the package's PMTiles layer. Theglyphsendpoint stays hosted (MapLibre caches fetched glyph ranges; no offline glyph bundle ships in packages today).@Throws(NavCoreException::class) override fun verifyTerritory(territoryId: String): TerritoryInfo: Re-verify an installed territory from disk: the manifest signature, the BLAKE3 of every layer this install holds, and the absence of every layer it recorded as omitted. The ordinary calls do not re-hash gigabytes; this is the on-demand integrity check for after a restore or a crash. A failure arrives as [NavCoreError::Verification] and means the install must be repaired or reinstalled, not retried.
Nested: TerritoryManager.Companion.
TerritorySearch
Class · uniffi/mapmap/mapmap.kt
open class TerritorySearch: Disposable, AutoCloseable, TerritorySearchInterface
On-device search over an installed territory's bundled geocode index
(see [TerritoryManager::open_search]). Fully offline; queries are
synchronous and mmap-backed, call from a background thread/dispatcher
like any other disk-bound SDK call.
Initialisers and methods
override fun destroy()override fun close()@Throws(NavCoreException::class) override fun reverse(lat: Double, lon: Double, limit: UInt): List<Place>: Reverse geocode: the nearest indexed places to a coordinate, nearest first.@Throws(NavCoreException::class) override fun search(query: String, near: RoutePoint?, limit: UInt): List<Place>: Free-text search (addresses, streets, places, POIs, UK postcodes; prefix-tokenised, so it works for search-as-you-type).nearbiases ranking towards the given point and fills each result'sdistance_m;limitcaps the number of hits.
UpdateOutcome
Class · uniffi/mapmap/mapmap.kt
sealed class UpdateOutcome
How a cancellable update ended.
Nested: UpdateOutcome.Applied, UpdateOutcome.Cancelled.
UpdateOutcome.Applied
Class · uniffi/mapmap/mapmap.kt
data class Applied(val result: uniffi.mapmap.UpdateResult) : UpdateOutcome()
The update verified and was swapped in.
| Property | Type | Default | Description |
|---|---|---|---|
val result | uniffi.mapmap.UpdateResult |
UpdatePlan
Class · uniffi/mapmap/mapmap.kt
data class UpdatePlan (var changed: List<ChangedLayer>, var installedBytes: ULong)
A differential update plan.
| Property | Type | Default | Description |
|---|---|---|---|
var changed | List<ChangedLayer> | ||
var installedBytes | ULong |
UpdateResult
Class · uniffi/mapmap/mapmap.kt
data class UpdateResult (var territory: TerritoryInfo, var previousVersion: String, var layersFetched: UInt, var layersReused: UInt, var bytesDownloaded: ULong)
What [TerritoryManager::apply_update] did.
| Property | Type | Default | Description |
|---|---|---|---|
var territory | TerritoryInfo | ||
var previousVersion | String | ||
var layersFetched | UInt | ||
var layersReused | UInt | ||
var bytesDownloaded | ULong |
VisualBanner
Class · uniffi/mapmap/mapmap.kt
data class VisualBanner (var primary: BannerLine, var secondary: BannerLine?, var sub: BannerLine?, var triggerDistanceM: Double, var drivingSide: String? = null, var roadRef: String? = null, var country: String? = null, var subdivision: String? = null, var roadClass: String? = null)
The visual banner to display for the upcoming maneuver.
| Property | Type | Default | Description |
|---|---|---|---|
var primary | BannerLine | ||
var secondary | BannerLine? | ||
var sub | BannerLine? | ||
var triggerDistanceM | Double | ||
var drivingSide | String? | null | |
var roadRef | String? | null | |
var country | String? | null | |
var subdivision | String? | null | |
var roadClass | String? | null |
Enums (uniffi.mapmap)
AdrTunnelCategory, AdrTunnelCode, CostingModel, InstructionSeverity, PlaceKind, StyleTheme
AdrTunnelCategory
Enum · uniffi/mapmap/mapmap.kt
enum class AdrTunnelCategory
ADR tunnel category A–E (ascending restrictiveness), mirroring
[sn_adr::TunnelCategory].
| Case | Description |
|---|---|
A | No dangerous-goods restriction. |
B | Restriction for goods which may lead to a very large explosion. |
C | … or a large explosion or large toxic release. |
D | … or a large fire. |
E | Restriction for nearly all dangerous goods. |
AdrTunnelCode
Enum · uniffi/mapmap/mapmap.kt
enum class AdrTunnelCode
ADR 8.6.4 tunnel restriction code of a load, mirroring
[sn_adr::TunnelRestrictionCode]. NoCode is ADR's (, ): explicitly
unrestricted.
| Case | Description |
|---|---|
NO_CODE | ADR (, ), passage permitted through all tunnels. |
B | Code B. |
B1000C | Code B1000C. |
BD | Code B/D. |
BE | Code B/E. |
C | Code C. |
C5000D | Code C5000D. |
CD | Code C/D. |
CE | Code C/E. |
D | Code D. |
DE | Code D/E. |
E | Code E. |
CostingModel
Enum · uniffi/mapmap/mapmap.kt
enum class CostingModel
Valhalla costing model, mirroring [sn_valhalla::valhalla::Costing].
| Case | Description |
|---|---|
AUTO | Standard car costing. |
TRUCK | Truck costing (required when an ADR profile is supplied). |
BUS | Bus costing. |
MOTOR_SCOOTER | Motor scooter costing. |
MOTORCYCLE | Motorcycle costing. |
BICYCLE | Bicycle costing. |
PEDESTRIAN | Pedestrian costing. |
InstructionSeverity
Enum · uniffi/mapmap/mapmap.kt
enum class InstructionSeverity
How urgently a guidance update should be surfaced to the driver.
Voice layers map this to prosody (pitch/rate) and earcons; visual
layers to banner styling. Ordered: Info < Warning < Critical.
Derivation (single source of truth for every SDK):
- Critical, restriction prohibitions: an ADR tunnel prohibition
([
InstructionSeverity::for_adr_decision] on aBlockeddecision, the hook platform layers use whencheck_tunnelfires off-route) and manoeuvres crossing a gate (a physical barrier the vehicle must not run). - Warning, approaching a restriction or interruption of the drive: toll booths and ferry boardings/landings.
- Info, every normal manoeuvre.
Off-route updates carry no instruction; platform voice layers treat
[GuidanceUpdate::OffRoute] itself as Warning.
| Case | Description |
|---|---|
INFO | A normal manoeuvre announcement. |
WARNING | Approaching a restriction (toll booth, ferry boarding/landing). |
CRITICAL | A prohibition: ADR tunnel block or a gate across the carriageway. |
PlaceKind
Enum · uniffi/mapmap/mapmap.kt
enum class PlaceKind
The kind of entity a Place describes, mirroring
[sn_geocode::DocKind].
| Case | Description |
|---|---|
ADDRESS | A single addressable building or unit (housenumber + street). |
STREET | A named street or road. |
LOCALITY | A town, city, village or suburb. |
POI | A point of interest (fuel station, truck stop, museum, …). |
POSTCODE | A postcode centroid (full or outward code). |
StyleTheme
Enum · uniffi/mapmap/mapmap.kt
enum class StyleTheme
Which packaged style variant [TerritoryManager::territory_style]
returns, mirroring [crate::territory::StyleTheme] (and the web SDK's
buildStyle({ theme }) names).
| Case | Description |
|---|---|
LIGHT | The light (day) style, also the package default. |
DARK | The dark (night) style. |
Interfaces (uniffi.mapmap)
CancelTokenInterface, GuidanceSessionInterface, LayerFetcher, LocalRouter, ProbeCollectorInterface, TerritoryManagerInterface, TerritorySearchInterface
CancelTokenInterface
Interface · uniffi/mapmap/mapmap.kt
public interface CancelTokenInterface
A cancellation handle for an in-flight territory install or update.
The install calls on TerritoryManager block the calling thread for
as long as a multi-gigabyte package takes to download, unpack and
verify. Create a token, pass it to one of the _cancellable variants
running on a background thread, and call [CancelToken::cancel] from
the UI thread when the user taps Cancel. The install polls it at safe
points and returns [InstallOutcome::Cancelled] /
[UpdateOutcome::Cancelled] with its staging directory removed: no
partial package is left on disk, the previously installed version is
untouched, and layers that had already been verified stay in the
resumable cache for the next attempt. Cancelling after the call has
returned changes nothing.
The token cannot interrupt a LayerFetcher blocked in a transfer:
give the fetcher the same token and have it poll
[CancelToken::is_cancelled] between chunks (or abort its request when
the app cancels). Whatever the fetcher then returns, the install
reports Cancelled, not a transport error.
Initialisers and methods
fun cancel(): Request cancellation. Idempotent and safe from any thread.fun isCancelled(): Boolean: Whether [Self::cancel] has been called.
GuidanceSessionInterface
Interface · uniffi/mapmap/mapmap.kt
public interface GuidanceSessionInterface
A turn-by-turn guidance session (see [crate::guidance]).
Thread-safe: the mutable Ferrostar navigation state is guarded by a mutex, matching UniFFI's shared-object concurrency model.
Initialisers and methods
fun advanceToNextStep(): GuidanceUpdate: Manually advance to the next step (e.g. in a tunnel with no GNSS).fun totalSteps(): UInt: Number of steps in the route, including the arrival step.fun updateLocation(lat: Double, lon: Double, timestampMs: Long, speedMps: Double?, courseDeg: Double?, horizontalAccuracyM: Double?): GuidanceUpdate: Feed a location fix; returns the updated guidance state.horizontal_accuracy_mdefaults to0.0(trusted exactly) when absent; pass the platform's reported accuracy when available so step advance and deviation gating behave correctly.
LayerFetcher
Interface · uniffi/mapmap/mapmap.kt
public interface LayerFetcher
The platform's download transport for over-the-air territory updates,
exported as a UniFFI callback interface like
[crate::routing::LocalRouter]: the core decides what to fetch and
cryptographically verifies everything; Kotlin/Swift decide how bytes
move (OkHttp, URLSession, an air-gapped mirror, …).
Initialisers and methods
fun fetch(relPath: String, expectedBlake3: String, destPath: String): Download the channel-relativerel_path(e.g.territories/uk/2.0.0/layers/<addr>/valhalla.tar.zst) to the local filedest_path.expected_blake3is advisory (empty for signed metadata files); the core re-verifies all content itself.
LocalRouter
Interface · uniffi/mapmap/mapmap.kt
public interface LocalRouter
The injection point for the platform's on-device Valhalla binding.
valhalla-mobile (https://github.com/Rallista/valhalla-mobile) exposes
a route(request_json) -> response_json actor on both Android and iOS;
Kotlin/Swift implement this interface with that actor and pass it to
[crate::ffi::route_offline]. Exported as a UniFFI callback interface
(with_foreign) so the implementation lives in foreign code.
Initialisers and methods
fun route(requestJson: String): String: Execute a Valhalla turn-by-turn request and return the raw response JSON (either a route response or a Valhalla error body).
ProbeCollectorInterface
Interface · uniffi/mapmap/mapmap.kt
public interface ProbeCollectorInterface
On-device probe collector. Feed it every guidance update with the fix's
position, speed and timestamp; call finish at
arrival or trip abandonment to get the ProbeBatch to upload.
Interior mutability (a Mutex) lets the FFI methods take &self, matching
the [crate::guidance::GuidanceSession] object shape.
Initialisers and methods
fun finish(arrived: Boolean, timestampMs: Long): ProbeBatch: Close the trip and return the batch to upload.arriveddistinguishes a completed trip from an abandoned one (both apply end suppression).fun finishJson(arrived: Boolean, timestampMs: Long): String?: Close the trip and return the exact JSON body toPOST /v1/probe, orNonewhen the batch carries nothing worth uploading. This is the single canonical serialiser for the probe wire format, platform code should upload this verbatim rather than re-encoding the record, so the wire form can never drift from what the gateway ingests.fun observe(update: GuidanceUpdate, fixLat: Double, fixLon: Double, speedMps: Double?, timestampMs: Long): Feed one guidance update and its fix.speed_mpsis the device's reported ground speed when available (preferred); passNoneto let the collector estimate it from successive positions.fun setRouteRef(routeRef: String): Set the opaque served-route token so the server can resolve segments.fun setTerritory(territory: String): Set the territory id stamped into the batch.fun setVehicleClass(vehicleClass: String): Set the vehicle costing class stamped into the batch (a class only, never a vehicle or driver identifier).
TerritoryManagerInterface
Interface · uniffi/mapmap/mapmap.kt
public interface TerritoryManagerInterface
Manages signed offline territory packages (see [crate::territory]).
Initialisers and methods
fun active(): String?: The active territory id, if one is set and still installed.fun applyUpdate(territoryId: String, newManifestJson: String, newManifestSigBase64: String, fetcher: LayerFetcher): UpdateResult: Apply a differential update: stage, fetch only the changed layers throughfetcher, verify everything and swap atomically. Any failure leaves the installed territory untouched; the active flag is preserved. Blocks until done and cannot be interrupted; see [Self::apply_update_cancellable].fun applyUpdateCancellable(territoryId: String, newManifestJson: String, newManifestSigBase64: String, fetcher: LayerFetcher, cancel: CancelToken): UpdateOutcome: [Self::apply_update] with aCancelToken. Polled before every layer download, between archive entries while unpacking, before each hash pass and before promotion. A tripped token yields [UpdateOutcome::Cancelled]: the installed version is untouched, staging is removed, and layers that had already been fetched and verified stay in the resumable cache, so calling again with the same manifest re-fetches only what is missing. Givefetcherthe same token so it can stop an in-flight transfer (the token cannot interrupt foreign code on its own); whatever the fetcher then returns, a tripped token reportsCancelledrather than a transport error.fun cachedLayerBytes(): ULong: Bytes parked in the resumable layer cache: downloads a failed install already paid for, which a retry will not pay for again. Surface this next to a "resume" affordance and in storage settings.fun checkForUpdate(territoryId: String, indexJson: String, indexSigBase64: String, fetcher: LayerFetcher): AvailableUpdate?: Check the signed channel index for an update to an installed territory.index_jsonmust be the exact bytes served asindex.jsonandindex_sig_base64the content ofindex.json.sig; the remote manifest is fetched and verified throughfetcher. ReturnsNonewhen the device is already on the channel's latest version (or the channel does not list the territory).fun clearLayerCache(): Discard every parked layer. The bytes are lost and a later install re-downloads (and on a metered channel re-pays for) them, so offer this only as a deliberate "free up space" action.fun installDir(packageDir: String): TerritoryInfo: Install an unpacked package directory. Blocks until done and cannot be interrupted; see [Self::install_dir_cancellable].fun installDirCancellable(packageDir: String, cancel: CancelToken): InstallOutcome: [Self::install_dir] with aCancelToken. Polled between copied files, before verification and before promotion.fun installDirPartial(packageDir: String, omit: List<MapLayerKind>, cancel: CancelToken): InstallOutcome: Install an unpacked package directory, holding only the layers this app can use:omitnames the kinds to leave out (e.g.PmtilesandExtra("style")for an app with no map view). The install records what it left out, and every later verification requires those layers to be absent rather than exempting them from hashing, so the record cannot be forged into admitting tampered bytes. Asking for an omitted layer answers [NavCoreError::LayerNotInstalled], which is not an error state: it is "you chose not to download this". The selection is sticky: updates carry it forward, so an app that skipped the render layers never downloads them on an update either.fun installFromChannel(territoryId: String, indexJson: String, indexSigBase64: String, omit: List<MapLayerKind>, fetcher: LayerFetcher, cancel: CancelToken): ChannelInstallOutcome: Install a territory from the channel, downloading only the layers this app can use. The first-install counterpart of [Self::apply_update], and the only path on which omitting layers saves bandwidth: a layer inomitis never requested, so it is never metered and never stored.index_json/index_sig_base64are the exact served bytes ofindex.jsonandindex.json.sig; the channel's latest version of the territory is installed. Nothing is trusted but the pinned key: the index signature, the manifest signature and every blob's BLAKE3 are checked, and the assembled directory goes through the same full verification pass as any other install before it is promoted. Interrupted installs resume: verified layers stay parked in the layer cache. Calling it again for a territory that is already installed is how a selection is widened later. Layers already on the device at the same content hash are linked, not re-downloaded, so adding the map to a router-only install costs the map alone.fun installSnpkg(archivePath: String): TerritoryInfo: Install a packed.snpkgarchive (verify-then-promote; rejected packages leave no trace). Blocks until done and cannot be interrupted; see [Self::install_snpkg_cancellable].fun installSnpkgCancellable(archivePath: String, cancel: CancelToken): InstallOutcome: [Self::install_snpkg] with aCancelToken. Polled between archive entries, before verification and before promotion; a tripped token yields [InstallOutcome::Cancelled] with staging removed and nothing installed.fun installSnpkgPartial(archivePath: String, omit: List<MapLayerKind>, cancel: CancelToken): InstallOutcome: [Self::install_dir_partial] from a packed.snpkgarchive. The archive carries every layer, so this saves storage, not bandwidth: the omitted layers are unpacked and then dropped before verification. For the bandwidth saving use [Self::install_from_channel], which never fetches a blob it does not want.fun layerPath(territoryId: String, kind: MapLayerKind): String: Absolute path of a layer inside an installed territory (e.g. the Valhalla tile tree for valhalla-mobile, the PMTiles file for MapLibre).fun list(): List<TerritoryInfo>: List installed territories in territory-id order.fun openSearch(territoryId: String): TerritorySearch: Open the installed territory's bundled geocode index for on-device search. The returnedTerritorySearchholds the index open (mmap-backed), create it once per territory and reuse it across queries.fun planUpdate(newManifestJson: String): UpdatePlan: Plan a differential update from the installed manifest tonew_manifest_json(a signed manifest's JSON body, as served by the update channel).fun remove(territoryId: String): Remove an installed territory (clears the active marker if needed).fun setActive(territoryId: String): Mark a territory as active (persisted atomically).fun territoryStyle(territoryId: String, theme: StyleTheme): String: A complete MapLibre style JSON for an installed territory with local (offline) references, mirroring the web SDK'sbuildStyle(). Load it straight into MapLibre, the territory tile source points at the installed PMTiles layer via apmtiles://<absolute path>URL, so the map renders with radios off. Packages without a baked style layer get the default MapMap theme compiled on the fly over the package's PMTiles layer. Theglyphsendpoint stays hosted (MapLibre caches fetched glyph ranges; no offline glyph bundle ships in packages today).fun verifyTerritory(territoryId: String): TerritoryInfo: Re-verify an installed territory from disk: the manifest signature, the BLAKE3 of every layer this install holds, and the absence of every layer it recorded as omitted. The ordinary calls do not re-hash gigabytes; this is the on-demand integrity check for after a restore or a crash. A failure arrives as [NavCoreError::Verification] and means the install must be repaired or reinstalled, not retried.
TerritorySearchInterface
Interface · uniffi/mapmap/mapmap.kt
public interface TerritorySearchInterface
On-device search over an installed territory's bundled geocode index
(see [TerritoryManager::open_search]). Fully offline; queries are
synchronous and mmap-backed, call from a background thread/dispatcher
like any other disk-bound SDK call.
Initialisers and methods
fun reverse(lat: Double, lon: Double, limit: UInt): List<Place>: Reverse geocode: the nearest indexed places to a coordinate, nearest first.fun search(query: String, near: RoutePoint?, limit: UInt): List<Place>: Free-text search (addresses, streets, places, POIs, UK postcodes; prefix-tokenised, so it works for search-as-you-type).nearbiases ranking towards the given point and fills each result'sdistance_m;limitcaps the number of hits.
Objects (uniffi.mapmap)
AdrDecision.Allowed, ChannelInstallOutcome.Cancelled, FetchException.ErrorHandler, GuidanceUpdate.Arrived, InstallOutcome.Cancelled, MapLayerKind.GeocodeIndex, MapLayerKind.Pmtiles, MapLayerKind.PoiSidecar, MapLayerKind.ValhallaTiles, NavCoreException.ErrorHandler, RerouteState.CoolingDown, RerouteState.Monitoring, RerouteState.RerouteNeeded, SpeedLimit.Unknown, SpeedLimit.Unlimited, TerritoryManager.Companion, UpdateOutcome.Cancelled
AdrDecision.Allowed
Object · uniffi/mapmap/mapmap.kt
object Allowed : AdrDecision()
Passage is permitted.
ChannelInstallOutcome.Cancelled
Object · uniffi/mapmap/mapmap.kt
object Cancelled : ChannelInstallOutcome()
The CancelToken was tripped before promotion. Nothing was
installed; verified layers stay parked for the next attempt.
FetchException.ErrorHandler
Object · uniffi/mapmap/mapmap.kt
companion object ErrorHandler : UniffiRustCallStatusErrorHandler<FetchException>
Human-readable description of the failure.
GuidanceUpdate.Arrived
Object · uniffi/mapmap/mapmap.kt
object Arrived : GuidanceUpdate()
The user has arrived at the destination.
InstallOutcome.Cancelled
Object · uniffi/mapmap/mapmap.kt
object Cancelled : InstallOutcome()
The CancelToken was tripped before promotion. Nothing was
installed; staging was removed.
MapLayerKind.GeocodeIndex
Object · uniffi/mapmap/mapmap.kt
object GeocodeIndex : MapLayerKind()
Tantivy geocoding index.
MapLayerKind.Pmtiles
Object · uniffi/mapmap/mapmap.kt
object Pmtiles : MapLayerKind()
PMTiles render layer.
MapLayerKind.PoiSidecar
Object · uniffi/mapmap/mapmap.kt
object PoiSidecar : MapLayerKind()
Proprietary POI sidecar database.
MapLayerKind.ValhallaTiles
Object · uniffi/mapmap/mapmap.kt
object ValhallaTiles : MapLayerKind()
Valhalla routing tile tree.
NavCoreException.ErrorHandler
Object · uniffi/mapmap/mapmap.kt
companion object ErrorHandler : UniffiRustCallStatusErrorHandler<NavCoreException>
RerouteState.CoolingDown
Object · uniffi/mapmap/mapmap.kt
object CoolingDown : RerouteState()
Off route and confirmed again, but suppressed because a reroute fired
within [RerouteConfig::min_interval_between_reroutes_s].
RerouteState.Monitoring
Object · uniffi/mapmap/mapmap.kt
object Monitoring : RerouteState()
On route (or recovered): nothing to do.
RerouteState.RerouteNeeded
Object · uniffi/mapmap/mapmap.kt
object RerouteNeeded : RerouteState()
A reroute is confirmed for this update; the accompanying
RerouteDecision should be routed. Reported exactly once per
confirmed departure.
SpeedLimit.Unknown
Object · uniffi/mapmap/mapmap.kt
object Unknown : SpeedLimit()
A limit applies but is unknown for the current segment (Mapbox
maxspeed unknown), the data source annotates this position but has
no value for it. Distinct from the field being absent entirely.
SpeedLimit.Unlimited
Object · uniffi/mapmap/mapmap.kt
object Unlimited : SpeedLimit()
The road is de-restricted (Mapbox maxspeed none; OSM
maxspeed=none, e.g. a German autobahn), show a "no limit" badge, do
not warn.
TerritoryManager.Companion
Object · uniffi/mapmap/mapmap.kt
companion object
Initialisers and methods
@Throws(NavCoreException::class) fun withRegionKey(rootDir: String, verifyingKeyHex: String, regionKeyHex: String): TerritoryManager: [Self::new], also trusting custom regions (region-…ids, cut byPOST /v1/jobs/territory) signed byregion_key_hex, the public half of the gateway's region signing key. The keys are partitioned by id: the region key verifiesregion-ids only and the factory key everything else. Pin both in the app; never read either from the network.
UpdateOutcome.Cancelled
Object · uniffi/mapmap/mapmap.kt
object Cancelled : UpdateOutcome()
The CancelToken was tripped before promotion. The installed
version is untouched; verified layers stay parked for a retry.
Functions (uniffi.mapmap)
buildOfflineRouteRequest, checkTunnel, forbiddenCategories, parseRouteResult, routeOffline, styleForNavigation, styleWithBuildings3d
buildOfflineRouteRequest
Function · uniffi/mapmap/mapmap.kt
@Throws(NavCoreException::class) fun buildOfflineRouteRequest(locations: List<RoutePoint>, costing: CostingModel, adr: AdrProfile?): String
Build the Valhalla request JSON an on-device engine accepts, with ADR costing options merged (conflicts rejected). Useful when foreign code wants to drive the engine itself.
checkTunnel
Function · uniffi/mapmap/mapmap.kt
fun checkTunnel(profile: AdrProfile, category: AdrTunnelCategory): AdrDecision
Decide whether the vehicle may pass through a tunnel of category
(conservative ADR 8.6.4 reading; see [crate::adr::check_tunnel]).
forbiddenCategories
Function · uniffi/mapmap/mapmap.kt
fun forbiddenCategories(profile: AdrProfile): List<AdrTunnelCategory>
All tunnel categories the vehicle is forbidden from (ascending). Empty when unrestricted.
parseRouteResult
Function · uniffi/mapmap/mapmap.kt
@Throws(NavCoreException::class) fun parseRouteResult(responseJson: String): RouteResult
Parse a raw on-device route response into a RouteResult, including
the typed [RouteResult::geometry] and [RouteResult::maneuvers].
routeOffline
Function · uniffi/mapmap/mapmap.kt
@Throws(NavCoreException::class) fun routeOffline(router: LocalRouter, locations: List<RoutePoint>, costing: CostingModel, adr: AdrProfile?): RouteResult
Full offline routing orchestration: build the request, run it through
the injected LocalRouter (the platform's valhalla-mobile binding)
and parse the response.
styleForNavigation
Function · uniffi/mapmap/mapmap.kt
@Throws(NavCoreException::class) fun styleForNavigation(styleJson: String, keepBuildings3d: Boolean = true): String
Prepares a style for a turn-by-turn navigation view. Call it on whatever style the app otherwise uses, right before loading the navigation map; it is where nav-view safeguards live.
By default (keep_buildings_3d = true) the style's 3D building state
is left exactly as the app configured it: MapLibre Native's historical
fill-extrusion memory blow-up (maplibre-native#4107) is fixed by the
instancing rework (#4256; Android >= 13.2.0, iOS >= 6.26.1), and a
navigation-loop soak (qa/expo-3d-soak, 17 Jul 2026) measured a
bounded ~170 MB for city-wide 3D at nav zoom, flat, no growth.
Pass keep_buildings_3d = false to strip the building-3d layer, the pre-fix behaviour, when targeting MapLibre pins older than the
fix or low-memory devices you have not measured.
styleWithBuildings3d
Function · uniffi/mapmap/mapmap.kt
@Throws(NavCoreException::class) fun styleWithBuildings3d(styleJson: String, enabled: Boolean): String
Toggle 3D building extrusions on a MapMap style.json document (a
territory package's baked style or a hosted style body), returning the
adjusted document to load into MapLibre. Idempotent; errors with
[NavCoreError::InvalidArgument] on non-style input.
Safe on MapLibre Native releases carrying the fill-extrusion instancing fix (maplibre-native#4256, merged 2026-05-05: Android
= 13.2.0, iOS >= 6.26.1), the historical street-zoom memory blow-up (#4107, 900 MB+ at zoom 17) is fixed there. Measured 17 Jul 2026 on a Pixel-class device (
qa/expo-3d-soak): city-wide extrusions at zoom 16.5/pitch 60 cost a bounded ~170 MB over an identical no-3D control, flat over the soak. On pins older than the fix, keep this off outside measured map-browsing views.
uniffi.ferrostar
Classes (uniffi.ferrostar)
AndAdvanceConditions, BoundingBox, Congestion, CourseOverGround, DeviationKind, DeviationKind.CompletelyOffRoute, DeviationKind.OffStepOnRoute, DistanceEntryAndExitCondition, DistanceEntryAndSnappedExitCondition, DistanceFromStepCondition, DistanceToEndOfStepCondition, GeographicCoordinate, Heading, Incident, InstantiationException, InstantiationException.OptionsJsonParseException, LaneInfo, LocationBias, LocationBias.Left, LocationBias.Random, LocationBias.Right, LocationSimulationState, ManualStepCondition, ModelException, ModelException.PolylineGenerationException, NavigationCacheImpl, NavigationCachingConfig, NavigationController, NavigationControllerConfig, NavigationObserverImpl, NavigationRecorder, NavigationRecordingEvent, NavigationRecordingEventData, NavigationRecordingEventData.RouteUpdate, NavigationRecordingEventData.StateUpdate, NavigationReplay, NavigationSession, NavigationSessionCache, NavigationSessionSnapshot, Navigator, NavState, OrAdvanceConditions, OsrmWaypointProperties, ParsingException, ParsingException.InvalidGeometry, ParsingException.InvalidRouteObject, ParsingException.InvalidStatusCode, ParsingException.MalformedAnnotations, ParsingException.UnknownParsingException, RecordingException, RecordingException.DeserializationException, RecordingException.RecordingNotEnabled, RecordingException.SerializationException, Route, RouteAdapter, RouteDeviation, RouteDeviation.Deviation, RouteDeviationDetectorImpl, RouteDeviationTracking, RouteDeviationTracking.Custom, RouteDeviationTracking.StaticThreshold, RouteRequest, RouteRequest.HttpGet, RouteRequest.HttpPost, RouteRequestGeneratorImpl, RouteResponseParserImpl, RouteStep, RoutingRequestGenerationException, RoutingRequestGenerationException.JsonException, RoutingRequestGenerationException.NotEnoughWaypoints, RoutingRequestGenerationException.UnknownRequestGenerationException, SerializableNavState, SerializableStepAdvanceCondition, SerializableStepAdvanceCondition.AndAdvanceConditions, SerializableStepAdvanceCondition.DistanceEntryAndSnappedExit, SerializableStepAdvanceCondition.DistanceEntryExit, SerializableStepAdvanceCondition.DistanceFromStep, SerializableStepAdvanceCondition.DistanceToEndOfStep, SerializableStepAdvanceCondition.OrAdvanceConditions, SimulationException, SimulationException.NotEnoughPoints, SimulationException.PolylineException, Speed, SpokenInstruction, StepAdvanceCondition, StepAdvanceResult, TripProgress, TripState, TripState.Complete, TripState.Idle, TripState.Navigating, TripSummary, UserLocation, ValhallaLocationSearchFilter, ValhallaWaypointProperties, VisualInstruction, VisualInstructionContent, Waypoint, WaypointAdvanceMode, WaypointAdvanceMode.WaypointAlongAdvancingStep, WaypointAdvanceMode.WaypointWithinRange, WellKnownRouteProvider, WellKnownRouteProvider.GraphHopper, WellKnownRouteProvider.Valhalla
AndAdvanceConditions
Class · uniffi/ferrostar/ferrostar.kt
open class AndAdvanceConditions: Disposable, AutoCloseable, AndAdvanceConditionsInterface
Advance if all of the conditions are met (AND).
Initialisers and methods
override fun destroy()override fun close()
BoundingBox
Class · uniffi/ferrostar/ferrostar.kt
data class BoundingBox (var sw: GeographicCoordinate, var ne: GeographicCoordinate)
A geographic bounding box defined by its corners.
| Property | Type | Default | Description |
|---|---|---|---|
var sw | GeographicCoordinate | ||
var ne | GeographicCoordinate |
Congestion
Class · uniffi/ferrostar/ferrostar.kt
data class Congestion (var value: UByte)
Details about congestion for an incident.
| Property | Type | Default | Description |
|---|---|---|---|
var value | UByte |
CourseOverGround
Class · uniffi/ferrostar/ferrostar.kt
data class CourseOverGround (var degrees: UShort, var accuracy: UShort?)
The direction in which the user/device is observed to be traveling.
| Property | Type | Default | Description |
|---|---|---|---|
var degrees | UShort | ||
var accuracy | UShort? |
DeviationKind
Class · uniffi/ferrostar/ferrostar.kt
sealed class DeviationKind
The kind of deviation from the expected route.
Nested: DeviationKind.OffStepOnRoute, DeviationKind.CompletelyOffRoute.
DeviationKind.CompletelyOffRoute
Class · uniffi/ferrostar/ferrostar.kt
data class CompletelyOffRoute(val deviationFromRouteLine: Double) : DeviationKind()
The user is off the expected route entirely (not within threshold of any remaining step, neither the current one nor any future one).
| Property | Type | Default | Description |
|---|---|---|---|
val deviationFromRouteLine | Double |
DeviationKind.OffStepOnRoute
Class · uniffi/ferrostar/ferrostar.kt
data class OffStepOnRoute(val deviationFromStepLine: Double) : DeviationKind()
The user is off the current step, but still on the route polyline (on a future step).
This can happen when the user takes a shortcut, GPS noise places them on a future step, or the route self-intersects. Step advance conditions can use this to limit advancement.
| Property | Type | Default | Description |
|---|---|---|---|
val deviationFromStepLine | Double |
DistanceEntryAndExitCondition
Class · uniffi/ferrostar/ferrostar.kt
open class DistanceEntryAndExitCondition: Disposable, AutoCloseable, DistanceEntryAndExitConditionInterface
A stateful condition that requires the user to reach the end of the step then proceed past it to advance.
Initialisers and methods
override fun destroy()override fun close()
DistanceEntryAndSnappedExitCondition
Class · uniffi/ferrostar/ferrostar.kt
open class DistanceEntryAndSnappedExitCondition: Disposable, AutoCloseable, DistanceEntryAndSnappedExitConditionInterface
A stateful condition that requires the user to reach the end of the step then proceed past it to advance.
This variant uses route snapping (snapping to the combined current+next step geometry) for the exit check, making it more robust for pedestrian/hiking navigation where users may walk on the opposite side of the street or wander around the optimal path. The route-snapped exit check prevents premature advancement while still allowing natural pedestrian movement patterns. The exit distance is measured from the current step to the route-snapped position.
Initialisers and methods
override fun destroy()override fun close()
DistanceFromStepCondition
Class · uniffi/ferrostar/ferrostar.kt
open class DistanceFromStepCondition: Disposable, AutoCloseable, DistanceFromStepConditionInterface
Advances once the user is at least [Self::distance] meters from the current step's polyline.
This results in delayed advance, but is more robust to spurious / unwanted step changes in scenarios including self-intersecting routes (sudden jumps to the next step) and pauses at intersections (advancing too soon before the maneuver is complete).
NOTE! This may be less robust to things like short steps, out-and-backs, and U-turns, where this may eagerly exit a current step before the user has traversed it if the start of the step is within range of the end.
Initialisers and methods
override fun destroy()override fun close()
DistanceToEndOfStepCondition
Class · uniffi/ferrostar/ferrostar.kt
open class DistanceToEndOfStepCondition: Disposable, AutoCloseable, DistanceToEndOfStepConditionInterface
Automatically advances when the user's location is close enough to the end of the step.
This results in an eager advance where the user will jump to the next step when the condition is met.
Initialisers and methods
override fun destroy()override fun close()
GeographicCoordinate
Class · uniffi/ferrostar/ferrostar.kt
data class GeographicCoordinate (var lat: Double, var lng: Double)
A geographic coordinate in WGS84.
| Property | Type | Default | Description |
|---|---|---|---|
var lat | Double | ||
var lng | Double |
Heading
Class · uniffi/ferrostar/ferrostar.kt
data class Heading (var trueHeading: UShort, var accuracy: UShort, var timestamp: java.time.Instant)
The heading of the user/device.
| Property | Type | Default | Description |
|---|---|---|---|
var trueHeading | UShort | ||
var accuracy | UShort | ||
var timestamp | java.time.Instant |
Incident
Class · uniffi/ferrostar/ferrostar.kt
data class Incident (var id: String, var incidentType: IncidentType, var description: String?, var longDescription: String?, var creationTime: UtcDateTime?, var startTime: UtcDateTime?, var endTime: UtcDateTime?, var impact: Impact?, var lanesBlocked: List<BlockedLane>, var congestion: Congestion?, var closed: Boolean?, var geometryIndexStart: ULong, var geometryIndexEnd: ULong?, var subType: String?, var subTypeDescription: String?, var iso31661Alpha2: String?, var iso31661Alpha3: String?, var affectedRoadNames: List<String>, var bbox: BoundingBox?)
An incident affecting the free flow of traffic, such as constructions, accidents, and congestion.
| Property | Type | Default | Description |
|---|---|---|---|
var id | String | ||
var incidentType | IncidentType | ||
var description | String? | ||
var longDescription | String? | ||
var creationTime | UtcDateTime? | ||
var startTime | UtcDateTime? | ||
var endTime | UtcDateTime? | ||
var impact | Impact? | ||
var lanesBlocked | List<BlockedLane> | ||
var congestion | Congestion? | ||
var closed | Boolean? | ||
var geometryIndexStart | ULong | ||
var geometryIndexEnd | ULong? | ||
var subType | String? | ||
var subTypeDescription | String? | ||
var iso31661Alpha2 | String? | ||
var iso31661Alpha3 | String? | ||
var affectedRoadNames | List<String> | ||
var bbox | BoundingBox? |
InstantiationException
Class · uniffi/ferrostar/ferrostar.kt
sealed class InstantiationException: Exception()
Nested: InstantiationException.OptionsJsonParseException, InstantiationException.ErrorHandler.
InstantiationException.OptionsJsonParseException
Class · uniffi/ferrostar/ferrostar.kt
class OptionsJsonParseException() : InstantiationException()
| Property | Type | Default | Description |
|---|---|---|---|
val message |
LaneInfo
Class · uniffi/ferrostar/ferrostar.kt
data class LaneInfo (var active: Boolean, var directions: List<String>, var activeDirection: String?)
The content of a visual instruction.
| Property | Type | Default | Description |
|---|---|---|---|
var active | Boolean | ||
var directions | List<String> | ||
var activeDirection | String? |
LocationBias
Class · uniffi/ferrostar/ferrostar.kt
sealed class LocationBias
Controls how simulated locations deviate from the actual route line. This simulates real-world GPS behavior where readings often have systematic bias.
Nested: LocationBias.Left, LocationBias.Right, LocationBias.Random, LocationBias.None.
LocationBias.Left
Class · uniffi/ferrostar/ferrostar.kt
data class Left(val v1: Double) : LocationBias()
Simulates GPS bias by offsetting locations to the left of the route direction. The f64 parameter specifies the offset distance in meters.
| Property | Type | Default | Description |
|---|---|---|---|
val v1 | Double |
LocationBias.Random
Class · uniffi/ferrostar/ferrostar.kt
data class Random(val v1: Double) : LocationBias()
Simulates GPS bias by randomly choosing left or right offset on initialization and maintaining that bias throughout the route. The f64 parameter specifies the offset distance in meters.
This mimics real-world GPS behavior where bias direction is random but typically remains consistent during a trip.
| Property | Type | Default | Description |
|---|---|---|---|
val v1 | Double |
LocationBias.Right
Class · uniffi/ferrostar/ferrostar.kt
data class Right(val v1: Double) : LocationBias()
Simulates GPS bias by offsetting locations to the right of the route direction. The f64 parameter specifies the offset distance in meters.
| Property | Type | Default | Description |
|---|---|---|---|
val v1 | Double |
LocationSimulationState
Class · uniffi/ferrostar/ferrostar.kt
data class LocationSimulationState (var currentLocation: UserLocation, var remainingLocations: List<GeographicCoordinate>, var bias: LocationBias)
The current state of the simulation.
| Property | Type | Default | Description |
|---|---|---|---|
var currentLocation | UserLocation | ||
var remainingLocations | List<GeographicCoordinate> | ||
var bias | LocationBias |
ManualStepCondition
Class · uniffi/ferrostar/ferrostar.kt
open class ManualStepCondition: Disposable, AutoCloseable, ManualStepConditionInterface
Never advances to the next step automatically;
requires calling NavigationController::advance_to_next_step.
You can use this to implement custom behaviors in external code.
Initialisers and methods
override fun destroy()override fun close()
ModelException
Class · uniffi/ferrostar/ferrostar.kt
sealed class ModelException: Exception()
Nested: ModelException.PolylineGenerationException, ModelException.ErrorHandler.
ModelException.PolylineGenerationException
Class · uniffi/ferrostar/ferrostar.kt
class PolylineGenerationException(val error: String) : ModelException()
| Property | Type | Default | Description |
|---|---|---|---|
val error | String | ||
val message |
NavigationCacheImpl
Class · uniffi/ferrostar/ferrostar.kt
open class NavigationCacheImpl: Disposable, AutoCloseable, NavigationCache
Initialisers and methods
override fun destroy()override fun close()override fun save(record: ByteArray)override fun load(): ByteArray?override fun delete()
NavigationCachingConfig
Class · uniffi/ferrostar/ferrostar.kt
data class NavigationCachingConfig (var cacheIntervalSeconds: Long, var maxAgeSeconds: Long)
| Property | Type | Default | Description |
|---|---|---|---|
var cacheIntervalSeconds | Long | ||
var maxAgeSeconds | Long |
NavigationController
Class · uniffi/ferrostar/ferrostar.kt
open class NavigationController: Disposable, AutoCloseable, NavigationControllerInterface
Manages the navigation lifecycle through a route, returning an updated state given inputs like user location.
Notes for implementing a new platform:
- A controller is bound to a single route; if you want recalculation, create a new instance.
- This is a pure type (no interior mutability), so a core function of your platform code is responsibly managing mutable state.
Initialisers and methods
constructor(route: Route, config: NavigationControllerConfig): Create a navigation controller for a route and configuration.override fun destroy()override fun close()
NavigationControllerConfig
Class · uniffi/ferrostar/ferrostar.kt
data class NavigationControllerConfig (var waypointAdvance: WaypointAdvanceMode, var stepAdvanceCondition: StepAdvanceCondition, var arrivalStepAdvanceCondition: StepAdvanceCondition, var routeDeviationTracking: RouteDeviationTracking, var snappedLocationCourseFiltering: CourseFiltering): Disposable
| Property | Type | Default | Description |
|---|---|---|---|
var waypointAdvance | WaypointAdvanceMode | ||
var stepAdvanceCondition | StepAdvanceCondition | ||
var arrivalStepAdvanceCondition | StepAdvanceCondition | ||
var routeDeviationTracking | RouteDeviationTracking | ||
var snappedLocationCourseFiltering | CourseFiltering |
NavigationObserverImpl
Class · uniffi/ferrostar/ferrostar.kt
open class NavigationObserverImpl: Disposable, AutoCloseable, NavigationObserver
Initialisers and methods
override fun destroy()override fun close()override fun onGetInitialState(state: NavState)override fun onUserLocationUpdate(location: UserLocation, state: NavState)override fun onAdvanceToNextStep(state: NavState)override fun onRouteAvailable(route: Route)
NavigationRecorder
Class · uniffi/ferrostar/ferrostar.kt
open class NavigationRecorder: Disposable, AutoCloseable, NavigationRecorderInterface
NavigationRecordingEvent
Class · uniffi/ferrostar/ferrostar.kt
data class NavigationRecordingEvent (var timestamp: Long, var eventData: NavigationRecordingEventData)
An event that occurs during navigation.
This is used for the optional session recording / telemetry.
| Property | Type | Default | Description |
|---|---|---|---|
var timestamp | Long | ||
var eventData | NavigationRecordingEventData |
NavigationRecordingEventData
Class · uniffi/ferrostar/ferrostar.kt
sealed class NavigationRecordingEventData
The event type.
For full replayability, we record things like rerouting, and not just location updates.
Nested: NavigationRecordingEventData.StateUpdate, NavigationRecordingEventData.RouteUpdate.
NavigationRecordingEventData.RouteUpdate
Class · uniffi/ferrostar/ferrostar.kt
data class RouteUpdate(val route: uniffi.ferrostar.Route) : NavigationRecordingEventData()
| Property | Type | Default | Description |
|---|---|---|---|
val route | uniffi.ferrostar.Route |
NavigationRecordingEventData.StateUpdate
Class · uniffi/ferrostar/ferrostar.kt
data class StateUpdate(val tripState: uniffi.ferrostar.TripState, val stepAdvanceCondition: uniffi.ferrostar.SerializableStepAdvanceCondition) : NavigationRecordingEventData()
| Property | Type | Default | Description |
|---|---|---|---|
val tripState | uniffi.ferrostar.TripState | ||
val stepAdvanceCondition | uniffi.ferrostar.SerializableStepAdvanceCondition |
NavigationReplay
Class · uniffi/ferrostar/ferrostar.kt
open class NavigationReplay: Disposable, AutoCloseable, NavigationReplayInterface
A wrapper around NavigationRecording to facilitate replaying the event stream.
Initialisers and methods
override fun destroy()override fun close()
NavigationSession
Class · uniffi/ferrostar/ferrostar.kt
open class NavigationSession: Disposable, AutoCloseable, NavigationSessionInterface
NavigationSessionCache
Class · uniffi/ferrostar/ferrostar.kt
open class NavigationSessionCache: Disposable, AutoCloseable, NavigationSessionCacheInterface
NavigationSessionSnapshot
Class · uniffi/ferrostar/ferrostar.kt
data class NavigationSessionSnapshot (var savedAt: UtcDateTime, var route: Route, var tripState: TripState?)
| Property | Type | Default | Description |
|---|---|---|---|
var savedAt | UtcDateTime | ||
var route | Route | ||
var tripState | TripState? |
Navigator
Class · uniffi/ferrostar/ferrostar.kt
open class Navigator: Disposable, AutoCloseable, NavigatorInterface
Core interface for navigation functionalities.
This trait defines the essential operations for a navigation state manager.
This lets us build additional layers (e.g. event logging)
around NavigationController in a composable manner.
Initialisers and methods
override fun destroy()override fun close()override fun route(): Routeoverride fun getInitialState(location: UserLocation): NavStateoverride fun advanceToNextStep(state: NavState): NavStateoverride fun updateUserLocation(location: UserLocation, state: NavState): NavState
NavState
Class · uniffi/ferrostar/ferrostar.kt
data class NavState (var tripState: TripState, var stepAdvanceCondition: StepAdvanceCondition): Disposable
The navigation state.
This is typically created from an initial trip state and conditions for advancing navigation to the next step. Any internal navigation state is packed in here so that the navigation controller can remain functionally pure.
| Property | Type | Default | Description |
|---|---|---|---|
var tripState | TripState | ||
var stepAdvanceCondition | StepAdvanceCondition |
OrAdvanceConditions
Class · uniffi/ferrostar/ferrostar.kt
open class OrAdvanceConditions: Disposable, AutoCloseable, OrAdvanceConditionsInterface
Advance if any of the conditions are met (OR).
This is ideal for short circuit type advance conditions.
E.g. you may have:
- A short circuit detecting if the user has exceeded a large distance from the current step.
- A default advance behavior.
Initialisers and methods
override fun destroy()override fun close()
OsrmWaypointProperties
Class · uniffi/ferrostar/ferrostar.kt
data class OsrmWaypointProperties (var name: String?, var distance: Double?)
Waypoint properties parsed from an OSRM-compatible server response.
NOTE: Some servers (such as Valhalla) may support additional parameters at request time which are not echoed back in the response time. This is unfortunate; PRs upstream would likely be welcomed! Similarly, if your server is OSRM-compatible and returns additional attributes, feel free to open a PR to include these as optional properties.
| Property | Type | Default | Description |
|---|---|---|---|
var name | String? | ||
var distance | Double? |
ParsingException
Class · uniffi/ferrostar/ferrostar.kt
sealed class ParsingException: Exception()
Nested: ParsingException.InvalidRouteObject, ParsingException.InvalidGeometry, ParsingException.MalformedAnnotations, ParsingException.InvalidStatusCode, ParsingException.UnknownParsingException, ParsingException.ErrorHandler.
ParsingException.InvalidGeometry
Class · uniffi/ferrostar/ferrostar.kt
class InvalidGeometry(val error: String) : ParsingException()
| Property | Type | Default | Description |
|---|---|---|---|
val error | String | ||
val message |
ParsingException.InvalidRouteObject
Class · uniffi/ferrostar/ferrostar.kt
class InvalidRouteObject(val error: String) : ParsingException()
| Property | Type | Default | Description |
|---|---|---|---|
val error | String | ||
val message |
ParsingException.InvalidStatusCode
Class · uniffi/ferrostar/ferrostar.kt
class InvalidStatusCode(val code: String, val description: String?) : ParsingException()
| Property | Type | Default | Description |
|---|---|---|---|
val code | String | ||
val description | String? | ||
val message |
ParsingException.MalformedAnnotations
Class · uniffi/ferrostar/ferrostar.kt
class MalformedAnnotations(val error: String) : ParsingException()
| Property | Type | Default | Description |
|---|---|---|---|
val error | String | ||
val message |
ParsingException.UnknownParsingException
Class · uniffi/ferrostar/ferrostar.kt
class UnknownParsingException() : ParsingException()
| Property | Type | Default | Description |
|---|---|---|---|
val message |
RecordingException
Class · uniffi/ferrostar/ferrostar.kt
sealed class RecordingException: Exception()
A session recording error.
Nested: RecordingException.SerializationException, RecordingException.RecordingNotEnabled, RecordingException.DeserializationException, RecordingException.ErrorHandler.
RecordingException.DeserializationException
Class · uniffi/ferrostar/ferrostar.kt
class DeserializationException(val error: String) : RecordingException()
Error during deserialization.
| Property | Type | Default | Description |
|---|---|---|---|
val error | String | ||
val message |
RecordingException.RecordingNotEnabled
Class · uniffi/ferrostar/ferrostar.kt
class RecordingNotEnabled() : RecordingException()
Recording is not enabled for this controller.
| Property | Type | Default | Description |
|---|---|---|---|
val message |
RecordingException.SerializationException
Class · uniffi/ferrostar/ferrostar.kt
class SerializationException(val error: String) : RecordingException()
Error during serialization.
| Property | Type | Default | Description |
|---|---|---|---|
val error | String | ||
val message |
Route
Class · uniffi/ferrostar/ferrostar.kt
data class Route (var geometry: List<GeographicCoordinate>, var bbox: BoundingBox, var distance: Double, var waypoints: List<Waypoint>, var steps: List<RouteStep>)
Information describing the series of steps needed to travel between two or more points.
NOTE: This type is unstable and is still under active development and should be considered unstable.
| Property | Type | Default | Description |
|---|---|---|---|
var geometry | List<GeographicCoordinate> | ||
var bbox | BoundingBox | ||
var distance | Double | ||
var waypoints | List<Waypoint> | ||
var steps | List<RouteStep> |
RouteAdapter
Class · uniffi/ferrostar/ferrostar.kt
open class RouteAdapter: Disposable, AutoCloseable, RouteAdapterInterface
The route adapter bridges between the common core and a routing backend where interaction takes place over a generic request/response flow (typically over a network; local/offline routers do not use this object as the interaction patterns are different).
This is essentially the composite of the RouteRequestGenerator and RouteResponseParser
traits, but it provides one further level of abstraction which is helpful to consumers.
As there is no way to signal compatibility between request generators and response parsers,
the RouteAdapter provides convenience constructors which take the guesswork out of it,
while still leaving consumers free to implement one or both halves.
In the future, we may provide additional methods or conveniences, and this indirection leaves the design open to such changes without necessarily breaking source compatibility. One such possible extension would be the ability to fetch more detailed attributes in real time. This is supported by the Valhalla stack, among others.
Ideas welcome re: how to signal compatibility between request generators and response parsers. I don't think we can do this in the type system, since one of the reasons for the split design is modularity, including the possibility of user-provided implementations, and these will not always be of a "known" type to the Rust side.
Initialisers and methods
constructor(requestGenerator: RouteRequestGenerator, responseParser: RouteResponseParser): Creates a route adapter from any request generator and response parser. This constructor offers unlimited flexibility, but if you're using a major routing vendor API, [RouteAdapter::from_well_known_route_provider] may be a more convenient interface.override fun destroy()override fun close()@Throws(RoutingRequestGenerationException::class) override fun generateRequest(userLocation: UserLocation, waypoints: List<Waypoint>): RouteRequest@Throws(ParsingException::class) override fun parseResponse(response: ByteArray): List<Route>
Nested: RouteAdapter.Companion.
RouteDeviation
Class · uniffi/ferrostar/ferrostar.kt
sealed class RouteDeviation
Status information that describes whether the user is proceeding according to the route or not.
Note that the name is intentionally a bit generic to allow for expansion of other states. For example, we could conceivably add a "wrong way" status in the future.
Nested: RouteDeviation.NoDeviation, RouteDeviation.Deviation.
RouteDeviation.Deviation
Class · uniffi/ferrostar/ferrostar.kt
data class Deviation(val kind: uniffi.ferrostar.DeviationKind) : RouteDeviation()
The user has deviated from the expected route.
Check the DeviationKind to determine if the user is still on the route polyline
(off the current step but on a future step) or off the route entirely.
| Property | Type | Default | Description |
|---|---|---|---|
val kind | uniffi.ferrostar.DeviationKind |
RouteDeviationDetectorImpl
Class · uniffi/ferrostar/ferrostar.kt
open class RouteDeviationDetectorImpl: Disposable, AutoCloseable, RouteDeviationDetector
A custom deviation detector (for extending the behavior of RouteDeviationTracking).
This allows for arbitrarily complex implementations when the provided ones are not enough. For example, detecting that the user is proceeding the wrong direction by keeping a ring buffer of recent locations, or perform local map matching.
Initialisers and methods
override fun destroy()override fun close()override fun checkRouteDeviation(route: Route, tripState: TripState): RouteDeviation: Determines whether the user is following the route correctly or not. NOTE: This function has a single responsibility. Side-effects like whether to recalculate a route are left to higher levels, and implementations should only be concerned with determining the facts. IMPORTANT: If you are short circuitingStepAdvanceCondition's to allow skipping steps, you must always fall back to checking the deviation from the full route line.
RouteDeviationTracking
Class · uniffi/ferrostar/ferrostar.kt
sealed class RouteDeviationTracking: Disposable
Determines if the user has deviated from the expected route.
Initialisers and methods
override fun destroy()
Nested: RouteDeviationTracking.None, RouteDeviationTracking.StaticThreshold, RouteDeviationTracking.Custom.
RouteDeviationTracking.Custom
Class · uniffi/ferrostar/ferrostar.kt
data class Custom(val detector: uniffi.ferrostar.RouteDeviationDetector) : RouteDeviationTracking()
An arbitrary user-defined implementation.
You decide with your own RouteDeviationDetector implementation!
| Property | Type | Default | Description |
|---|---|---|---|
val detector | uniffi.ferrostar.RouteDeviationDetector |
RouteDeviationTracking.StaticThreshold
Class · uniffi/ferrostar/ferrostar.kt
data class StaticThreshold(val minimumHorizontalAccuracy: UShort, val maxAcceptableDeviation: Double) : RouteDeviationTracking()
Detects deviation from the route using a configurable static distance threshold from the route line.
| Property | Type | Default | Description |
|---|---|---|---|
val minimumHorizontalAccuracy | UShort | ||
val maxAcceptableDeviation | Double |
RouteRequest
Class · uniffi/ferrostar/ferrostar.kt
sealed class RouteRequest
A route request generated by a RouteRequestGenerator.
Nested: RouteRequest.HttpPost, RouteRequest.HttpGet.
RouteRequest.HttpGet
Class · uniffi/ferrostar/ferrostar.kt
data class HttpGet(val url: String, val headers: Map<String, String>) : RouteRequest()
| Property | Type | Default | Description |
|---|---|---|---|
val url | String | ||
val headers | Map<String, String> |
RouteRequest.HttpPost
Class · uniffi/ferrostar/ferrostar.kt
data class HttpPost(val url: String, val headers: Map<String, String>, val body: ByteArray) : RouteRequest()
| Property | Type | Default | Description |
|---|---|---|---|
val url | String | ||
val headers | Map<String, String> | ||
val body | ByteArray |
RouteRequestGeneratorImpl
Class · uniffi/ferrostar/ferrostar.kt
open class RouteRequestGeneratorImpl: Disposable, AutoCloseable, RouteRequestGenerator
A trait describing any object capable of generating RouteRequests.
The interface is intentionally generic. Every routing backend has its own set of parameters, including a "profile," max travel speed, units of speed and distance, and more. It is assumed that these properties will be set at construction time or otherwise configured before use, so that we can keep the public interface as generic as possible.
Implementations may be either in Rust (most popular engines should eventually have Rust glue code) or foreign code.
Initialisers and methods
override fun destroy()override fun close()@Throws(RoutingRequestGenerationException::class) override fun generateRequest(userLocation: UserLocation, waypoints: List<Waypoint>): RouteRequest: Generates a routing backend request given the set of locations. While most implementations will treat the locations as an ordered sequence, this is not guaranteed (ex: an optimized router).
RouteResponseParserImpl
Class · uniffi/ferrostar/ferrostar.kt
open class RouteResponseParserImpl: Disposable, AutoCloseable, RouteResponseParser
A generic interface describing any object capable of parsing a response from a routing
backend into one or more Routes.
Initialisers and methods
override fun destroy()override fun close()@Throws(ParsingException::class) override fun parseResponse(response: ByteArray): List<Route>: Parses a raw response from the routing backend into a route. We use a sequence of octets as a common interchange format. as this works for all currently conceivable formats (JSON, PBF, etc.).
RouteStep
Class · uniffi/ferrostar/ferrostar.kt
data class RouteStep (var geometry: List<GeographicCoordinate>, var distance: Double, var duration: Double, var roadName: String?, var exits: List<String>, var instruction: String, var visualInstructions: List<VisualInstruction>, var spokenInstructions: List<SpokenInstruction>, var annotations: List<String>?, var incidents: List<Incident>, var drivingSide: DrivingSide?, var roundaboutExitNumber: UByte?)
A maneuver (such as a turn or merge) followed by travel of a certain distance until reaching the next step.
| Property | Type | Default | Description |
|---|---|---|---|
var geometry | List<GeographicCoordinate> | ||
var distance | Double | ||
var duration | Double | ||
var roadName | String? | ||
var exits | List<String> | ||
var instruction | String | ||
var visualInstructions | List<VisualInstruction> | ||
var spokenInstructions | List<SpokenInstruction> | ||
var annotations | List<String>? | ||
var incidents | List<Incident> | ||
var drivingSide | DrivingSide? | ||
var roundaboutExitNumber | UByte? |
RoutingRequestGenerationException
Class · uniffi/ferrostar/ferrostar.kt
sealed class RoutingRequestGenerationException: Exception()
Nested: RoutingRequestGenerationException.NotEnoughWaypoints, RoutingRequestGenerationException.JsonException, RoutingRequestGenerationException.UnknownRequestGenerationException, RoutingRequestGenerationException.ErrorHandler.
RoutingRequestGenerationException.JsonException
Class · uniffi/ferrostar/ferrostar.kt
class JsonException() : RoutingRequestGenerationException()
| Property | Type | Default | Description |
|---|---|---|---|
val message |
RoutingRequestGenerationException.NotEnoughWaypoints
Class · uniffi/ferrostar/ferrostar.kt
class NotEnoughWaypoints() : RoutingRequestGenerationException()
| Property | Type | Default | Description |
|---|---|---|---|
val message |
RoutingRequestGenerationException.UnknownRequestGenerationException
Class · uniffi/ferrostar/ferrostar.kt
class UnknownRequestGenerationException() : RoutingRequestGenerationException()
| Property | Type | Default | Description |
|---|---|---|---|
val message |
SerializableNavState
Class · uniffi/ferrostar/ferrostar.kt
data class SerializableNavState (var tripState: TripState, var stepAdvanceCondition: SerializableStepAdvanceCondition)
| Property | Type | Default | Description |
|---|---|---|---|
var tripState | TripState | ||
var stepAdvanceCondition | SerializableStepAdvanceCondition |
SerializableStepAdvanceCondition
Class · uniffi/ferrostar/ferrostar.kt
sealed class SerializableStepAdvanceCondition
Nested: SerializableStepAdvanceCondition.Manual, SerializableStepAdvanceCondition.DistanceToEndOfStep, SerializableStepAdvanceCondition.DistanceFromStep, SerializableStepAdvanceCondition.DistanceEntryExit, SerializableStepAdvanceCondition.DistanceEntryAndSnappedExit, SerializableStepAdvanceCondition.OrAdvanceConditions, SerializableStepAdvanceCondition.AndAdvanceConditions.
SerializableStepAdvanceCondition.AndAdvanceConditions
Class · uniffi/ferrostar/ferrostar.kt
data class AndAdvanceConditions(val conditions: List<uniffi.ferrostar.SerializableStepAdvanceCondition>) : SerializableStepAdvanceCondition()
| Property | Type | Default | Description |
|---|---|---|---|
val conditions | List<uniffi.ferrostar.SerializableStepAdvanceCondition> |
SerializableStepAdvanceCondition.DistanceEntryAndSnappedExit
Class · uniffi/ferrostar/ferrostar.kt
data class DistanceEntryAndSnappedExit(val distanceToEndOfStep: UShort, val distanceAfterEndStep: UShort, val minimumHorizontalAccuracy: UShort, val hasReachedEndOfCurrentStep: Boolean) : SerializableStepAdvanceCondition()
| Property | Type | Default | Description |
|---|---|---|---|
val distanceToEndOfStep | UShort | ||
val distanceAfterEndStep | UShort | ||
val minimumHorizontalAccuracy | UShort | ||
val hasReachedEndOfCurrentStep | Boolean |
SerializableStepAdvanceCondition.DistanceEntryExit
Class · uniffi/ferrostar/ferrostar.kt
data class DistanceEntryExit(val distanceToEndOfStep: UShort, val distanceAfterEndStep: UShort, val minimumHorizontalAccuracy: UShort, val hasReachedEndOfCurrentStep: Boolean) : SerializableStepAdvanceCondition()
| Property | Type | Default | Description |
|---|---|---|---|
val distanceToEndOfStep | UShort | ||
val distanceAfterEndStep | UShort | ||
val minimumHorizontalAccuracy | UShort | ||
val hasReachedEndOfCurrentStep | Boolean |
SerializableStepAdvanceCondition.DistanceFromStep
Class · uniffi/ferrostar/ferrostar.kt
data class DistanceFromStep(val distance: UShort, val minimumHorizontalAccuracy: UShort, val calculationPolicy: uniffi.ferrostar.DeviationCalculationPolicy) : SerializableStepAdvanceCondition()
| Property | Type | Default | Description |
|---|---|---|---|
val distance | UShort | ||
val minimumHorizontalAccuracy | UShort | ||
val calculationPolicy | uniffi.ferrostar.DeviationCalculationPolicy |
SerializableStepAdvanceCondition.DistanceToEndOfStep
Class · uniffi/ferrostar/ferrostar.kt
data class DistanceToEndOfStep(val distance: UShort, val minimumHorizontalAccuracy: UShort) : SerializableStepAdvanceCondition()
| Property | Type | Default | Description |
|---|---|---|---|
val distance | UShort | ||
val minimumHorizontalAccuracy | UShort |
SerializableStepAdvanceCondition.OrAdvanceConditions
Class · uniffi/ferrostar/ferrostar.kt
data class OrAdvanceConditions(val conditions: List<uniffi.ferrostar.SerializableStepAdvanceCondition>) : SerializableStepAdvanceCondition()
| Property | Type | Default | Description |
|---|---|---|---|
val conditions | List<uniffi.ferrostar.SerializableStepAdvanceCondition> |
SimulationException
Class · uniffi/ferrostar/ferrostar.kt
sealed class SimulationException: Exception()
Nested: SimulationException.PolylineException, SimulationException.NotEnoughPoints, SimulationException.ErrorHandler.
SimulationException.NotEnoughPoints
Class · uniffi/ferrostar/ferrostar.kt
class NotEnoughPoints() : SimulationException()
Not enough points in the input.
| Property | Type | Default | Description |
|---|---|---|---|
val message |
SimulationException.PolylineException
Class · uniffi/ferrostar/ferrostar.kt
class PolylineException(val error: String) : SimulationException()
Errors decoding the polyline string.
| Property | Type | Default | Description |
|---|---|---|---|
val error | String | ||
val message |
Speed
Class · uniffi/ferrostar/ferrostar.kt
data class Speed (var value: Double, var accuracy: Double?)
The speed of the user from the location provider.
| Property | Type | Default | Description |
|---|---|---|---|
var value | Double | ||
var accuracy | Double? |
SpokenInstruction
Class · uniffi/ferrostar/ferrostar.kt
data class SpokenInstruction (var text: String, var ssml: String?, var triggerDistanceBeforeManeuver: Double, var utteranceId: Uuid)
An instruction that can be synthesized using a TTS engine to announce an upcoming maneuver.
Note that these do not have any locale information attached.
| Property | Type | Default | Description |
|---|---|---|---|
var text | String | ||
var ssml | String? | ||
var triggerDistanceBeforeManeuver | Double | ||
var utteranceId | Uuid |
StepAdvanceCondition
Class · uniffi/ferrostar/ferrostar.kt
open class StepAdvanceCondition: Disposable, AutoCloseable, StepAdvanceConditionInterface
When implementing custom step advance logic, this trait allows you to define whether the condition should advance to the next condition, the next step or not.
At the moment, these must be implemented in Rust.
Initialisers and methods
override fun destroy()override fun close()override fun shouldAdvanceStep(tripState: TripState): StepAdvanceResult: This callback method is used by a step advance condition to receive step updates. The step advance condition can choose based on its outcome and internal state whether to advance to the next step or not.override fun newInstance(): StepAdvanceCondition: Creates a clean instance of this condition with the same configuration but reset state. This is used by composite conditions (Or/And) to ensure proper state isolation when any condition triggers advancement. Implementation Requirements: - Stateless conditions: Return a copy/clone of self - Stateful conditions: Return a new instance with initial state but preserve configuration parameters - Composite conditions: Recursively create fresh instances of all nested conditions This method prevents the state leakage bugs that can cause rapid step advancement and jumping behavior in navigation.
StepAdvanceResult
Class · uniffi/ferrostar/ferrostar.kt
data class StepAdvanceResult (var shouldAdvance: Boolean, var nextIteration: StepAdvanceCondition): Disposable
The step advance result is produced on every iteration of the navigation state machine and
used by the navigation to build a new NavState instance for that update.
| Property | Type | Default | Description |
|---|---|---|---|
var shouldAdvance | Boolean | ||
var nextIteration | StepAdvanceCondition |
TripProgress
Class · uniffi/ferrostar/ferrostar.kt
data class TripProgress (var distanceToNextManeuver: Double, var distanceRemaining: Double, var durationRemaining: Double)
High-level state describing progress through a route.
| Property | Type | Default | Description |
|---|---|---|---|
var distanceToNextManeuver | Double | ||
var distanceRemaining | Double | ||
var durationRemaining | Double |
TripState
Class · uniffi/ferrostar/ferrostar.kt
sealed class TripState
The state of a navigation session.
This is produced by NavigationController methods
including get_initial_state
and update_user_location.
Nested: TripState.Idle, TripState.Navigating, TripState.Complete.
TripState.Complete
Class · uniffi/ferrostar/ferrostar.kt
data class Complete(val userLocation: uniffi.ferrostar.UserLocation, val summary: uniffi.ferrostar.TripSummary) : TripState()
The navigation controller has reached the end of the trip.
| Property | Type | Default | Description |
|---|---|---|---|
val userLocation | uniffi.ferrostar.UserLocation | ||
val summary | uniffi.ferrostar.TripSummary |
TripState.Idle
Class · uniffi/ferrostar/ferrostar.kt
data class Idle(val userLocation: uniffi.ferrostar.UserLocation?) : TripState()
The navigation controller is idle and there is no active trip.
| Property | Type | Default | Description |
|---|---|---|---|
val userLocation | uniffi.ferrostar.UserLocation? |
TripState.Navigating
Class · uniffi/ferrostar/ferrostar.kt
data class Navigating(val currentStepGeometryIndex: ULong?, val userLocation: uniffi.ferrostar.UserLocation, val snappedUserLocation: uniffi.ferrostar.UserLocation, val remainingSteps: List<uniffi.ferrostar.RouteStep>, val remainingWaypoints: List<uniffi.ferrostar.Waypoint>, val progress: uniffi.ferrostar.TripProgress, val summary: uniffi.ferrostar.TripSummary, val deviation: uniffi.ferrostar.RouteDeviation, val visualInstruction: uniffi.ferrostar.VisualInstruction?, val spokenInstruction: uniffi.ferrostar.SpokenInstruction?, val annotationJson: String?) : TripState()
The navigation controller is actively navigating a trip.
| Property | Type | Default | Description |
|---|---|---|---|
val currentStepGeometryIndex | ULong? | ||
val userLocation | uniffi.ferrostar.UserLocation | ||
val snappedUserLocation | uniffi.ferrostar.UserLocation | ||
val remainingSteps | List<uniffi.ferrostar.RouteStep> | ||
val remainingWaypoints | List<uniffi.ferrostar.Waypoint> | ||
val progress | uniffi.ferrostar.TripProgress | ||
val summary | uniffi.ferrostar.TripSummary | ||
val deviation | uniffi.ferrostar.RouteDeviation | ||
val visualInstruction | uniffi.ferrostar.VisualInstruction? | ||
val spokenInstruction | uniffi.ferrostar.SpokenInstruction? | ||
val annotationJson | String? |
TripSummary
Class · uniffi/ferrostar/ferrostar.kt
data class TripSummary (var distanceTraveled: Double, var snappedDistanceTraveled: Double, var startedAt: UtcDateTime, var endedAt: UtcDateTime?)
Information pertaining to the user's full navigation trip. This includes simple stats like total duration and distance.
| Property | Type | Default | Description |
|---|---|---|---|
var distanceTraveled | Double | ||
var snappedDistanceTraveled | Double | ||
var startedAt | UtcDateTime | ||
var endedAt | UtcDateTime? |
UserLocation
Class · uniffi/ferrostar/ferrostar.kt
data class UserLocation (var coordinates: GeographicCoordinate, var horizontalAccuracy: Double, var courseOverGround: CourseOverGround?, var timestamp: java.time.Instant, var speed: Speed?)
The location of the user that is navigating.
In addition to coordinates, this includes estimated accuracy and course information, which can influence navigation logic and UI.
NOTE: Heading is absent on purpose. Heading updates are not related to a change in the user's location.
| Property | Type | Default | Description |
|---|---|---|---|
var coordinates | GeographicCoordinate | ||
var horizontalAccuracy | Double | ||
var courseOverGround | CourseOverGround? | ||
var timestamp | java.time.Instant | ||
var speed | Speed? |
ValhallaLocationSearchFilter
Class · uniffi/ferrostar/ferrostar.kt
data class ValhallaLocationSearchFilter (var excludeTunnel: Boolean? = null, var excludeBridge: Boolean? = null, var excludeTolls: Boolean? = null, var excludeFerry: Boolean? = null, var excludeRamp: Boolean? = null, var excludeClosures: Boolean? = null, var minRoadClass: ValhallaRoadClass? = null, var maxRoadClass: ValhallaRoadClass? = null, var level: Float? = null)
A set of optional filters to exclude candidate edges based on their attributes.
| Property | Type | Default | Description |
|---|---|---|---|
var excludeTunnel | Boolean? | null | |
var excludeBridge | Boolean? | null | |
var excludeTolls | Boolean? | null | |
var excludeFerry | Boolean? | null | |
var excludeRamp | Boolean? | null | |
var excludeClosures | Boolean? | null | |
var minRoadClass | ValhallaRoadClass? | null | |
var maxRoadClass | ValhallaRoadClass? | null | |
var level | Float? | null |
ValhallaWaypointProperties
Class · uniffi/ferrostar/ferrostar.kt
data class ValhallaWaypointProperties (var heading: UShort? = null, var headingTolerance: UShort? = null, var minimumReachability: UShort? = null, var radius: UShort? = null, var preferredSide: ValhallaWaypointPreferredSide? = null, var displayCoordinate: GeographicCoordinate? = null, var searchCutoff: UInt? = null, var nodeSnapTolerance: UShort? = null, var streetSideTolerance: UShort? = null, var streetSideMaxDistance: UShort? = null, var streetSideCutoff: ValhallaRoadClass? = null, var searchFilter: ValhallaLocationSearchFilter? = null, var allowUturns: Boolean? = null, var name: String? = null)
Waypoint properties supported by Valhalla servers.
Our docstrings are short here, since Valhalla is the final authority. Refer to https://valhalla.github.io/valhalla/api/turn-by-turn/api-reference/#locations for more details, including default values. Other Valhalla-based APIs such as Stadia Maps or Mapbox may have slightly different defaults. Refer to your vendor's documentation when in doubt.
NOTE: Waypoint properties will NOT currently be echoed back in OSRM format, so these are sent to the server one time.
| Property | Type | Default | Description |
|---|---|---|---|
var heading | UShort? | null | |
var headingTolerance | UShort? | null | |
var minimumReachability | UShort? | null | |
var radius | UShort? | null | |
var preferredSide | ValhallaWaypointPreferredSide? | null | |
var displayCoordinate | GeographicCoordinate? | null | |
var searchCutoff | UInt? | null | |
var nodeSnapTolerance | UShort? | null | |
var streetSideTolerance | UShort? | null | |
var streetSideMaxDistance | UShort? | null | |
var streetSideCutoff | ValhallaRoadClass? | null | |
var searchFilter | ValhallaLocationSearchFilter? | null | |
var allowUturns | Boolean? | null | |
var name | String? | null |
VisualInstruction
Class · uniffi/ferrostar/ferrostar.kt
data class VisualInstruction (var primaryContent: VisualInstructionContent, var secondaryContent: VisualInstructionContent?, var subContent: VisualInstructionContent?, var triggerDistanceBeforeManeuver: Double)
An instruction for visual display (usually as banners) at a specific point along a RouteStep.
| Property | Type | Default | Description |
|---|---|---|---|
var primaryContent | VisualInstructionContent | ||
var secondaryContent | VisualInstructionContent? | ||
var subContent | VisualInstructionContent? | ||
var triggerDistanceBeforeManeuver | Double |
VisualInstructionContent
Class · uniffi/ferrostar/ferrostar.kt
data class VisualInstructionContent (var text: String, var maneuverType: ManeuverType?, var maneuverModifier: ManeuverModifier?, var roundaboutExitDegrees: UShort?, var laneInfo: List<LaneInfo>?, var exitNumbers: List<String>)
The content of a visual instruction.
| Property | Type | Default | Description |
|---|---|---|---|
var text | String | ||
var maneuverType | ManeuverType? | ||
var maneuverModifier | ManeuverModifier? | ||
var roundaboutExitDegrees | UShort? | ||
var laneInfo | List<LaneInfo>? | ||
var exitNumbers | List<String> |
Waypoint
Class · uniffi/ferrostar/ferrostar.kt
data class Waypoint (var coordinate: GeographicCoordinate, var kind: WaypointKind, var properties: ByteArray? = null)
A waypoint along a route.
Within the context of Ferrostar, a route request consists of exactly one UserLocation
and at least one Waypoint. The route starts from the user's location (which may
contain other useful information like their current course for the [crate::routing_adapters::RouteRequestGenerator]
to use) and proceeds through one or more waypoints.
Waypoints are used during route calculation, are tracked throughout the lifecycle of a trip, and are used for recalculating when the user deviates from the expected route.
Note that support for properties beyond basic geographic coordinates varies by routing engine.
| Property | Type | Default | Description |
|---|---|---|---|
var coordinate | GeographicCoordinate | ||
var kind | WaypointKind | ||
var properties | ByteArray? | null |
WaypointAdvanceMode
Class · uniffi/ferrostar/ferrostar.kt
sealed class WaypointAdvanceMode
Controls when a waypoint should be marked as complete.
While a route may consist of thousands of points, waypoints are special. A simple trip will have only one waypoint: the final destination. A more complex trip may have several intermediate stops. Just as the navigation state keeps track of which steps remain in the route, it also tracks which waypoints are still remaining.
Tracking waypoints enables Ferrostar to reroute users when they stray off the route line. The waypoint advance mode specifies how the framework decides that a waypoint has been visited (and is removed from the list).
NOTE: Advancing to the next step and advancing to the next waypoint are separate processes. This will not normally cause any issues, but keep in mind that manually advancing to the next step does not necessarily imply that the waypoint will be marked as complete!
Nested: WaypointAdvanceMode.WaypointWithinRange, WaypointAdvanceMode.WaypointAlongAdvancingStep.
WaypointAdvanceMode.WaypointAlongAdvancingStep
Class · uniffi/ferrostar/ferrostar.kt
data class WaypointAlongAdvancingStep(val v1: Double) : WaypointAdvanceMode()
Advance when a waypoint is within a certain range of meters of any point on the advancing step.
This condition considers the step being advanced, not the user's location. As a result, it can recover when your step advance conditions allow the user to skip forward on the route.
| Property | Type | Default | Description |
|---|---|---|---|
val v1 | Double |
WaypointAdvanceMode.WaypointWithinRange
Class · uniffi/ferrostar/ferrostar.kt
data class WaypointWithinRange(val v1: Double) : WaypointAdvanceMode()
Advance when the waypoint is within a certain range of meters from the user's location.
This condition is potentially more rigorous, requiring the user to actually visit within a range of every waypoint regardless of step advance.
| Property | Type | Default | Description |
|---|---|---|---|
val v1 | Double |
WellKnownRouteProvider
Class · uniffi/ferrostar/ferrostar.kt
sealed class WellKnownRouteProvider
Configurations for built-in route providers.
Nested: WellKnownRouteProvider.Valhalla, WellKnownRouteProvider.GraphHopper.
WellKnownRouteProvider.GraphHopper
Class · uniffi/ferrostar/ferrostar.kt
data class GraphHopper(val endpointUrl: String, val profile: String, val locale: String, val voiceUnits: uniffi.ferrostar.GraphHopperVoiceUnits, val optionsJson: String? = null) : WellKnownRouteProvider()
A GraphHopper-based routing API.
GraphHopper offers a commercially supported API. You can also substitute any other URL to use a self-hosted server.
| Property | Type | Default | Description |
|---|---|---|---|
val endpointUrl | String | ||
val profile | String | ||
val locale | String | ||
val voiceUnits | uniffi.ferrostar.GraphHopperVoiceUnits | ||
val optionsJson | String? | null |
WellKnownRouteProvider.Valhalla
Class · uniffi/ferrostar/ferrostar.kt
data class Valhalla(val endpointUrl: String, val profile: String, val optionsJson: String? = null) : WellKnownRouteProvider()
A Valhalla-based routing API.
Stadia Maps offers a commercially supported API. You can also substitute any URL to use a self-hosted server.
| Property | Type | Default | Description |
|---|---|---|---|
val endpointUrl | String | ||
val profile | String | ||
val optionsJson | String? | null |
Enums (uniffi.ferrostar)
BlockedLane, CourseFiltering, DeviationCalculationPolicy, DrivingSide, GraphHopperVoiceUnits, Impact, IncidentType, ManeuverModifier, ManeuverType, ValhallaRoadClass, ValhallaWaypointPreferredSide, WaypointKind
BlockedLane
Enum · uniffi/ferrostar/ferrostar.kt
enum class BlockedLane
The lane type blocked by the incident.
| Case | Description |
|---|---|
LEFT | |
LEFT_CENTER | |
LEFT_TURN_LANE | |
CENTER | |
RIGHT | |
RIGHT_CENTER | |
RIGHT_TURN_LANE | |
HOV |
CourseFiltering
Enum · uniffi/ferrostar/ferrostar.kt
enum class CourseFiltering
Controls filtering/post-processing of user course by the NavigationController.
| Case | Description |
|---|---|
SNAP_TO_ROUTE | Snap the user's course to the current step's linestring using the next index in the step's geometry. |
RAW | Use the raw course as reported by the location provider with no processing. |
DeviationCalculationPolicy
Enum · uniffi/ferrostar/ferrostar.kt
enum class DeviationCalculationPolicy
Controls when a deviation-aware step-advance condition is allowed to evaluate,
based on the user's current
RouteDeviation status.
| Case | Description |
|---|---|
ALWAYS | Always evaluate, regardless of deviation status. |
WHILE_ON_ROUTE | Evaluate while the user is still somewhere on the route polyline (current step or any future step), but suspend if the user is completely off the route. |
WHILE_ON_CURRENT_STEP | Evaluate only while the user is within an acceptable deviation of the current step's polyline. Suspend on any deviation (whether off-step-but-on-route, or completely off-route). |
DrivingSide
Enum · uniffi/ferrostar/ferrostar.kt
enum class DrivingSide
Which side of the road traffic drives on.
This is needed by consumers like Android Auto to determine whether a roundabout should be rendered as clockwise (right-hand traffic) or counterclockwise (left-hand traffic).
| Case | Description |
|---|---|
LEFT | |
RIGHT |
GraphHopperVoiceUnits
Enum · uniffi/ferrostar/ferrostar.kt
enum class GraphHopperVoiceUnits
| Case | Description |
|---|---|
METRIC | |
IMPERIAL |
Impact
Enum · uniffi/ferrostar/ferrostar.kt
enum class Impact
The impact of the incident that has occurred.
| Case | Description |
|---|---|
UNKNOWN | |
CRITICAL | |
MAJOR | |
MINOR | |
LOW |
IncidentType
Enum · uniffi/ferrostar/ferrostar.kt
enum class IncidentType
The type of incident that has occurred.
| Case | Description |
|---|---|
ACCIDENT | |
CONGESTION | |
CONSTRUCTION | |
DISABLED_VEHICLE | |
LANE_RESTRICTION | |
MASS_TRANSIT | |
MISCELLANEOUS | |
OTHER_NEWS | |
PLANNED_EVENT | |
ROAD_CLOSURE | |
ROAD_HAZARD | |
WEATHER |
ManeuverModifier
Enum · uniffi/ferrostar/ferrostar.kt
enum class ManeuverModifier
Additional information to further specify a ManeuverType.
| Case | Description |
|---|---|
U_TURN | |
SHARP_RIGHT | |
RIGHT | |
SLIGHT_RIGHT | |
STRAIGHT | |
SLIGHT_LEFT | |
LEFT | |
SHARP_LEFT |
ManeuverType
Enum · uniffi/ferrostar/ferrostar.kt
enum class ManeuverType
The broad class of maneuver to perform.
This is usually combined with ManeuverModifier in VisualInstructionContent.
| Case | Description |
|---|---|
TURN | |
NEW_NAME | |
DEPART | |
ARRIVE | |
MERGE | |
ON_RAMP | |
OFF_RAMP | |
FORK | |
END_OF_ROAD | |
CONTINUE | |
ROUNDABOUT | |
ROTARY | |
ROUNDABOUT_TURN | |
NOTIFICATION | |
EXIT_ROUNDABOUT | |
EXIT_ROTARY |
ValhallaRoadClass
Enum · uniffi/ferrostar/ferrostar.kt
enum class ValhallaRoadClass
A road class in the Valhalla taxonomy.
These are ordered from highest (fastest travel speed) to lowest.
| Case | Description |
|---|---|
MOTORWAY | |
TRUNK | |
PRIMARY | |
SECONDARY | |
TERTIARY | |
UNCLASSIFIED | |
RESIDENTIAL | |
SERVICE_OTHER |
ValhallaWaypointPreferredSide
Enum · uniffi/ferrostar/ferrostar.kt
enum class ValhallaWaypointPreferredSide
Specifies a preferred side for departing from / arriving at a location.
Examples:
- Germany drives on the right side of the road. A value of
samewill only allow leaving or arriving at a location such that it is on your right. - Australia drives on the left side of the road. Passing a value of
samewill only allow leaving or arriving at a location such that it is on your left.
| Case | Description |
|---|---|
SAME | You must depart from or arrive at the location on the same side as you drive. |
OPPOSITE | You must depart from or arrive at the location on the opposite side as you drive. |
EITHER | No preference; you can depart or arrive from any direction. |
WaypointKind
Enum · uniffi/ferrostar/ferrostar.kt
enum class WaypointKind
Describes characteristics of the waypoint for routing purposes.
| Case | Description |
|---|---|
BREAK | Starts or ends a leg of the trip. Most routing engines will generate arrival and departure instructions. Some routing engines do not support multi-leg routes, so an intermediate break may behave like a [WaypointKind::Via]. |
VIA | A waypoint that is simply passed through, but will not have any arrival or departure instructions. |
Interfaces (uniffi.ferrostar)
AndAdvanceConditionsInterface, DistanceEntryAndExitConditionInterface, DistanceEntryAndSnappedExitConditionInterface, DistanceFromStepConditionInterface, DistanceToEndOfStepConditionInterface, ManualStepConditionInterface, NavigationCache, NavigationControllerInterface, NavigationObserver, NavigationRecorderInterface, NavigationReplayInterface, NavigationSessionCacheInterface, NavigationSessionInterface, NavigatorInterface, OrAdvanceConditionsInterface, RouteAdapterInterface, RouteDeviationDetector, RouteRequestGenerator, RouteResponseParser, StepAdvanceConditionInterface
AndAdvanceConditionsInterface
Interface · uniffi/ferrostar/ferrostar.kt
public interface AndAdvanceConditionsInterface
Advance if all of the conditions are met (AND).
DistanceEntryAndExitConditionInterface
Interface · uniffi/ferrostar/ferrostar.kt
public interface DistanceEntryAndExitConditionInterface
A stateful condition that requires the user to reach the end of the step then proceed past it to advance.
DistanceEntryAndSnappedExitConditionInterface
Interface · uniffi/ferrostar/ferrostar.kt
public interface DistanceEntryAndSnappedExitConditionInterface
A stateful condition that requires the user to reach the end of the step then proceed past it to advance.
This variant uses route snapping (snapping to the combined current+next step geometry) for the exit check, making it more robust for pedestrian/hiking navigation where users may walk on the opposite side of the street or wander around the optimal path. The route-snapped exit check prevents premature advancement while still allowing natural pedestrian movement patterns. The exit distance is measured from the current step to the route-snapped position.
DistanceFromStepConditionInterface
Interface · uniffi/ferrostar/ferrostar.kt
public interface DistanceFromStepConditionInterface
Advances once the user is at least [Self::distance] meters from the current step's polyline.
This results in delayed advance, but is more robust to spurious / unwanted step changes in scenarios including self-intersecting routes (sudden jumps to the next step) and pauses at intersections (advancing too soon before the maneuver is complete).
NOTE! This may be less robust to things like short steps, out-and-backs, and U-turns, where this may eagerly exit a current step before the user has traversed it if the start of the step is within range of the end.
DistanceToEndOfStepConditionInterface
Interface · uniffi/ferrostar/ferrostar.kt
public interface DistanceToEndOfStepConditionInterface
Automatically advances when the user's location is close enough to the end of the step.
This results in an eager advance where the user will jump to the next step when the condition is met.
ManualStepConditionInterface
Interface · uniffi/ferrostar/ferrostar.kt
public interface ManualStepConditionInterface
Never advances to the next step automatically;
requires calling NavigationController::advance_to_next_step.
You can use this to implement custom behaviors in external code.
NavigationCache
Interface · uniffi/ferrostar/ferrostar.kt
public interface NavigationCache
Initialisers and methods
fun save(record: ByteArray)fun load(): ByteArray?fun delete()
NavigationControllerInterface
Interface · uniffi/ferrostar/ferrostar.kt
public interface NavigationControllerInterface
Manages the navigation lifecycle through a route, returning an updated state given inputs like user location.
Notes for implementing a new platform:
- A controller is bound to a single route; if you want recalculation, create a new instance.
- This is a pure type (no interior mutability), so a core function of your platform code is responsibly managing mutable state.
NavigationObserver
Interface · uniffi/ferrostar/ferrostar.kt
public interface NavigationObserver
Initialisers and methods
fun onGetInitialState(state: NavState)fun onUserLocationUpdate(location: UserLocation, state: NavState)fun onAdvanceToNextStep(state: NavState)fun onRouteAvailable(route: Route)
NavigationRecorderInterface
Interface · uniffi/ferrostar/ferrostar.kt
public interface NavigationRecorderInterface
Initialisers and methods
fun getEvents(): List<NavigationRecordingEvent>fun getRecordingJson(): Stringfun onAdvanceToNextStep(state: NavState)fun onGetInitialState(state: NavState)fun onRouteAvailable(route: Route)fun onUserLocationUpdate(location: UserLocation, state: NavState)
NavigationReplayInterface
Interface · uniffi/ferrostar/ferrostar.kt
public interface NavigationReplayInterface
A wrapper around NavigationRecording to facilitate replaying the event stream.
NavigationSessionCacheInterface
Interface · uniffi/ferrostar/ferrostar.kt
public interface NavigationSessionCacheInterface
Initialisers and methods
fun canResume(): Boolean: Check if the navigation session can be resumed.fun load(): NavigationSessionSnapshot?: Load the navigation session record from the cache if it exists and is not stale.fun onAdvanceToNextStep(state: NavState)fun onGetInitialState(state: NavState)fun onRouteAvailable(route: Route)fun onUserLocationUpdate(location: UserLocation, state: NavState)
NavigationSessionInterface
Interface · uniffi/ferrostar/ferrostar.kt
public interface NavigationSessionInterface
Initialisers and methods
fun advanceToNextStep(state: NavState): NavStatefun getInitialState(location: UserLocation): NavStatefun route(): Routefun updateUserLocation(location: UserLocation, state: NavState): NavState
NavigatorInterface
Interface · uniffi/ferrostar/ferrostar.kt
public interface NavigatorInterface
Core interface for navigation functionalities.
This trait defines the essential operations for a navigation state manager.
This lets us build additional layers (e.g. event logging)
around NavigationController in a composable manner.
Initialisers and methods
fun route(): Routefun getInitialState(location: UserLocation): NavStatefun advanceToNextStep(state: NavState): NavStatefun updateUserLocation(location: UserLocation, state: NavState): NavState
OrAdvanceConditionsInterface
Interface · uniffi/ferrostar/ferrostar.kt
public interface OrAdvanceConditionsInterface
Advance if any of the conditions are met (OR).
This is ideal for short circuit type advance conditions.
E.g. you may have:
- A short circuit detecting if the user has exceeded a large distance from the current step.
- A default advance behavior.
RouteAdapterInterface
Interface · uniffi/ferrostar/ferrostar.kt
public interface RouteAdapterInterface
The route adapter bridges between the common core and a routing backend where interaction takes place over a generic request/response flow (typically over a network; local/offline routers do not use this object as the interaction patterns are different).
This is essentially the composite of the RouteRequestGenerator and RouteResponseParser
traits, but it provides one further level of abstraction which is helpful to consumers.
As there is no way to signal compatibility between request generators and response parsers,
the RouteAdapter provides convenience constructors which take the guesswork out of it,
while still leaving consumers free to implement one or both halves.
In the future, we may provide additional methods or conveniences, and this indirection leaves the design open to such changes without necessarily breaking source compatibility. One such possible extension would be the ability to fetch more detailed attributes in real time. This is supported by the Valhalla stack, among others.
Ideas welcome re: how to signal compatibility between request generators and response parsers. I don't think we can do this in the type system, since one of the reasons for the split design is modularity, including the possibility of user-provided implementations, and these will not always be of a "known" type to the Rust side.
Initialisers and methods
fun generateRequest(userLocation: UserLocation, waypoints: List<Waypoint>): RouteRequestfun parseResponse(response: ByteArray): List<Route>
RouteDeviationDetector
Interface · uniffi/ferrostar/ferrostar.kt
public interface RouteDeviationDetector
A custom deviation detector (for extending the behavior of RouteDeviationTracking).
This allows for arbitrarily complex implementations when the provided ones are not enough. For example, detecting that the user is proceeding the wrong direction by keeping a ring buffer of recent locations, or perform local map matching.
Initialisers and methods
fun checkRouteDeviation(route: Route, tripState: TripState): RouteDeviation: Determines whether the user is following the route correctly or not. NOTE: This function has a single responsibility. Side-effects like whether to recalculate a route are left to higher levels, and implementations should only be concerned with determining the facts. IMPORTANT: If you are short circuitingStepAdvanceCondition's to allow skipping steps, you must always fall back to checking the deviation from the full route line.
RouteRequestGenerator
Interface · uniffi/ferrostar/ferrostar.kt
public interface RouteRequestGenerator
A trait describing any object capable of generating RouteRequests.
The interface is intentionally generic. Every routing backend has its own set of parameters, including a "profile," max travel speed, units of speed and distance, and more. It is assumed that these properties will be set at construction time or otherwise configured before use, so that we can keep the public interface as generic as possible.
Implementations may be either in Rust (most popular engines should eventually have Rust glue code) or foreign code.
Initialisers and methods
fun generateRequest(userLocation: UserLocation, waypoints: List<Waypoint>): RouteRequest: Generates a routing backend request given the set of locations. While most implementations will treat the locations as an ordered sequence, this is not guaranteed (ex: an optimized router).
RouteResponseParser
Interface · uniffi/ferrostar/ferrostar.kt
public interface RouteResponseParser
A generic interface describing any object capable of parsing a response from a routing
backend into one or more Routes.
Initialisers and methods
fun parseResponse(response: ByteArray): List<Route>: Parses a raw response from the routing backend into a route. We use a sequence of octets as a common interchange format. as this works for all currently conceivable formats (JSON, PBF, etc.).
StepAdvanceConditionInterface
Interface · uniffi/ferrostar/ferrostar.kt
public interface StepAdvanceConditionInterface
When implementing custom step advance logic, this trait allows you to define whether the condition should advance to the next condition, the next step or not.
At the moment, these must be implemented in Rust.
Initialisers and methods
fun shouldAdvanceStep(tripState: TripState): StepAdvanceResult: This callback method is used by a step advance condition to receive step updates. The step advance condition can choose based on its outcome and internal state whether to advance to the next step or not.fun newInstance(): StepAdvanceCondition: Creates a clean instance of this condition with the same configuration but reset state. This is used by composite conditions (Or/And) to ensure proper state isolation when any condition triggers advancement. Implementation Requirements: - Stateless conditions: Return a copy/clone of self - Stateful conditions: Return a new instance with initial state but preserve configuration parameters - Composite conditions: Recursively create fresh instances of all nested conditions This method prevents the state leakage bugs that can cause rapid step advancement and jumping behavior in navigation.
Objects (uniffi.ferrostar)
InstantiationException.ErrorHandler, LocationBias.None, ModelException.ErrorHandler, ParsingException.ErrorHandler, RecordingException.ErrorHandler, RouteAdapter.Companion, RouteDeviation.NoDeviation, RouteDeviationTracking.None, RoutingRequestGenerationException.ErrorHandler, SerializableStepAdvanceCondition.Manual, SimulationException.ErrorHandler
InstantiationException.ErrorHandler
Object · uniffi/ferrostar/ferrostar.kt
companion object ErrorHandler : UniffiRustCallStatusErrorHandler<InstantiationException>
LocationBias.None
Object · uniffi/ferrostar/ferrostar.kt
object None : LocationBias()
No position bias - locations follow the route line exactly.
This provides "perfect" GPS behavior, useful for testing basic route following without position uncertainty.
ModelException.ErrorHandler
Object · uniffi/ferrostar/ferrostar.kt
companion object ErrorHandler : UniffiRustCallStatusErrorHandler<ModelException>
ParsingException.ErrorHandler
Object · uniffi/ferrostar/ferrostar.kt
companion object ErrorHandler : UniffiRustCallStatusErrorHandler<ParsingException>
RecordingException.ErrorHandler
Object · uniffi/ferrostar/ferrostar.kt
companion object ErrorHandler : UniffiRustCallStatusErrorHandler<RecordingException>
RouteAdapter.Companion
Object · uniffi/ferrostar/ferrostar.kt
companion object
Initialisers and methods
@Throws(InstantiationException::class) fun fromWellKnownRouteProvider(wellKnownRouteProvider: WellKnownRouteProvider): RouteAdapter: Creates a route adapter from a well-known provider configuration.
RouteDeviation.NoDeviation
Object · uniffi/ferrostar/ferrostar.kt
object NoDeviation : RouteDeviation()
The user is proceeding on course within the expected tolerances; everything is normal.
RouteDeviationTracking.None
Object · uniffi/ferrostar/ferrostar.kt
object None : RouteDeviationTracking()
No checks will be done, and we assume the user is always following the route.
RoutingRequestGenerationException.ErrorHandler
Object · uniffi/ferrostar/ferrostar.kt
companion object ErrorHandler : UniffiRustCallStatusErrorHandler<RoutingRequestGenerationException>
SerializableStepAdvanceCondition.Manual
Object · uniffi/ferrostar/ferrostar.kt
object Manual : SerializableStepAdvanceCondition()
SimulationException.ErrorHandler
Object · uniffi/ferrostar/ferrostar.kt
companion object ErrorHandler : UniffiRustCallStatusErrorHandler<SimulationException>
Functions (uniffi.ferrostar)
advanceLocationSimulation, createNavigationSession, createNavigator, createOsrmResponseParser, createRouteFromOsrm, createRouteFromOsrmRoute, createValhallaRequestGenerator, createWaypointWithValhallaProperties, getRoutePolyline, locationSimulationFromCoordinates, locationSimulationFromPolyline, locationSimulationFromRoute, stepAdvanceAnd, stepAdvanceDistanceEntryAndExit, stepAdvanceDistanceEntryAndSnappedExit, stepAdvanceDistanceFromStep, stepAdvanceDistanceToEndOfStep, stepAdvanceManual, stepAdvanceOr
advanceLocationSimulation
Function · uniffi/ferrostar/ferrostar.kt
fun advanceLocationSimulation(state: LocationSimulationState): LocationSimulationState
Returns the next simulation state based on the desired strategy. Results of this can be thought of like a stream from a generator function.
This function is intended to be called once/second. However, the caller may vary speed to purposefully replay at a faster rate (ex: calling 3x per second will be a triple speed simulation).
When there are now more locations to visit, returns the same state forever.
createNavigationSession
Function · uniffi/ferrostar/ferrostar.kt
fun createNavigationSession(route: Route, config: NavigationControllerConfig, observers: List<NavigationObserver>): NavigationSession
Creates a new navigation session for the given route and configuration.
It returns an Arc-wrapped trait object implementing Navigator.
If should_record is true, it creates a controller with event recording enabled.
createNavigator
Function · uniffi/ferrostar/ferrostar.kt
fun createNavigator(route: Route, config: NavigationControllerConfig, shouldRecord: Boolean): Navigator
Creates a new navigation controller for the given route and configuration.
It returns an Arc-wrapped trait object implementing Navigator.
If should_record is true, it creates a controller with event recording enabled.
createOsrmResponseParser
Function · uniffi/ferrostar/ferrostar.kt
fun createOsrmResponseParser(polylinePrecision: UInt): RouteResponseParser
Creates a RouteResponseParser capable of parsing OSRM responses.
This response parser is designed to be fairly flexible, supporting both vanilla OSRM and enhanced Valhalla (ex: from Stadia Maps and Mapbox) outputs which contain richer information like banners and voice instructions for navigation.
createRouteFromOsrm
Function · uniffi/ferrostar/ferrostar.kt
@Throws(ParsingException::class) fun createRouteFromOsrm(routeData: ByteArray, waypointData: ByteArray, polylinePrecision: UInt): Route
Creates a Route from OSRM data.
This uses the same logic as the OsrmResponseParser and is designed to be fairly flexible,
supporting both vanilla OSRM and enhanced Valhalla (ex: from Stadia Maps and Mapbox) outputs
which contain richer information like banners and voice instructions for navigation.
createRouteFromOsrmRoute
Function · uniffi/ferrostar/ferrostar.kt
@Throws(ParsingException::class) fun createRouteFromOsrmRoute(routeData: ByteArray, waypoints: List<Waypoint>, polylinePrecision: UInt): Route
Creates a Route from OSRM route data and ferrostar waypoints.
This uses the same logic as the OsrmResponseParser and is designed to be fairly flexible,
supporting both vanilla OSRM and enhanced Valhalla (ex: from Stadia Maps and Mapbox) outputs
which contain richer information like banners and voice instructions for navigation.
createValhallaRequestGenerator
Function · uniffi/ferrostar/ferrostar.kt
@Throws(InstantiationException::class) fun createValhallaRequestGenerator(endpointUrl: String, profile: String, optionsJson: String?): RouteRequestGenerator
Creates a RouteRequestGenerator
which generates requests to an arbitrary Valhalla server (using the OSRM response format).
This is provided as a convenience for use from foreign code when creating your own [routing_adapters::RouteAdapter].
createWaypointWithValhallaProperties
Function · uniffi/ferrostar/ferrostar.kt
fun createWaypointWithValhallaProperties(coordinate: GeographicCoordinate, kind: WaypointKind, properties: ValhallaWaypointProperties): Waypoint
A convenience helper for creating waypoints with Valhalla rich location properties.
Regrettably this must live as a top-level function unless constructors for record types lands
in UniFFI:
https://github.com/mozilla/uniffi-rs/issues/1935.
getRoutePolyline
Function · uniffi/ferrostar/ferrostar.kt
@Throws(ModelException::class) fun getRoutePolyline(route: Route, precision: UInt): String
Helper function for getting the route as an encoded polyline.
Mostly used for debugging.
locationSimulationFromCoordinates
Function · uniffi/ferrostar/ferrostar.kt
@Throws(SimulationException::class) fun locationSimulationFromCoordinates(coordinates: List<GeographicCoordinate>, resampleDistance: Double?, bias: LocationBias): LocationSimulationState
Creates a location simulation from a set of coordinates.
Optionally resamples the input line so that there is a maximum distance between points.
locationSimulationFromPolyline
Function · uniffi/ferrostar/ferrostar.kt
@Throws(SimulationException::class) fun locationSimulationFromPolyline(polyline: String, precision: UInt, resampleDistance: Double?, bias: LocationBias): LocationSimulationState
Creates a location simulation from a polyline.
Optionally resamples the input line so that there is no more than the specified maximum distance between points.
locationSimulationFromRoute
Function · uniffi/ferrostar/ferrostar.kt
@Throws(SimulationException::class) fun locationSimulationFromRoute(route: Route, resampleDistance: Double?, bias: LocationBias): LocationSimulationState
Creates a location simulation from a route.
Optionally resamples the route geometry so that there is no more than the specified maximum distance between points.
stepAdvanceAnd
Function · uniffi/ferrostar/ferrostar.kt
fun stepAdvanceAnd(conditions: List<StepAdvanceCondition>): StepAdvanceCondition
Convenience function for creating an AndAdvanceConditions.
This composes multiple conditions together and advances to the next step if ALL of them trigger.
stepAdvanceDistanceEntryAndExit
Function · uniffi/ferrostar/ferrostar.kt
fun stepAdvanceDistanceEntryAndExit(distanceToEndOfStep: UShort, distanceAfterEndOfStep: UShort, minimumHorizontalAccuracy: UShort): StepAdvanceCondition
Convenience function for creating a DistanceEntryAndExitCondition.
Requires the user to first travel within distance_to_end_of_step meters of the end of the step,
and then travel at least distance_after_end_of_step meters away from the step geometry.
This ensures the user completes the maneuver before advancing to the next step.
stepAdvanceDistanceEntryAndSnappedExit
Function · uniffi/ferrostar/ferrostar.kt
fun stepAdvanceDistanceEntryAndSnappedExit(distanceToEndOfStep: UShort, distanceAfterEndOfStep: UShort, minimumHorizontalAccuracy: UShort): StepAdvanceCondition
Convenience function for creating a DistanceEntryAndSnappedExitCondition.
This variant uses route snapping for better handling of pedestrian/hiking navigation scenarios
where users may walk on the opposite side of the street or wander around the optimal path.
Requires the user to first travel within distance_to_end_of_step meters of the end of the step,
and then the route-snapped position moves distance_after_end_of_step meters from the current step.
The snapping to the combined route (current+next steps) prevents premature advancement.
The exit distance is automatically capped to the next step's length to prevent getting stuck on short steps.
Recommended values for pedestrian navigation: entry 20m, exit 2-5m.
stepAdvanceDistanceFromStep
Function · uniffi/ferrostar/ferrostar.kt
fun stepAdvanceDistanceFromStep(distance: UShort, minimumHorizontalAccuracy: UShort, calculationPolicy: DeviationCalculationPolicy): StepAdvanceCondition
Convenience function for creating a DistanceFromStepCondition.
This advances to the next step when the user is at least distance meters away from any point
on the current route step geometry.
Does not advance unless the reported location accuracy is minimum_horizontal_accuracy
meters or better.
calculation_policy controls when this condition is permitted to evaluate
based on the user's current route deviation status.
stepAdvanceDistanceToEndOfStep
Function · uniffi/ferrostar/ferrostar.kt
fun stepAdvanceDistanceToEndOfStep(distance: UShort, minimumHorizontalAccuracy: UShort): StepAdvanceCondition
Convenience function for creating a DistanceToEndOfStepCondition.
This advances to the next step when the user is within distance meters of the last point in the current route step.
Does not advance unless the reported location accuracy is minimum_horizontal_accuracy meters or better.
stepAdvanceManual
Function · uniffi/ferrostar/ferrostar.kt
fun stepAdvanceManual(): StepAdvanceCondition
Convenience function for creating a ManualStepCondition.
This never advances to the next step automatically.
You must manually advance to the next step programmatically using a FerrostarCore
platform wrapper or by calling [super::Navigator::advance_to_next_step] manually.
stepAdvanceOr
Function · uniffi/ferrostar/ferrostar.kt
fun stepAdvanceOr(conditions: List<StepAdvanceCondition>): StepAdvanceCondition
Convenience function for creating an OrAdvanceConditions.
This composes multiple conditions together and advances to the next step if ANY of them trigger.
Type aliases (uniffi.ferrostar)
UtcDateTime
Type alias · uniffi/ferrostar/ferrostar.kt
public typealias UtcDateTime = java.util.Date
Typealias from the type name used in the UDL file to the custom type. This is needed because the UDL type name is used in function/method signatures. It's also what we have an external type that references a custom type.
Uuid
Type alias · uniffi/ferrostar/ferrostar.kt
public typealias Uuid = java.util.UUID
Typealias from the type name used in the UDL file to the custom type. This is needed because the UDL type name is used in function/method signatures. It's also what we have an external type that references a custom type.