From 8c926723c314e9035eca241b597b88acb9d9cd9f Mon Sep 17 00:00:00 2001 From: Jacob Fielding Date: Mon, 10 Feb 2025 20:58:34 -0800 Subject: [PATCH 1/7] feat: separate waypoint logic --- .../src/navigation_controller/mod.rs | 61 ++++++++++++------- .../src/navigation_controller/models.rs | 12 ++++ .../ferrostar/tests/navigation_controller.rs | 5 +- 3 files changed, 54 insertions(+), 24 deletions(-) diff --git a/common/ferrostar/src/navigation_controller/mod.rs b/common/ferrostar/src/navigation_controller/mod.rs index eee71230..5d439f9d 100644 --- a/common/ferrostar/src/navigation_controller/mod.rs +++ b/common/ferrostar/src/navigation_controller/mod.rs @@ -16,7 +16,7 @@ use geo::{ algorithm::{Distance, Haversine}, geometry::{LineString, Point}, }; -use models::{NavigationControllerConfig, StepAdvanceStatus, TripState}; +use models::{NavigationControllerConfig, StepAdvanceStatus, TripState, WaypointAdvanceMode}; use std::clone::Clone; #[cfg(feature = "wasm-bindgen")] @@ -120,27 +120,6 @@ impl NavigationController { let mut remaining_steps = remaining_steps.clone(); remaining_steps.remove(0); - // Update remaining waypoints - let should_advance_waypoint = if let Some(waypoint) = - remaining_waypoints.first() - { - let current_location: Point = snapped_user_location.coordinates.into(); - let next_waypoint: Point = waypoint.coordinate.into(); - // TODO: This is just a hard-coded threshold for the time being. - // More sophisticated behavior will take some time and use cases, so punting on this for now. - Haversine::distance(current_location, next_waypoint) < 100.0 - } else { - false - }; - - let remaining_waypoints = if should_advance_waypoint { - let mut remaining_waypoints = remaining_waypoints.clone(); - remaining_waypoints.remove(0); - remaining_waypoints - } else { - remaining_waypoints.clone() - }; - let progress = calculate_trip_progress( &(*snapped_user_location).into(), &linestring, @@ -160,7 +139,7 @@ impl NavigationController { current_step_geometry_index: *current_step_geometry_index, snapped_user_location: *snapped_user_location, remaining_steps, - remaining_waypoints, + remaining_waypoints: remaining_waypoints.clone(), progress, // NOTE: We *can't* run deviation calculations in this method, // as it requires a non-snapped user location. @@ -215,6 +194,16 @@ impl NavigationController { ¤t_step_linestring, remaining_steps, ); + + // Trim the remaining waypoints if we should advance. + let remaining_waypoints = if self.should_advance_waypoint(state) { + let mut remaining_waypoints = remaining_waypoints.clone(); + remaining_waypoints.remove(0); + remaining_waypoints + } else { + remaining_waypoints.clone() + }; + let intermediate_state = TripState::Navigating { current_step_geometry_index, snapped_user_location, @@ -336,6 +325,31 @@ impl NavigationController { (current_step_geometry_index, snapped_with_course) } + + /// Determines if the navigation controller should advance to the next waypoint. + fn should_advance_waypoint(&self, state: &TripState) -> bool { + match state { + TripState::Navigating { + snapped_user_location, + ref remaining_waypoints, + .. + } => { + // Update remaining waypoints + if let Some(waypoint) = remaining_waypoints.first() { + let current_location: Point = snapped_user_location.coordinates.into(); + let next_waypoint: Point = waypoint.coordinate.into(); + match self.config.waypoint_advance { + WaypointAdvanceMode::WaypointWithinRange(range) => { + Haversine::distance(current_location, next_waypoint) < range + } + } + } else { + false + } + } + _ => false, + } + } } /// JavaScript wrapper for `NavigationController`. @@ -410,6 +424,7 @@ mod tests { let controller = NavigationController::new( route, NavigationControllerConfig { + waypoint_advance: WaypointAdvanceMode::WaypointWithinRange(100.0), // NOTE: We will use a few varieties here via parameterized testing, // but the point of this test is *not* testing the thresholds. step_advance, diff --git a/common/ferrostar/src/navigation_controller/models.rs b/common/ferrostar/src/navigation_controller/models.rs index 9fd73a40..798d0935 100644 --- a/common/ferrostar/src/navigation_controller/models.rs +++ b/common/ferrostar/src/navigation_controller/models.rs @@ -169,12 +169,24 @@ pub enum SpecialAdvanceConditions { MinimumDistanceFromCurrentStepLine(u16), } +// Condition to advance the remaining waypoints. +#[derive(Debug, Copy, Clone)] +#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))] +#[cfg_attr(feature = "wasm-bindgen", derive(Deserialize, Tsify))] +#[cfg_attr(feature = "wasm-bindgen", tsify(from_wasm_abi))] +pub enum WaypointAdvanceMode { + /// Advance when the waypoint is within a certain range of meters from the user's location. + WaypointWithinRange(f64), +} + #[derive(Clone)] #[cfg_attr(feature = "uniffi", derive(uniffi::Record))] #[cfg_attr(feature = "wasm-bindgen", derive(Deserialize, Tsify))] #[cfg_attr(feature = "wasm-bindgen", serde(rename_all = "camelCase"))] #[cfg_attr(feature = "wasm-bindgen", tsify(from_wasm_abi))] pub struct NavigationControllerConfig { + /// Configures when navigation advances to next waypoint in the route. + pub waypoint_advance: WaypointAdvanceMode, /// Configures when navigation advances to the next step in the route. pub step_advance: StepAdvanceMode, /// Configures when the user is deemed to be off course. diff --git a/common/ferrostar/tests/navigation_controller.rs b/common/ferrostar/tests/navigation_controller.rs index 20fdb7b6..ed83cccf 100644 --- a/common/ferrostar/tests/navigation_controller.rs +++ b/common/ferrostar/tests/navigation_controller.rs @@ -3,7 +3,7 @@ extern crate ferrostar; use ferrostar::deviation_detection::RouteDeviationTracking; use ferrostar::models::{Route, UserLocation}; use ferrostar::navigation_controller::models::{ - CourseFiltering, NavigationControllerConfig, StepAdvanceMode, TripState, + CourseFiltering, NavigationControllerConfig, StepAdvanceMode, TripState, WaypointAdvanceMode, }; use ferrostar::navigation_controller::NavigationController; use ferrostar::routing_adapters::osrm::OsrmResponseParser; @@ -44,6 +44,7 @@ fn same_location_results_in_identical_state() { let controller = NavigationController::new( route, NavigationControllerConfig { + waypoint_advance: WaypointAdvanceMode::WaypointWithinRange(100.0), step_advance: StepAdvanceMode::Manual, route_deviation_tracking: RouteDeviationTracking::None, snapped_location_course_filtering: CourseFiltering::Raw, @@ -81,6 +82,7 @@ fn simple_route_state_machine_manual_advance() { let controller = NavigationController::new( route, NavigationControllerConfig { + waypoint_advance: WaypointAdvanceMode::WaypointWithinRange(100.0), step_advance: StepAdvanceMode::Manual, route_deviation_tracking: RouteDeviationTracking::None, snapped_location_course_filtering: CourseFiltering::Raw, @@ -152,6 +154,7 @@ fn simple_route_state_machine_advances_with_location_change() { let controller = NavigationController::new( route, NavigationControllerConfig { + waypoint_advance: WaypointAdvanceMode::WaypointWithinRange(100.0), // NOTE: We will use an exact location to trigger the update; // this is not testing the thresholds. step_advance: StepAdvanceMode::DistanceToEndOfStep { From e69501e4173c2c277de15bcbf9fb0377e8f6e371 Mon Sep 17 00:00:00 2001 From: Jacob Fielding Date: Sat, 15 Feb 2025 21:05:32 -0800 Subject: [PATCH 2/7] feat: separate advance waypoint logic --- .../com/stadiamaps/ferrostar/AppModule.kt | 2 + android/gradle/libs.versions.toml | 4 +- apple/DemoApp/Demo/AppEnvironment.swift | 1 + apple/DemoApp/Demo/NavigationDelegate.swift | 1 + .../FerrostarCore/Models/ModelWrappers.swift | 4 +- apple/Sources/UniFFI/ferrostar.swift | 73 +++++++++++++++++++ .../src/navigation_controller/mod.rs | 6 +- ...oller__tests__extended_exact_distance.snap | 69 +++--------------- ...__tests__extended_relative_linestring.snap | 69 +++--------------- ...sts__self_intersecting_exact_distance.snap | 57 +++------------ ...self_intersecting_relative_linestring.snap | 57 +++------------ ...relative_linestring_min_line_distance.snap | 57 +++------------ guide/src/general-customization.md | 11 +++ 13 files changed, 149 insertions(+), 262 deletions(-) diff --git a/android/demo-app/src/main/java/com/stadiamaps/ferrostar/AppModule.kt b/android/demo-app/src/main/java/com/stadiamaps/ferrostar/AppModule.kt index 1bb8ba4f..a4c5403a 100644 --- a/android/demo-app/src/main/java/com/stadiamaps/ferrostar/AppModule.kt +++ b/android/demo-app/src/main/java/com/stadiamaps/ferrostar/AppModule.kt @@ -20,6 +20,7 @@ import uniffi.ferrostar.NavigationControllerConfig import uniffi.ferrostar.RouteDeviationTracking import uniffi.ferrostar.SpecialAdvanceConditions import uniffi.ferrostar.StepAdvanceMode +import uniffi.ferrostar.WaypointAdvanceMode /** * A basic sample of a dependency injection module for the demo app. This is only used to @@ -86,6 +87,7 @@ object AppModule { foregroundServiceManager = foregroundServiceManager, navigationControllerConfig = NavigationControllerConfig( + WaypointAdvanceMode.WaypointWithinRange(100.0), StepAdvanceMode.RelativeLineStringDistance( minimumHorizontalAccuracy = 25U, specialAdvanceConditions = diff --git a/android/gradle/libs.versions.toml b/android/gradle/libs.versions.toml index f3f42554..b6ff2405 100644 --- a/android/gradle/libs.versions.toml +++ b/android/gradle/libs.versions.toml @@ -11,14 +11,14 @@ kotlinx-coroutines = "1.10.1" kotlinx-datetime = "0.6.1" androidx-appcompat = "1.7.0" androidx-activity-compose = "1.10.0" -compose = "2024.12.01" +compose = "2025.02.00" okhttp = "4.12.0" moshi = "1.15.1" maplibre-compose = "0.4.0" playServicesLocation = "21.3.0" junit = "4.13.2" junitVersion = "1.2.1" -junitCompose = "1.7.6" +junitCompose = "1.7.8" espressoCore = "3.6.1" okhttp-mock = "2.0.0" mockk = "1.13.16" diff --git a/apple/DemoApp/Demo/AppEnvironment.swift b/apple/DemoApp/Demo/AppEnvironment.swift index 628f8574..fa9ebc80 100644 --- a/apple/DemoApp/Demo/AppEnvironment.swift +++ b/apple/DemoApp/Demo/AppEnvironment.swift @@ -34,6 +34,7 @@ class AppEnvironment: ObservableObject { // Configure the navigation session. // You have a lot of flexibility here based on your use case. let config = SwiftNavigationControllerConfig( + waypointAdvance: .waypointWithinRange(100.0), stepAdvance: .relativeLineStringDistance( minimumHorizontalAccuracy: 32, specialAdvanceConditions: .minimumDistanceFromCurrentStepLine(10) diff --git a/apple/DemoApp/Demo/NavigationDelegate.swift b/apple/DemoApp/Demo/NavigationDelegate.swift index 6ca489a6..0f80fd3c 100644 --- a/apple/DemoApp/Demo/NavigationDelegate.swift +++ b/apple/DemoApp/Demo/NavigationDelegate.swift @@ -24,6 +24,7 @@ class NavigationDelegate: FerrostarCoreDelegate { // Most implementations will probably reuse existing configs (the default implementation does), // but we provide devs with flexibility here. let config = SwiftNavigationControllerConfig( + waypointAdvance: .waypointWithinRange(100.0), stepAdvance: .relativeLineStringDistance(minimumHorizontalAccuracy: 32, specialAdvanceConditions: .minimumDistanceFromCurrentStepLine( 10 diff --git a/apple/Sources/FerrostarCore/Models/ModelWrappers.swift b/apple/Sources/FerrostarCore/Models/ModelWrappers.swift index 6a3fba83..437ea7b0 100644 --- a/apple/Sources/FerrostarCore/Models/ModelWrappers.swift +++ b/apple/Sources/FerrostarCore/Models/ModelWrappers.swift @@ -42,11 +42,13 @@ public enum SwiftRouteDeviationTracking { /// A Swift wrapper around `UniFFI.NavigationControllerConfig`. public struct SwiftNavigationControllerConfig { - public init(stepAdvance: StepAdvanceMode, + public init(waypointAdvance: WaypointAdvanceMode, + stepAdvance: StepAdvanceMode, routeDeviationTracking: SwiftRouteDeviationTracking, snappedLocationCourseFiltering: CourseFiltering) { ffiValue = FerrostarCoreFFI.NavigationControllerConfig( + waypointAdvance: waypointAdvance, stepAdvance: stepAdvance, routeDeviationTracking: routeDeviationTracking.ffiValue, snappedLocationCourseFiltering: snappedLocationCourseFiltering diff --git a/apple/Sources/UniFFI/ferrostar.swift b/apple/Sources/UniFFI/ferrostar.swift index 5f0c1ac9..308a12ca 100644 --- a/apple/Sources/UniFFI/ferrostar.swift +++ b/apple/Sources/UniFFI/ferrostar.swift @@ -2525,6 +2525,10 @@ public func FfiConverterTypeLocationSimulationState_lower(_ value: LocationSimul public struct NavigationControllerConfig { + /** + * Configures when navigation advances to next waypoint in the route. + */ + public var waypointAdvance: WaypointAdvanceMode /** * Configures when navigation advances to the next step in the route. */ @@ -2544,6 +2548,9 @@ public struct NavigationControllerConfig { // Default memberwise initializers are never public by default, so we // declare one manually. public init( + /** + * Configures when navigation advances to next waypoint in the route. + */waypointAdvance: WaypointAdvanceMode, /** * Configures when navigation advances to the next step in the route. */stepAdvance: StepAdvanceMode, @@ -2556,6 +2563,7 @@ public struct NavigationControllerConfig { /** * Configures how the heading component of the snapped location is reported in [`TripState`]. */snappedLocationCourseFiltering: CourseFiltering) { + self.waypointAdvance = waypointAdvance self.stepAdvance = stepAdvance self.routeDeviationTracking = routeDeviationTracking self.snappedLocationCourseFiltering = snappedLocationCourseFiltering @@ -2571,6 +2579,7 @@ public struct FfiConverterTypeNavigationControllerConfig: FfiConverterRustBuffer public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> NavigationControllerConfig { return try NavigationControllerConfig( + waypointAdvance: FfiConverterTypeWaypointAdvanceMode.read(from: &buf), stepAdvance: FfiConverterTypeStepAdvanceMode.read(from: &buf), routeDeviationTracking: FfiConverterTypeRouteDeviationTracking.read(from: &buf), snappedLocationCourseFiltering: FfiConverterTypeCourseFiltering.read(from: &buf) @@ -2578,6 +2587,7 @@ public struct FfiConverterTypeNavigationControllerConfig: FfiConverterRustBuffer } public static func write(_ value: NavigationControllerConfig, into buf: inout [UInt8]) { + FfiConverterTypeWaypointAdvanceMode.write(value.waypointAdvance, into: &buf) FfiConverterTypeStepAdvanceMode.write(value.stepAdvance, into: &buf) FfiConverterTypeRouteDeviationTracking.write(value.routeDeviationTracking, into: &buf) FfiConverterTypeCourseFiltering.write(value.snappedLocationCourseFiltering, into: &buf) @@ -5384,6 +5394,69 @@ extension TripState: Equatable, Hashable {} +// Note that we don't yet support `indirect` for enums. +// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. + +public enum WaypointAdvanceMode { + + /** + * Advance when the waypoint is within a certain range of meters from the user's location. + */ + case waypointWithinRange(Double + ) +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public struct FfiConverterTypeWaypointAdvanceMode: FfiConverterRustBuffer { + typealias SwiftType = WaypointAdvanceMode + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> WaypointAdvanceMode { + let variant: Int32 = try readInt(&buf) + switch variant { + + case 1: return .waypointWithinRange(try FfiConverterDouble.read(from: &buf) + ) + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: WaypointAdvanceMode, into buf: inout [UInt8]) { + switch value { + + + case let .waypointWithinRange(v1): + writeInt(&buf, Int32(1)) + FfiConverterDouble.write(v1, into: &buf) + + } + } +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeWaypointAdvanceMode_lift(_ buf: RustBuffer) throws -> WaypointAdvanceMode { + return try FfiConverterTypeWaypointAdvanceMode.lift(buf) +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeWaypointAdvanceMode_lower(_ value: WaypointAdvanceMode) -> RustBuffer { + return FfiConverterTypeWaypointAdvanceMode.lower(value) +} + + + +extension WaypointAdvanceMode: Equatable, Hashable {} + + + // Note that we don't yet support `indirect` for enums. // See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. /** diff --git a/common/ferrostar/src/navigation_controller/mod.rs b/common/ferrostar/src/navigation_controller/mod.rs index 5d439f9d..26177d4a 100644 --- a/common/ferrostar/src/navigation_controller/mod.rs +++ b/common/ferrostar/src/navigation_controller/mod.rs @@ -335,7 +335,7 @@ impl NavigationController { .. } => { // Update remaining waypoints - if let Some(waypoint) = remaining_waypoints.first() { + remaining_waypoints.first().is_some_and(|waypoint| { let current_location: Point = snapped_user_location.coordinates.into(); let next_waypoint: Point = waypoint.coordinate.into(); match self.config.waypoint_advance { @@ -343,9 +343,7 @@ impl NavigationController { Haversine::distance(current_location, next_waypoint) < range } } - } else { - false - } + }) } _ => false, } diff --git a/common/ferrostar/src/navigation_controller/snapshots/ferrostar__navigation_controller__tests__extended_exact_distance.snap b/common/ferrostar/src/navigation_controller/snapshots/ferrostar__navigation_controller__tests__extended_exact_distance.snap index 881cdb48..5bc623d7 100644 --- a/common/ferrostar/src/navigation_controller/snapshots/ferrostar__navigation_controller__tests__extended_exact_distance.snap +++ b/common/ferrostar/src/navigation_controller/snapshots/ferrostar__navigation_controller__tests__extended_exact_distance.snap @@ -1,7 +1,6 @@ --- source: ferrostar/src/navigation_controller/mod.rs -expression: "test_full_route_state_snapshot(get_extended_route(),\nStepAdvanceMode::DistanceToEndOfStep\n{ distance: 0, minimum_horizontal_accuracy: 0, })" -snapshot_kind: text +expression: "test_full_route_state_snapshot(get_extended_route(),\n StepAdvanceMode::DistanceToEndOfStep {\n distance: 0,\n minimum_horizontal_accuracy: 0,\n })" --- - Navigating: current_step_geometry_index: 0 @@ -66824,11 +66823,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 40.777985 - lng: -74.040048 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 85.66591581649834 distanceRemaining: 85.66591581649834 @@ -66909,11 +66904,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 40.777985 - lng: -74.040048 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 76.85045894609027 distanceRemaining: 76.85045894609027 @@ -66994,11 +66985,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 40.777985 - lng: -74.040048 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 68.06307191980636 distanceRemaining: 68.06307191980636 @@ -67079,11 +67066,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 40.777985 - lng: -74.040048 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 59.33350267279684 distanceRemaining: 59.33350267279684 @@ -67164,11 +67147,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 40.777985 - lng: -74.040048 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 50.460228023936 distanceRemaining: 50.460228023936 @@ -67249,11 +67228,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 40.777985 - lng: -74.040048 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 41.73065877610483 distanceRemaining: 41.73065877610483 @@ -67334,11 +67309,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 40.777985 - lng: -74.040048 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 33.83685913763435 distanceRemaining: 33.83685913763435 @@ -67419,11 +67390,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 40.777985 - lng: -74.040048 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 25.91526920319194 distanceRemaining: 25.91526920319194 @@ -67504,11 +67471,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 40.777985 - lng: -74.040048 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 18.02146956389788 distanceRemaining: 18.02146956389788 @@ -67589,11 +67552,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 40.777985 - lng: -74.040048 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 10.127669926036617 distanceRemaining: 10.127669926036617 @@ -67674,11 +67633,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 40.777985 - lng: -74.040048 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 5.050100380126253 distanceRemaining: 5.050100380126253 diff --git a/common/ferrostar/src/navigation_controller/snapshots/ferrostar__navigation_controller__tests__extended_relative_linestring.snap b/common/ferrostar/src/navigation_controller/snapshots/ferrostar__navigation_controller__tests__extended_relative_linestring.snap index 089d2803..2087b868 100644 --- a/common/ferrostar/src/navigation_controller/snapshots/ferrostar__navigation_controller__tests__extended_relative_linestring.snap +++ b/common/ferrostar/src/navigation_controller/snapshots/ferrostar__navigation_controller__tests__extended_relative_linestring.snap @@ -1,7 +1,6 @@ --- source: ferrostar/src/navigation_controller/mod.rs -expression: "test_full_route_state_snapshot(get_extended_route(),\nStepAdvanceMode::RelativeLineStringDistance\n{ minimum_horizontal_accuracy: 0, special_advance_conditions: None, })" -snapshot_kind: text +expression: "test_full_route_state_snapshot(get_extended_route(),\n StepAdvanceMode::RelativeLineStringDistance {\n minimum_horizontal_accuracy: 0,\n special_advance_conditions: None,\n })" --- - Navigating: current_step_geometry_index: 0 @@ -66824,11 +66823,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 40.777985 - lng: -74.040048 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 85.66591581649834 distanceRemaining: 85.66591581649834 @@ -66909,11 +66904,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 40.777985 - lng: -74.040048 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 76.85045894609027 distanceRemaining: 76.85045894609027 @@ -66994,11 +66985,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 40.777985 - lng: -74.040048 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 68.06307191980636 distanceRemaining: 68.06307191980636 @@ -67079,11 +67066,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 40.777985 - lng: -74.040048 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 59.33350267279684 distanceRemaining: 59.33350267279684 @@ -67164,11 +67147,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 40.777985 - lng: -74.040048 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 50.460228023936 distanceRemaining: 50.460228023936 @@ -67249,11 +67228,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 40.777985 - lng: -74.040048 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 41.73065877610483 distanceRemaining: 41.73065877610483 @@ -67334,11 +67309,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 40.777985 - lng: -74.040048 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 33.83685913763435 distanceRemaining: 33.83685913763435 @@ -67419,11 +67390,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 40.777985 - lng: -74.040048 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 25.91526920319194 distanceRemaining: 25.91526920319194 @@ -67504,11 +67471,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 40.777985 - lng: -74.040048 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 18.02146956389788 distanceRemaining: 18.02146956389788 @@ -67589,11 +67552,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 40.777985 - lng: -74.040048 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 10.127669926036617 distanceRemaining: 10.127669926036617 @@ -67674,11 +67633,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 40.777985 - lng: -74.040048 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 5.050100380126253 distanceRemaining: 5.050100380126253 diff --git a/common/ferrostar/src/navigation_controller/snapshots/ferrostar__navigation_controller__tests__self_intersecting_exact_distance.snap b/common/ferrostar/src/navigation_controller/snapshots/ferrostar__navigation_controller__tests__self_intersecting_exact_distance.snap index cd65696a..d350b2b9 100644 --- a/common/ferrostar/src/navigation_controller/snapshots/ferrostar__navigation_controller__tests__self_intersecting_exact_distance.snap +++ b/common/ferrostar/src/navigation_controller/snapshots/ferrostar__navigation_controller__tests__self_intersecting_exact_distance.snap @@ -1,7 +1,6 @@ --- source: ferrostar/src/navigation_controller/mod.rs -expression: "test_full_route_state_snapshot(get_self_intersecting_route(),\nStepAdvanceMode::DistanceToEndOfStep\n{ distance: 0, minimum_horizontal_accuracy: 0, })" -snapshot_kind: text +expression: "test_full_route_state_snapshot(get_self_intersecting_route(),\n StepAdvanceMode::DistanceToEndOfStep {\n distance: 0,\n minimum_horizontal_accuracy: 0,\n })" --- - Navigating: current_step_geometry_index: 0 @@ -13630,11 +13629,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 82.96117352281715 distanceRemaining: 82.96117352281715 @@ -13713,11 +13708,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 74.14908645333895 distanceRemaining: 74.14908645333895 @@ -13796,11 +13787,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 65.33239360462073 distanceRemaining: 65.33239360462073 @@ -13879,11 +13866,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 56.377924515734776 distanceRemaining: 56.377924515734776 @@ -13962,11 +13945,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 47.5612316665073 distanceRemaining: 47.5612316665073 @@ -14045,11 +14024,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 38.64260412903741 distanceRemaining: 38.64260412903741 @@ -14128,11 +14103,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 29.024470298729454 distanceRemaining: 29.024470298729454 @@ -14211,11 +14182,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 19.3038707696021 distanceRemaining: 19.3038707696021 @@ -14294,11 +14261,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 9.720599529127298 distanceRemaining: 9.720599529127298 diff --git a/common/ferrostar/src/navigation_controller/snapshots/ferrostar__navigation_controller__tests__self_intersecting_relative_linestring.snap b/common/ferrostar/src/navigation_controller/snapshots/ferrostar__navigation_controller__tests__self_intersecting_relative_linestring.snap index 12c1b27e..b169339e 100644 --- a/common/ferrostar/src/navigation_controller/snapshots/ferrostar__navigation_controller__tests__self_intersecting_relative_linestring.snap +++ b/common/ferrostar/src/navigation_controller/snapshots/ferrostar__navigation_controller__tests__self_intersecting_relative_linestring.snap @@ -1,7 +1,6 @@ --- source: ferrostar/src/navigation_controller/mod.rs -expression: "test_full_route_state_snapshot(get_self_intersecting_route(),\nStepAdvanceMode::RelativeLineStringDistance\n{ minimum_horizontal_accuracy: 0, special_advance_conditions: None, })" -snapshot_kind: text +expression: "test_full_route_state_snapshot(get_self_intersecting_route(),\n StepAdvanceMode::RelativeLineStringDistance {\n minimum_horizontal_accuracy: 0,\n special_advance_conditions: None,\n })" --- - Navigating: current_step_geometry_index: 0 @@ -13630,11 +13629,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 82.96117352281715 distanceRemaining: 82.96117352281715 @@ -13713,11 +13708,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 74.14908645333895 distanceRemaining: 74.14908645333895 @@ -13796,11 +13787,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 65.33239360462073 distanceRemaining: 65.33239360462073 @@ -13879,11 +13866,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 56.377924515734776 distanceRemaining: 56.377924515734776 @@ -13962,11 +13945,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 47.5612316665073 distanceRemaining: 47.5612316665073 @@ -14045,11 +14024,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 38.64260412903741 distanceRemaining: 38.64260412903741 @@ -14128,11 +14103,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 29.024470298729454 distanceRemaining: 29.024470298729454 @@ -14211,11 +14182,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 19.3038707696021 distanceRemaining: 19.3038707696021 @@ -14294,11 +14261,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 9.720599529127298 distanceRemaining: 9.720599529127298 diff --git a/common/ferrostar/src/navigation_controller/snapshots/ferrostar__navigation_controller__tests__self_intersecting_relative_linestring_min_line_distance.snap b/common/ferrostar/src/navigation_controller/snapshots/ferrostar__navigation_controller__tests__self_intersecting_relative_linestring_min_line_distance.snap index 7a73ed95..337e235a 100644 --- a/common/ferrostar/src/navigation_controller/snapshots/ferrostar__navigation_controller__tests__self_intersecting_relative_linestring_min_line_distance.snap +++ b/common/ferrostar/src/navigation_controller/snapshots/ferrostar__navigation_controller__tests__self_intersecting_relative_linestring_min_line_distance.snap @@ -1,7 +1,6 @@ --- source: ferrostar/src/navigation_controller/mod.rs -expression: "test_full_route_state_snapshot(get_self_intersecting_route(),\nStepAdvanceMode::RelativeLineStringDistance\n{\n minimum_horizontal_accuracy: 0, special_advance_conditions:\n Some(SpecialAdvanceConditions::MinimumDistanceFromCurrentStepLine(10)),\n})" -snapshot_kind: text +expression: "test_full_route_state_snapshot(get_self_intersecting_route(),\n StepAdvanceMode::RelativeLineStringDistance {\n minimum_horizontal_accuracy: 0,\n special_advance_conditions: Some(SpecialAdvanceConditions::MinimumDistanceFromCurrentStepLine(10)),\n })" --- - Navigating: current_step_geometry_index: 0 @@ -13780,11 +13779,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 82.96117352281715 distanceRemaining: 82.96117352281715 @@ -13863,11 +13858,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 74.14908645333895 distanceRemaining: 74.14908645333895 @@ -13946,11 +13937,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 65.33239360462073 distanceRemaining: 65.33239360462073 @@ -14029,11 +14016,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 56.377924515734776 distanceRemaining: 56.377924515734776 @@ -14112,11 +14095,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 47.5612316665073 distanceRemaining: 47.5612316665073 @@ -14195,11 +14174,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 38.64260412903741 distanceRemaining: 38.64260412903741 @@ -14278,11 +14253,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 29.024470298729454 distanceRemaining: 29.024470298729454 @@ -14361,11 +14332,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 19.3038707696021 distanceRemaining: 19.3038707696021 @@ -14444,11 +14411,7 @@ snapshot_kind: text spoken_instructions: [] annotations: ~ incidents: [] - remaining_waypoints: - - coordinate: - lat: 45.371508 - lng: -122.585901 - kind: Break + remaining_waypoints: [] progress: distanceToNextManeuver: 9.720599529127298 distanceRemaining: 9.720599529127298 diff --git a/guide/src/general-customization.md b/guide/src/general-customization.md index f6869215..97e97544 100644 --- a/guide/src/general-customization.md +++ b/guide/src/general-customization.md @@ -12,6 +12,17 @@ These customizations apply to the [`NavigationController`](https://docs.rs/ferro They are surfaced at the platform layer as an argument to the `startNavigation` method of `FerrostarCore`. +### Waypoint advance + +The waypoint advance is configured by the `WaypointAdvanceMode`. Our original (V0.27.0 and earlier) hardcoded implementation +simply checked if the user was within 100 meters of the waypoint when the step was being advanced. The waypoint advance logic +is separated from step advance to ensure that the user will advance waypoint regardless of step advance conditions. + +To match Ferrostar's original default, use `WaypointAdvanceMode::WaypointWithinRange(100.0)`. + +The waypoint advance mode has access to the entire TripState anytime the user location is updated. As a result more complex +implementations would be welcome additions to the library. + #### Step advance The step advance mode controls when navigation advances to the next step in the route. From e1add046294d8de596919502172bc2e520000364 Mon Sep 17 00:00:00 2001 From: Jacob Fielding Date: Mon, 17 Feb 2025 19:00:36 -0800 Subject: [PATCH 3/7] feat: waypoint advance config guide --- .../ferrostar/src/navigation_controller/mod.rs | 2 +- .../src/navigation_controller/models.rs | 18 +++++++++++++++++- guide/src/android-getting-started.md | 1 + .../configuring-the-navigation-controller.md | 4 +++- guide/src/web-getting-started.md | 3 +++ web/index.html | 3 +++ 6 files changed, 28 insertions(+), 3 deletions(-) diff --git a/common/ferrostar/src/navigation_controller/mod.rs b/common/ferrostar/src/navigation_controller/mod.rs index 26177d4a..7a6cee51 100644 --- a/common/ferrostar/src/navigation_controller/mod.rs +++ b/common/ferrostar/src/navigation_controller/mod.rs @@ -195,7 +195,7 @@ impl NavigationController { remaining_steps, ); - // Trim the remaining waypoints if we should advance. + // Trim the remaining waypoints if needed. let remaining_waypoints = if self.should_advance_waypoint(state) { let mut remaining_waypoints = remaining_waypoints.clone(); remaining_waypoints.remove(0); diff --git a/common/ferrostar/src/navigation_controller/models.rs b/common/ferrostar/src/navigation_controller/models.rs index 798d0935..0b8c450c 100644 --- a/common/ferrostar/src/navigation_controller/models.rs +++ b/common/ferrostar/src/navigation_controller/models.rs @@ -169,7 +169,23 @@ pub enum SpecialAdvanceConditions { MinimumDistanceFromCurrentStepLine(u16), } -// Condition to advance the remaining waypoints. +/// 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! #[derive(Debug, Copy, Clone)] #[cfg_attr(feature = "uniffi", derive(uniffi::Enum))] #[cfg_attr(feature = "wasm-bindgen", derive(Deserialize, Tsify))] diff --git a/guide/src/android-getting-started.md b/guide/src/android-getting-started.md index 9421b84e..c41cd666 100644 --- a/guide/src/android-getting-started.md +++ b/guide/src/android-getting-started.md @@ -231,6 +231,7 @@ private val core = foregroundServiceManager = foregroundServiceManager, navigationControllerConfig = NavigationControllerConfig( + WaypointAdvanceMode.WaypointWithinRange(100.0), StepAdvanceMode.RelativeLineStringDistance( minimumHorizontalAccuracy = 25U, specialAdvanceConditions = diff --git a/guide/src/configuring-the-navigation-controller.md b/guide/src/configuring-the-navigation-controller.md index c27183ac..51faac7f 100644 --- a/guide/src/configuring-the-navigation-controller.md +++ b/guide/src/configuring-the-navigation-controller.md @@ -45,6 +45,7 @@ Swift: ```swift let config = SwiftNavigationControllerConfig( + waypointAdvance: .waypointWithinRange(100.0), stepAdvance: .relativeLineStringDistance(minimumHorizontalAccuracy: 16, automaticAdvanceDistance: 16), routeDeviationTracking: .custom(detector: { _, _, _ in // Pretend that the user is always off route @@ -60,6 +61,7 @@ Kotlin: ```kotlin val config = NavigationControllerConfig( + WaypointAdvanceMode.WaypointWithinRange(100.0), stepAdvance = StepAdvanceMode.RelativeLineStringDistance(16U, 16U), routeDeviationTracking = RouteDeviationTracking.Custom( @@ -138,4 +140,4 @@ We envision live traffic, incidents, etc. being used to feed periodic “route revalidation” in the future. The same “alternative route” notification mechanism can be extended (ex: with a reason why the alternative is being supplied) -for this purpose. \ No newline at end of file +for this purpose. diff --git a/guide/src/web-getting-started.md b/guide/src/web-getting-started.md index 58c01e46..650f1298 100644 --- a/guide/src/web-getting-started.md +++ b/guide/src/web-getting-started.md @@ -182,6 +182,9 @@ ferrostar.startNavigation(route, { }, }, snappedLocationCourseFiltering: "Raw", + waypointAdvance: { + WaypointWithinRange: 100, + }, }); ``` diff --git a/web/index.html b/web/index.html index 42228067..6ab6ccc8 100644 --- a/web/index.html +++ b/web/index.html @@ -55,6 +55,9 @@ }, }, snappedLocationCourseFiltering: "Raw", + waypointAdvance: { + WaypointWithinRange: 100, + }, }; async function onload() { From c4ae1b132b759cf2e3210fd100bd1cbac869315d Mon Sep 17 00:00:00 2001 From: Jacob Fielding Date: Mon, 17 Feb 2025 19:04:53 -0800 Subject: [PATCH 4/7] feat: waypoint advance config guide --- apple/Sources/UniFFI/ferrostar.swift | 19 +++++++++++++++++++ common/Cargo.lock | 2 +- common/ferrostar/Cargo.toml | 2 +- .../ferrostar/tests/navigation_controller.rs | 3 +-- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/apple/Sources/UniFFI/ferrostar.swift b/apple/Sources/UniFFI/ferrostar.swift index 308a12ca..5657d5fb 100644 --- a/apple/Sources/UniFFI/ferrostar.swift +++ b/apple/Sources/UniFFI/ferrostar.swift @@ -5396,6 +5396,25 @@ extension TripState: Equatable, Hashable {} // Note that we don't yet support `indirect` for enums. // See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. +/** + * 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! + */ public enum WaypointAdvanceMode { diff --git a/common/Cargo.lock b/common/Cargo.lock index 7e16c69d..a986cbef 100644 --- a/common/Cargo.lock +++ b/common/Cargo.lock @@ -453,7 +453,7 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "ferrostar" -version = "0.27.0" +version = "0.28.0" dependencies = [ "android_logger", "assert-json-diff", diff --git a/common/ferrostar/Cargo.toml b/common/ferrostar/Cargo.toml index ab59d501..f335691a 100644 --- a/common/ferrostar/Cargo.toml +++ b/common/ferrostar/Cargo.toml @@ -2,7 +2,7 @@ lints.workspace = true [package] name = "ferrostar" -version = "0.27.0" +version = "0.28.0" readme = "README.md" description = "The core of modern turn-by-turn navigation." keywords = ["navigation", "routing", "valhalla", "osrm"] diff --git a/common/ferrostar/tests/navigation_controller.rs b/common/ferrostar/tests/navigation_controller.rs index ed83cccf..40c54e6d 100644 --- a/common/ferrostar/tests/navigation_controller.rs +++ b/common/ferrostar/tests/navigation_controller.rs @@ -190,8 +190,7 @@ fn simple_route_state_machine_advances_with_location_change() { }; assert_ne!(remaining_steps, initial_remaining_steps); - // In this case, the final step is the arrival point - assert_eq!(remaining_waypoints.len(), 0); + assert_eq!(remaining_waypoints.len(), 1); assert_eq!(progress.distance_to_next_maneuver, 0f64); assert_eq!(progress.distance_remaining, 0f64); From bf9eb6baf32ae0b36f64d7c5aa9217307299c90b Mon Sep 17 00:00:00 2001 From: Jacob Fielding Date: Mon, 17 Feb 2025 19:15:45 -0800 Subject: [PATCH 5/7] feat: waypoint advance config guide --- apple/Tests/FerrostarCoreTests/FerrostarCoreTests.swift | 7 +++++++ apple/Tests/FerrostarCoreTests/ValhallaCoreTests.swift | 1 + 2 files changed, 8 insertions(+) diff --git a/apple/Tests/FerrostarCoreTests/FerrostarCoreTests.swift b/apple/Tests/FerrostarCoreTests/FerrostarCoreTests.swift index 73b08230..b94bae8e 100644 --- a/apple/Tests/FerrostarCoreTests/FerrostarCoreTests.swift +++ b/apple/Tests/FerrostarCoreTests/FerrostarCoreTests.swift @@ -123,6 +123,7 @@ final class FerrostarCoreTests: XCTestCase { routeAdapter: routeAdapter, locationProvider: SimulatedLocationProvider(), navigationControllerConfig: .init( + waypointAdvance: .waypointWithinRange(100.0), stepAdvance: .manual, routeDeviationTracking: .none, snappedLocationCourseFiltering: .raw @@ -166,6 +167,7 @@ final class FerrostarCoreTests: XCTestCase { routeAdapter: mockPOSTRouteAdapter, locationProvider: SimulatedLocationProvider(), navigationControllerConfig: .init( + waypointAdvance: .waypointWithinRange(100.0), stepAdvance: .manual, routeDeviationTracking: .none, snappedLocationCourseFiltering: .raw @@ -201,6 +203,7 @@ final class FerrostarCoreTests: XCTestCase { routeAdapter: mockGETRouteAdapter, locationProvider: SimulatedLocationProvider(), navigationControllerConfig: .init( + waypointAdvance: .waypointWithinRange(100.0), stepAdvance: .manual, routeDeviationTracking: .none, snappedLocationCourseFiltering: .raw @@ -239,6 +242,7 @@ final class FerrostarCoreTests: XCTestCase { profile: "low_speed_vehicle", locationProvider: SimulatedLocationProvider(), navigationControllerConfig: .init( + waypointAdvance: .waypointWithinRange(100.0), stepAdvance: .manual, routeDeviationTracking: .none, snappedLocationCourseFiltering: .raw @@ -285,6 +289,7 @@ final class FerrostarCoreTests: XCTestCase { customRouteProvider: mockCustomRouteProvider, locationProvider: SimulatedLocationProvider(), navigationControllerConfig: .init( + waypointAdvance: .waypointWithinRange(100.0), stepAdvance: .manual, routeDeviationTracking: .none, snappedLocationCourseFiltering: .raw @@ -331,6 +336,7 @@ final class FerrostarCoreTests: XCTestCase { routeAdapter: mockPOSTRouteAdapter, locationProvider: locationProvider, navigationControllerConfig: .init( + waypointAdvance: .waypointWithinRange(100.0), stepAdvance: .manual, routeDeviationTracking: .none, snappedLocationCourseFiltering: .raw @@ -385,6 +391,7 @@ final class FerrostarCoreTests: XCTestCase { locationProvider.lastLocation = CLLocation(latitude: 0, longitude: 0).userLocation let config = SwiftNavigationControllerConfig( + waypointAdvance: .waypointWithinRange(100.0), stepAdvance: .relativeLineStringDistance( minimumHorizontalAccuracy: 16, specialAdvanceConditions: .advanceAtDistanceFromEnd(16) diff --git a/apple/Tests/FerrostarCoreTests/ValhallaCoreTests.swift b/apple/Tests/FerrostarCoreTests/ValhallaCoreTests.swift index 0700313d..88d92462 100644 --- a/apple/Tests/FerrostarCoreTests/ValhallaCoreTests.swift +++ b/apple/Tests/FerrostarCoreTests/ValhallaCoreTests.swift @@ -20,6 +20,7 @@ final class ValhallaCoreTests: XCTestCase { profile: "auto", locationProvider: SimulatedLocationProvider(), navigationControllerConfig: .init( + waypointAdvance: .waypointWithinRange(100.0), stepAdvance: .manual, routeDeviationTracking: .none, snappedLocationCourseFiltering: .raw From 418afd87f0cdfca7b7a610d4f18dcf1a04538350 Mon Sep 17 00:00:00 2001 From: Jacob Fielding Date: Mon, 17 Feb 2025 19:20:41 -0800 Subject: [PATCH 6/7] feat: waypoint advance config guide --- .../ferrostar/core/FerrostarCoreTest.kt | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/android/core/src/androidTest/java/com/stadiamaps/ferrostar/core/FerrostarCoreTest.kt b/android/core/src/androidTest/java/com/stadiamaps/ferrostar/core/FerrostarCoreTest.kt index a077b75e..7da58f36 100644 --- a/android/core/src/androidTest/java/com/stadiamaps/ferrostar/core/FerrostarCoreTest.kt +++ b/android/core/src/androidTest/java/com/stadiamaps/ferrostar/core/FerrostarCoreTest.kt @@ -37,6 +37,7 @@ import uniffi.ferrostar.UserLocation import uniffi.ferrostar.VisualInstruction import uniffi.ferrostar.VisualInstructionContent import uniffi.ferrostar.Waypoint +import uniffi.ferrostar.WaypointAdvanceMode import uniffi.ferrostar.WaypointKind private val valhallaEndpointUrl = "https://api.stadiamaps.com/navigate/v1" @@ -148,7 +149,10 @@ class FerrostarCoreTest { foregroundServiceManager = MockForegroundNotificationManager(), navigationControllerConfig = NavigationControllerConfig( - StepAdvanceMode.Manual, RouteDeviationTracking.None, CourseFiltering.RAW)) + WaypointAdvanceMode.WaypointWithinRange(100.0), + StepAdvanceMode.Manual, + RouteDeviationTracking.None, + CourseFiltering.RAW)) try { // Tests that the core generates a request and attempts to process it, but throws due to the @@ -196,7 +200,10 @@ class FerrostarCoreTest { foregroundServiceManager = MockForegroundNotificationManager(), navigationControllerConfig = NavigationControllerConfig( - StepAdvanceMode.Manual, RouteDeviationTracking.None, CourseFiltering.RAW)) + WaypointAdvanceMode.WaypointWithinRange(100.0), + StepAdvanceMode.Manual, + RouteDeviationTracking.None, + CourseFiltering.RAW)) val routes = core.getRoutes( initialLocation = @@ -239,7 +246,10 @@ class FerrostarCoreTest { foregroundServiceManager = MockForegroundNotificationManager(), navigationControllerConfig = NavigationControllerConfig( - StepAdvanceMode.Manual, RouteDeviationTracking.None, CourseFiltering.RAW)) + WaypointAdvanceMode.WaypointWithinRange(100.0), + StepAdvanceMode.Manual, + RouteDeviationTracking.None, + CourseFiltering.RAW)) val routes = core.getRoutes( initialLocation = @@ -290,7 +300,10 @@ class FerrostarCoreTest { foregroundServiceManager = MockForegroundNotificationManager(), navigationControllerConfig = NavigationControllerConfig( - StepAdvanceMode.Manual, RouteDeviationTracking.None, CourseFiltering.RAW)) + WaypointAdvanceMode.WaypointWithinRange(100.0), + StepAdvanceMode.Manual, + RouteDeviationTracking.None, + CourseFiltering.RAW)) val routes = core.getRoutes( initialLocation = @@ -361,7 +374,10 @@ class FerrostarCoreTest { foregroundServiceManager = foregroundServiceManager, navigationControllerConfig = NavigationControllerConfig( - StepAdvanceMode.Manual, RouteDeviationTracking.None, CourseFiltering.RAW)) + WaypointAdvanceMode.WaypointWithinRange(100.0), + StepAdvanceMode.Manual, + RouteDeviationTracking.None, + CourseFiltering.RAW)) val deviationHandler = DeviationHandler() core.deviationHandler = deviationHandler @@ -398,6 +414,7 @@ class FerrostarCoreTest { core.startNavigation( routes.first(), NavigationControllerConfig( + WaypointAdvanceMode.WaypointWithinRange(100.0), stepAdvance = StepAdvanceMode.RelativeLineStringDistance( 16U, From 0f14dcbabf5e67db12bdb2a9cd1b190cd9872a2f Mon Sep 17 00:00:00 2001 From: Jacob Fielding Date: Mon, 17 Feb 2025 19:32:37 -0800 Subject: [PATCH 7/7] feat: waypoint advance config guide --- .../com/stadiamaps/ferrostar/core/ValhallaCoreTest.kt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/android/core/src/androidTest/java/com/stadiamaps/ferrostar/core/ValhallaCoreTest.kt b/android/core/src/androidTest/java/com/stadiamaps/ferrostar/core/ValhallaCoreTest.kt index 3a68c8bf..2b744ea8 100644 --- a/android/core/src/androidTest/java/com/stadiamaps/ferrostar/core/ValhallaCoreTest.kt +++ b/android/core/src/androidTest/java/com/stadiamaps/ferrostar/core/ValhallaCoreTest.kt @@ -30,6 +30,7 @@ import uniffi.ferrostar.RouteDeviationTracking import uniffi.ferrostar.StepAdvanceMode import uniffi.ferrostar.UserLocation import uniffi.ferrostar.Waypoint +import uniffi.ferrostar.WaypointAdvanceMode import uniffi.ferrostar.WaypointKind const val simpleRoute = @@ -254,7 +255,10 @@ class ValhallaCoreTest { foregroundServiceManager = MockForegroundNotificationManager(), navigationControllerConfig = NavigationControllerConfig( - StepAdvanceMode.Manual, RouteDeviationTracking.None, CourseFiltering.RAW)) + WaypointAdvanceMode.WaypointWithinRange(100.0), + StepAdvanceMode.Manual, + RouteDeviationTracking.None, + CourseFiltering.RAW)) return runTest { val routes = @@ -302,7 +306,10 @@ class ValhallaCoreTest { foregroundServiceManager = MockForegroundNotificationManager(), navigationControllerConfig = NavigationControllerConfig( - StepAdvanceMode.Manual, RouteDeviationTracking.None, CourseFiltering.RAW), + WaypointAdvanceMode.WaypointWithinRange(100.0), + StepAdvanceMode.Manual, + RouteDeviationTracking.None, + CourseFiltering.RAW), options = mapOf("costing_options" to mapOf("auto" to mapOf("useTolls" to 0)))) return runTest {