Refactoring Route, Speed

This commit is contained in:
Dimitris
2025-12-24 09:55:53 +01:00
parent d0a07e1315
commit 1b8abbd4eb
11 changed files with 55 additions and 67 deletions

View File

@@ -41,12 +41,9 @@ import com.google.android.gms.location.LocationServices
import com.kouros.navigation.MainApplication.Companion.navigationViewModel import com.kouros.navigation.MainApplication.Companion.navigationViewModel
import com.kouros.navigation.data.Constants.DESTINATION_ARRIVAL_DISTANCE import com.kouros.navigation.data.Constants.DESTINATION_ARRIVAL_DISTANCE
import com.kouros.navigation.data.Constants.homeLocation import com.kouros.navigation.data.Constants.homeLocation
import com.kouros.navigation.data.NavigationRepository
import com.kouros.navigation.data.StepData import com.kouros.navigation.data.StepData
import com.kouros.navigation.data.valhalla.ValhallaRepository
import com.kouros.navigation.model.MockLocation import com.kouros.navigation.model.MockLocation
import com.kouros.navigation.model.RouteModel import com.kouros.navigation.model.RouteModel
import com.kouros.navigation.model.ViewModel
import com.kouros.navigation.ui.theme.NavigationTheme import com.kouros.navigation.ui.theme.NavigationTheme
import com.kouros.navigation.utils.bearing import com.kouros.navigation.utils.bearing
import com.kouros.navigation.utils.calculateZoom import com.kouros.navigation.utils.calculateZoom
@@ -114,13 +111,16 @@ class MainActivity : ComponentActivity() {
} }
locationManager = getSystemService(LOCATION_SERVICE) as LocationManager locationManager = getSystemService(LOCATION_SERVICE) as LocationManager
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this) fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
fusedLocationClient.lastLocation
.addOnSuccessListener { location : android.location.Location? ->
if (useMock) { if (useMock) {
mock = MockLocation(locationManager) mock = MockLocation(locationManager)
mock.setMockLocation( mock.setMockLocation(
homeLocation.latitude, location?.latitude ?: homeLocation.latitude,
homeLocation.longitude location?.longitude ?: homeLocation.longitude
) )
} }
}
enableEdgeToEdge() enableEdgeToEdge()
setContent { setContent {
CheckPermissionScreen() CheckPermissionScreen()
@@ -165,11 +165,6 @@ class MainActivity : ComponentActivity() {
} }
val step: StepData? by stepData.observeAsState() val step: StepData? by stepData.observeAsState()
val nextStep: StepData? by nextStepData.observeAsState() val nextStep: StepData? by nextStepData.observeAsState()
fun openSheet() {
scope.launch { scaffoldState.bottomSheetState.expand() }
}
fun closeSheet() { fun closeSheet() {
scope.launch { scope.launch {
scaffoldState.bottomSheetState.partialExpand() scaffoldState.bottomSheetState.partialExpand()
@@ -242,7 +237,7 @@ class MainActivity : ComponentActivity() {
if (routeState.maneuverType == 39 if (routeState.maneuverType == 39
&& leftStepDistance() < DESTINATION_ARRIVAL_DISTANCE && leftStepDistance() < DESTINATION_ARRIVAL_DISTANCE
) { ) {
stopNavigation() // stopNavigation()
routeState = routeState.copy(arrived = true) routeState = routeState.copy(arrived = true)
routeData.value = "" routeData.value = ""
} }
@@ -305,7 +300,7 @@ class MainActivity : ComponentActivity() {
for ((index, step) in routeModel.legs.steps.withIndex()) { for ((index, step) in routeModel.legs.steps.withIndex()) {
for ((windex, waypoint) in step.maneuver.waypoints.withIndex()) { for ((windex, waypoint) in step.maneuver.waypoints.withIndex()) {
mock.setMockLocation(waypoint[1], waypoint[0]) mock.setMockLocation(waypoint[1], waypoint[0])
delay(1000L) // delay(600L) //
} }
} }
} }

View File

@@ -137,7 +137,7 @@ class RouteCarModel() : RouteModel() {
val dismissAction: Action = createToastAction( val dismissAction: Action = createToastAction(
carContext, carContext,
R.string.speed_camera, R.string.exit_action_title, R.string.exit_action_title, R.string.exit_action_title,
FLAG_DEFAULT FLAG_DEFAULT
) )

View File

@@ -34,7 +34,9 @@ import com.kouros.navigation.data.Place
import com.kouros.navigation.data.nominatim.SearchResult import com.kouros.navigation.data.nominatim.SearchResult
import com.kouros.navigation.data.overpass.Elements import com.kouros.navigation.data.overpass.Elements
import com.kouros.navigation.model.ViewModel import com.kouros.navigation.model.ViewModel
import com.kouros.navigation.utils.bearing
import com.kouros.navigation.utils.location import com.kouros.navigation.utils.location
import kotlin.math.absoluteValue
class NavigationScreen( class NavigationScreen(
carContext: CarContext, carContext: CarContext,
@@ -490,7 +492,12 @@ class NavigationScreen(
} }
val sortedList = updatedCameras.sortedWith(compareBy { it.distance }) val sortedList = updatedCameras.sortedWith(compareBy { it.distance })
val camera = sortedList.first() val camera = sortedList.first()
if (camera.distance < 80) { val bearingSpeedCamera = location.bearingTo(location(camera.lon!!, camera.lat!!))
val bearingRoute = surfaceRenderer.lastLocation.bearingTo(location)
if (camera.distance < 80
&& (bearingSpeedCamera.absoluteValue - bearingRoute.absoluteValue).absoluteValue < 15.0
) {
routeModel.showSpeedCamera(carContext, camera.distance, camera.tags.maxspeed) routeModel.showSpeedCamera(carContext, camera.distance, camera.tags.maxspeed)
} }
} }

View File

@@ -179,3 +179,6 @@ object Constants {
} }
enum class RouteEngine {
VALHALLA, OSRM, GRAPHHOPPER
}

View File

@@ -2,6 +2,8 @@ package com.kouros.navigation.data
import android.location.Location import android.location.Location
import com.google.gson.GsonBuilder import com.google.gson.GsonBuilder
import com.kouros.navigation.data.osrm.OsrmResponse
import com.kouros.navigation.data.osrm.OsrmRoute
import com.kouros.navigation.data.route.Leg import com.kouros.navigation.data.route.Leg
import com.kouros.navigation.data.route.Step import com.kouros.navigation.data.route.Step
import com.kouros.navigation.data.route.Summary import com.kouros.navigation.data.route.Summary
@@ -28,7 +30,7 @@ data class Route(
data class Builder ( data class Builder (
var routeEngine : Int = 0, var routeEngine : Int = RouteEngine.VALHALLA.ordinal,
var summary: Summary? = null, var summary: Summary? = null,
var legs: List<Leg>? = null, var legs: List<Leg>? = null,
var routeGeoJson: String = "", var routeGeoJson: String = "",
@@ -46,10 +48,14 @@ data class Route(
fun route(route: String) = apply { fun route(route: String) = apply {
if (route.isNotEmpty() && route != "[]") { if (route.isNotEmpty() && route != "[]") {
val gson = GsonBuilder().serializeNulls().create() val gson = GsonBuilder().serializeNulls().create()
if (routeEngine == RouteEngine.VALHALLA.ordinal) {
val jsonObject: Map<String, JsonElement> = Json.parseToJsonElement(route).jsonObject val jsonObject: Map<String, JsonElement> = Json.parseToJsonElement(route).jsonObject
val routeJson = val routeJson = gson.fromJson(jsonObject["trip"].toString(), ValhallaResponse::class.java)
gson.fromJson(jsonObject["trip"].toString(), ValhallaResponse::class.java)
ValhallaRoute().mapJsonToValhalla(routeJson, this) ValhallaRoute().mapJsonToValhalla(routeJson, this)
} else {
val osrmJson = gson.fromJson(route, OsrmResponse::class.java)
OsrmRoute().mapToOsrm(osrmJson, this)
}
} }
} }

View File

@@ -3,7 +3,7 @@ package com.kouros.navigation.data.osrm
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName
data class OsrmJson ( data class OsrmResponse (
@SerializedName("code" ) var code : String? = null, @SerializedName("code" ) var code : String? = null,
@SerializedName("routes" ) var routes : ArrayList<Routes> = arrayListOf(), @SerializedName("routes" ) var routes : ArrayList<Routes> = arrayListOf(),

View File

@@ -0,0 +1,11 @@
package com.kouros.navigation.data.osrm
import com.kouros.navigation.data.Route
import com.kouros.navigation.data.valhalla.ValhallaResponse
class OsrmRoute {
fun mapToOsrm(routeJson: OsrmResponse, builder: Route.Builder) {
}
}

View File

@@ -28,6 +28,7 @@ class Overpass {
|); |);
|out body; |out body;
""".trimMargin() """.trimMargin()
println("way[highway](around:$radius,$linestring)")
return overpassApi(httpURLConnection, searchQuery) return overpassApi(httpURLConnection, searchQuery)
} }
@@ -60,7 +61,6 @@ class Overpass {
} }
fun overpassApi(httpURLConnection: HttpURLConnection, searchQuery: String) : List<Elements> { fun overpassApi(httpURLConnection: HttpURLConnection, searchQuery: String) : List<Elements> {
// Send the JSON we created
val outputStreamWriter = OutputStreamWriter(httpURLConnection.outputStream) val outputStreamWriter = OutputStreamWriter(httpURLConnection.outputStream)
outputStreamWriter.write(searchQuery) outputStreamWriter.write(searchQuery)
outputStreamWriter.flush() outputStreamWriter.flush()

View File

@@ -1,20 +0,0 @@
package com.kouros.navigation.data.valhalla
import com.google.gson.annotations.SerializedName
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.JsonIgnoreUnknownKeys
@OptIn(ExperimentalSerializationApi::class)
@JsonIgnoreUnknownKeys
data class Trip (
@SerializedName("locations" ) var locations : ArrayList<Locations> = arrayListOf(),
@SerializedName("legs" ) var legs : ArrayList<Legs> = arrayListOf(),
@SerializedName("summary" ) var summaryValhalla : SummaryValhalla = SummaryValhalla(),
@SerializedName("status_message" ) var statusMessage : String = "",
@SerializedName("status" ) var status : Int = 0,
@SerializedName("units" ) var units : String = "",
@SerializedName("language" ) var language : String = "",
)

View File

@@ -1,16 +0,0 @@
package com.kouros.navigation.data.valhalla
import com.google.gson.annotations.SerializedName
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonIgnoreUnknownKeys
@OptIn(ExperimentalSerializationApi::class)
@JsonIgnoreUnknownKeys
data class ValhallaJson (
@SerializedName("trip" ) var trip : Trip = Trip(),
@SerializedName("id" ) var id : String = ""
)

View File

@@ -26,7 +26,7 @@ open class RouteModel() {
val arrived: Boolean = false, val arrived: Boolean = false,
val maneuverType: Int = 0, val maneuverType: Int = 0,
val travelMessage: String = "", val travelMessage: String = "",
// max speed for street (maneuver) val lastSpeedLocation: Location = location(0.0, 0.0),
val lastSpeedIndex: Int = 0, val lastSpeedIndex: Int = 0,
val maxSpeed: Int = 0, val maxSpeed: Int = 0,
) )
@@ -89,9 +89,11 @@ open class RouteModel() {
} }
fun updateSpeedLimit(location: Location, viewModel: ViewModel) { fun updateSpeedLimit(location: Location, viewModel: ViewModel) {
// speed limit for each maneuver index // speed limit
if (routeState.lastSpeedIndex < route.currentStep) { val distance = routeState.lastSpeedLocation.distanceTo(location)
if (distance > 500 || routeState.lastSpeedIndex < route.currentStep) {
routeState = routeState.copy(lastSpeedIndex = route.currentStep) routeState = routeState.copy(lastSpeedIndex = route.currentStep)
routeState = routeState.copy(lastSpeedLocation = location)
val elements = viewModel.getMaxSpeed(location) val elements = viewModel.getMaxSpeed(location)
elements.forEach { elements.forEach {
if (it.tags.name != null && it.tags.maxspeed != null) { if (it.tags.name != null && it.tags.maxspeed != null) {