RouteCalculator

This commit is contained in:
Dimitris
2026-05-07 10:34:27 +02:00
parent 8b612d5b80
commit 72b3185280
8 changed files with 79 additions and 53 deletions
@@ -16,6 +16,7 @@
package com.kouros.navigation.data
import android.location.Location
import android.net.Uri
import com.google.gson.annotations.Expose
import com.kouros.navigation.data.route.Lane
@@ -28,7 +29,7 @@ data class Category(
val name: String,
)
data class StepMatch(val stepIndex: Int, val waypointIndex: Int, val location: Location)
data class Places(
val places: List<Place>,
@@ -144,7 +145,7 @@ object Constants {
const val NEAREST_LOCATION_DISTANCE = 10F
const val MAXIMUM_LOCATION_DISTANCE = 100000F
const val MAXIMUM_LOCATION_DISTANCE = Float.MAX_VALUE
const val TRAFFIC_UPDATE = 300
@@ -3,60 +3,84 @@ package com.kouros.navigation.model
import android.location.Location
import android.util.Log
import androidx.car.app.navigation.model.Step
import com.kouros.navigation.data.ApplicationConfig
import com.kouros.navigation.data.Constants.MAXIMUM_LOCATION_DISTANCE
import com.kouros.navigation.data.Constants.NEAREST_LOCATION_DISTANCE
import com.kouros.navigation.data.Constants.SPEED_UPDATE_DISTANCE
import com.kouros.navigation.data.Constants.TAG
import com.kouros.navigation.utils.bearingPositive
import com.kouros.navigation.data.StepMatch
import com.kouros.navigation.data.osrm.Waypoints
import com.kouros.navigation.utils.location
import java.util.concurrent.TimeUnit
import kotlin.math.absoluteValue
class RouteCalculator(var routeModel: RouteModel) {
var bestMatch: StepMatch? = null
var lastSpeedLocation: Location = location(0.0, 0.0)
var lastSpeedIndex: Int = 0
fun findStep(location: Location) {
val route = routeModel.navState.route
val steps = routeModel.curLeg.steps
val startIndex = route.currentStepIndex
// Windowed search for performance (current + 2 steps)
//val endIndex = (startIndex + 2).coerceAtMost(steps.size - 1)
val endIndex = steps.size - 1
var nearestDistance = MAXIMUM_LOCATION_DISTANCE
var count = 0
var lastDistance = 0F
var increaseDistance = 0
for ((index, step) in routeModel.curLeg.steps.withIndex()) {
count++
var distance = 0F
if (index >= routeModel.navState.route.currentStepIndex) {
for ((wayIndex, waypoint) in step.maneuver.waypoints.withIndex()) {
count++
if (wayIndex >= step.waypointIndex) {
distance = location.distanceTo(waypoint)
if (distance < nearestDistance ) {
nearestDistance = distance
routeModel.navState.route.currentStepIndex = step.index
step.waypointIndex = wayIndex
step.wayPointLocation = waypoint
}
}
if (stopSearch(nearestDistance, distance) || increaseDistance > 20) {
break
}
if (distance > lastDistance) {
increaseDistance++
}
lastDistance = distance
var searchCount = 0
for (i in startIndex..endIndex) {
val step = steps[i]
val waypoints = step.maneuver.waypoints
val startWayIndex = if (i == startIndex) step.waypointIndex else 0
var lastDistance = Float.MAX_VALUE
var increaseCount = 0
for (j in startWayIndex until waypoints.size) {
searchCount++
val waypoint = waypoints[j]
val distance = location.distanceTo(waypoint)
if (distance < nearestDistance) {
nearestDistance = distance
bestMatch = StepMatch(step.index, j, waypoint)
}
}
if (stopSearch(nearestDistance, distance) || increaseDistance > 20) {
break
// Track if we are getting further away
if (distance > lastDistance) {
increaseCount++
} else {
increaseCount = 0
}
// Absolute early exit: found a close point and now moved far away
if (stopSearch(nearestDistance, distance, increaseCount)) {
bestMatch?.let { match ->
route.currentStepIndex = match.stepIndex
steps[match.stepIndex].waypointIndex = match.waypointIndex
steps[match.stepIndex].wayPointLocation = match.location
}
Log.d(TAG, "FindStep optimized: count=$searchCount, dist=$nearestDistance")
return
}
lastDistance = distance
}
}
Log.d(TAG, "FindStep $nearestDistance $count $increaseDistance")
bestMatch?.let { match ->
route.currentStepIndex = match.stepIndex
steps[match.stepIndex].waypointIndex = match.waypointIndex
steps[match.stepIndex].wayPointLocation = match.location
}
Log.d(TAG, "FindStep not optimized: count=$searchCount, dist=$nearestDistance")
}
private fun stopSearch(nearestDistance: Float, distance: Float): Boolean {
return nearestDistance < NEAREST_LOCATION_DISTANCE && distance > NEAREST_LOCATION_DISTANCE * 10
private fun stopSearch(nearestDistance: Float, distance: Float, increaseCount: Int): Boolean {
return (nearestDistance < NEAREST_LOCATION_DISTANCE && distance > NEAREST_LOCATION_DISTANCE * 10)
|| increaseCount > 10
}
fun travelLeftTime(): Double {
@@ -92,7 +116,7 @@ class RouteCalculator(var routeModel: RouteModel) {
fun leftStepDistance(): Double {
val step = routeModel.route.currentStep()
var leftDistance = 0F
if (step.waypointIndex < step.maneuver.waypoints.size -1) {
if (step.waypointIndex < step.maneuver.waypoints.size - 1) {
leftDistance = step.maneuver.leftDistance[step.waypointIndex]
val waypointLocation = step.maneuver.waypoints[step.waypointIndex]
if (routeModel.navState.lastLocation.latitude != 0.0) {