Navigation Settings
Available in SDK 0.5.2 on iOS, Android and WebXR. scanOnNewTrip was added in 0.5.4. SDK 0.6.9 adds the Q20 run-completion controls and continueGuidanceDuringRunExitCorrection on all three platforms.
The SDK uses one field-tested navigation and localization-recovery policy across standard routes and custom guidance presentations. Your app supplies route data, authenticated transport and UI. It does not need its own drift timers or another recovery coordinator.
VPSNavigationSettings exposes thresholds and timings for integrations that need different behavior. Omit overrides to keep the field-tested defaults. The current Treedis applications use those defaults. Settings names and default values match across the three platforms.
Configure a session
Only override values your application intentionally needs to change. Other values retain their defaults. These examples demonstrate an override; they are not settings required by Treedis applications.
iOS
import TreedisVPS
let policy = try VPSNavigationSettings(
offRouteMeters: 4,
correctionTimeoutSeconds: 9
)
let session = VPSSession(configuration: VPSConfiguration(
serverURL: serverURL,
apiKey: apiKey,
navigationSettings: policy
))
VPSNavigationSettings() returns the defaults. The typed initializer with overrides throws for invalid input. Partial JSON decoding also fills omitted values from defaults and rejects unknown or invalid settings.
For barometer-assisted completion, add NSMotionUsageDescription to the app and App Clip Info.plist. The SDK can request the first motion permission when starting the sensor. Missing permission, denied access or unavailable hardware leaves camera, route-progress and time fallbacks available.
Android
import com.treedis.vps.*
val session = VPSSession(context, VPSConfiguration(
serverURL = serverURL,
apiKey = apiKey,
navigationSettings = VPSNavigationSettings(
offRouteMeters = 4.0,
correctionTimeoutSeconds = 9.0,
),
))
VPSNavigationSettings() returns the defaults. Invalid constructor values throw IllegalArgumentException. The SDK uses an available pressure sensor for relative height; a missing sensor leaves camera, route-progress and time fallbacks available.
WebXR
import { VPSSession } from '@treedis/vps-webxr';
const session = new VPSSession({
serverURL,
apiKey,
navigationSettings: {
offRouteMeters: 4,
correctionTimeoutSeconds: 9,
},
});
WebXR also exports defaultNavigationSettings, resolveNavigationSettings and the readonly VPSNavigationSettings type. The resolver validates, copies and freezes an override object. Changing the caller's original object cannot mutate a running coordinator. Browser hardware determines which camera/altitude inputs are available; the time fallback remains part of the same policy.
Lifetime and validation
Configure policy before starting navigation. Coordinators snapshot settings; they are not mutable live timers. Create a new coordinator/session for a policy change. Native recovery also supports configuration while inactive.
- Numbers must be finite and nonnegative.
- Correction/request/run-exit timeouts, scan retry and ride speeds must be positive.
- Shares must be between zero and one.
routeRetryLimitmust be an integer from zero through ten. Its default is zero, so automatic transport retry is disabled.afterTurnWindowMetersmust includeafterTurnMeters.climbingWindowToleranceSecondscannot exceedclimbingWindowSeconds.- Turn/bend angles cannot exceed 180 degrees; the bend threshold cannot exceed the turn threshold.
scanOnNewTripandcontinueGuidanceDuringRunExitCorrectionmust betrueorfalse; all other settings are numbers.cameraHeightMinimumMetersmust not exceedcameraHeightMeters, which must not exceedcameraHeightMaximumMeters.rideMaximumRateMetersPerSecondandrunProgressSpeedMetersPerSecondmust be positive.
Units and defaults
Positions and distances use Y-up metres. Durations use seconds, speeds use metres per second, angles use degrees and progress shares use 0–1. routeRetryLimit is a count and the two policy flags are true/false. The SDK archives include the same defaults in NavigationSettings.defaults.json.
| Setting | Default | Behavior |
|---|---|---|
offRouteMeters |
3 | Lateral route deviation that can request a correction. |
correctionTimeoutSeconds |
6 | Wait for correction; ordinary drift can reroute, while unresolved landing drift requires a full scan. |
correctionSettleSeconds |
0.6 | Settle interval after an accepted fix before treating a corrected off-route pose as settled. |
quietFixMinimumGapSeconds |
8 | Minimum interval between eligible turn/gate correction requests. |
recentFixSeconds |
5 | Suppress redundant correction immediately after an accepted localization fix. |
rerouteCooldownSeconds |
5 | Walking deviation cooldown after route installation or recovery. |
routeRequestTimeoutSeconds |
8 | Time an in-flight route request blocks guidance. Authenticated transport remains host-owned. |
routeRetrySeconds |
3 | Delay between route attempts when retry is enabled. |
routeRetryLimit |
0 | Automatic route retries after transport failure; zero disables retries. |
scanRetrySeconds |
15 | Retry interval while full scanning remains pending. |
trackingLostSeconds |
3 | Duration of untrusted tracking before the position is considered lost. |
resumeLostSeconds |
1.5 | Time away after which foreground resume requires recovery. |
afterTurnMeters |
2 | Distance past a turn that permits its background correction. |
afterTurnWindowMeters |
6 | End of the post-turn correction window. |
gatePassedMeters |
1 | Distance beyond a gate before its correction request becomes eligible. |
gateLateralMeters |
3 | Maximum gate distance from the route for passage-based correction. |
runEntryLateralMeters |
3 | Maximum lateral deviation when selecting an active stairs/escalator section. |
runMinimumClimbMeters |
2 | Minimum mapped climb for an automatic walked-run candidate. |
runRetreatMeters |
3 | Distance behind the entry that can cancel an unconfirmed run. |
runRetreatMaximumShare |
0.2 | Maximum observed barometer progress that still permits entry retreat. |
runApproachMeters |
15 | Approach distance in which climbing can activate an upcoming run. |
runExitHorizontalMeters |
2 | Exit agreement in the horizontal plane for a quiet exit correction. |
runExitVerticalMeters |
1.5 | Exit height agreement for a quiet exit correction. |
runExitTimeoutSeconds |
8 | Fresh-fix deadline at a distant run exit. At timeout, normal tracking and an on-route floor position allow quiet correction when continuation is enabled; otherwise full loss recovery is required. |
runProgressGraceMeters |
0.1 | Small forward progress margin applied after a completed run. |
postRunGraceSeconds |
15 | Post-run grace period for lateral drift handling. |
postRunLateralMeters |
6 | Maximum lateral drift allowed by the post-run grace period. |
landingHorizontalMeters |
10 | Horizontal landing proximity used by landing-aware correction. |
landingVerticalMeters |
4 | Vertical landing proximity used by landing-aware correction. |
alternateDoorMeters |
2.5 | Distance from the planned elevator exit that identifies a different door. |
outsideElevatorMeters |
6 | Elevator-group clearance used by the outside-elevator eligibility helper. |
altitudeHistorySeconds |
20 | Relative altitude history retained for detecting an upcoming climb. |
rideMinimumClimbMeters |
1 | Minimum climb for a meaningful barometer progress ratio. |
rideFinishMarginMeters |
1 | Remaining climb margin that permits barometer completion. |
rideSettledShare |
0.6 | Legacy compatibility field; no longer ends a run early in 0.6.9. |
rideSettledSeconds |
3 | Legacy compatibility field; no longer used for run completion in 0.6.9. |
rideSettledRangeMeters |
0.3 | Legacy compatibility field; no longer used for run completion in 0.6.9. |
rideHistorySeconds |
5 | Recent relative-altitude sample history used during a ride. |
rideNearShare |
0.8 | Barometer progress share that permits an early exit correction. |
rideUsualSpeedMetersPerSecond |
0.45 | Typical flat run speed used by the near-end time signal. |
rideSlowSpeedMetersPerSecond |
0.35 | Slow flat run speed used by the completion time fallback. |
rideTimeSlackSeconds |
10 | Extra time added to the slow-speed completion estimate. |
rideNearLeadSeconds |
5 | Lead time for the near-end time signal. |
climbingWindowSeconds |
4 | Time window used to detect an upcoming climb. |
climbingWindowToleranceSeconds |
0.5 | Tolerance around the climb detection window. |
climbingRateMetersPerSecond |
0.12 | Minimum relative climb rate in the mapped direction. |
cameraExitRadiusMeters |
15 | Outer radius in which camera-based run completion is considered. |
cameraExitHorizontalMeters |
2 | Legacy compatibility field; 0.6.9 uses floor-height and outer-radius checks. |
cameraExitVerticalMeters |
1.5 | Legacy compatibility field; 0.6.9 uses cameraExitFloorMarginMeters. |
cameraExitHeightMarginMeters |
0.7 | Legacy compatibility field; 0.6.9 uses cameraExitFloorMarginMeters. |
cameraExitMinimumClimbMeters |
2 | Minimum mapped climb for camera height-settling completion. |
cameraExitSettledSeconds |
2 | Camera height-settling window. |
cameraExitHistoryPaddingSeconds |
1 | Extra camera sample history around the settling window. |
cameraExitSettledShare |
0.7 | Legacy compatibility field; 0.6.9 uses cameraExitFloorSettledShare. |
cameraExitSettledRangeMeters |
0.25 | Maximum camera height range when settled. |
arrivalMeters |
2 | Standard destination arrival distance; the distance must be strictly below this value. |
floorEntryMeters |
2 | Horizontal approach distance to a floor transition; strictly below this value. |
floorEntryVerticalMeters |
3 | Maximum absolute height difference for floor entry; strictly below this value. |
turnMinimumDegrees |
70 | Minimum heading change classified as a turn. |
bendMinimumDegrees |
35 | Minimum heading change classified as an open bend. |
turnLeadMeters |
1.5 | Approach distance for the standard turn instruction. |
scanOnNewTrip |
true | A new trip scans from scratch. On iOS/Android since 0.6.8, false reuses trusted localization without a confirming request and resumes on the next normally tracked frame. Missing/untrusted localization still scans. A nullable per-tour localization override takes precedence. WebXR retains confirming-fix behavior when false. |
cameraHeightMeters |
1.3 | Fallback phone height above the route floor, in metres. |
cameraHeightMinimumMeters |
1 | Minimum measured phone height. |
cameraHeightMaximumMeters |
1.7 | Maximum measured phone height. |
cameraExitFloorMarginMeters |
0.3 | Exit-floor tolerance for camera completion. |
cameraExitFloorSettledShare |
0.9 | Minimum climb share before settled floor height can end a run. |
rideMaximumRateMetersPerSecond |
1 | Maximum accepted barometer change rate; faster readings are ignored. |
runProgressMeters |
3 | Required route progress beyond the run exit. |
runProgressHoldSeconds |
1 | Time the progress condition must remain satisfied. |
runProgressSpeedMetersPerSecond |
1.2 | Earliest progress completion is run length divided by this speed. |
continueGuidanceDuringRunExitCorrection |
true | Normal tracking and an on-route floor position allow continued guidance with quiet run-exit correction, including scan timeout. False requires full-scan recovery. Lost tracking or off-route position still requires a scan. |
Run completion in 0.6.9
The shared Q20 policy handles stairs and escalators: subtract measured phone height before comparing the camera with the exit floor, ignore abrupt pressure jumps, and suppress residual barometer movement from starting the next flight during landing grace. Without a reliable barometer, sustained route progress beyond the exit can finish the run. A time fallback remains available. New-trip resets clear measured height; reroutes retain it. Settings above use Nevo’s field-tested defaults.
Starting a trip
Every trip start follows scanOnNewTrip:
| Platform | Standard route | Custom presentation |
|---|---|---|
| iOS | navigationRecovery.start(to:) |
navigationRecovery.start() |
| Android | startTo(...) |
navigationRecovery.start() |
| WebXR | navigation.start() |
VPSNavigationRecovery.start() |
Call the custom start() at the beginning of each trip instead of session.rescan(). Before 0.5.4, native starts always scanned and WebXR navigation.start() kept the previous fix. With the default, all three scan. To keep a fix between trips, for example when a kiosk starts trips back to back in the same spot, configure the session with scanOnNewTrip: false:
let policy = try VPSNavigationSettings(scanOnNewTrip: false)
val policy = VPSNavigationSettings(scanOnNewTrip = false)
const session = new VPSSession({ serverURL, apiKey, navigationSettings: { scanOnNewTrip: false } });
Navigation policy versus localization settings
Navigation settings control when the SDK corrects, retains, scans or requests another route. They do not replace localization settings from the current tour.
Continue passing supported tour arSettings dynamically into localization: confidence threshold, scan/background scheduling, position-hint radius, search settings and explicit floor bands. Do not hardcode tour confidence or hint radius into navigation policy. A first accepted fix and a later normally tracked camera frame are still required before guidance resumes; increasing a navigation timeout does not bypass that gate.
Upgrade from 0.5.1
Remove assignments to fieldManaged, automaticallyBoundsProgress and automaticallyCorrectsDeviation. SDK 0.5.2 has one policy rather than field/generic modes. Use the settings type for deliberate future overrides.
Custom presentations must share the session's coordinator and request epochs. Install logical route metadata once; use renderer-only path updates for redraws. Consume SDK actions to update UI and perform transport, without starting a second recovery timer or executing the same localization action twice.
For WebXR, legacy navigation style fields such as arrivalDistance, floorChangeDistance and deviationDistance do not control policy in 0.5.2. Use arrivalMeters, floorEntryMeters and offRouteMeters in navigation settings. Rendering style remains separate.
Standard navigation ends recovery automatically at arrival. Custom WebXR presentations call VPSNavigationRecovery.complete() when arrival is confirmed, then start() for the next trip. A route drawing retained by the arrival screen must not restart scan/retry policy.
UI, audio recordings, accessibility and authenticated route services stay app-owned. Field tests and deterministic replay validate the default policy; simulator/browser tests alone do not establish physical walking or AR alignment.

