TomTom Routing

This commit is contained in:
Dimitris
2026-02-09 08:44:57 +01:00
parent 0d51c6121d
commit e9474695bf
8 changed files with 95 additions and 70 deletions

View File

@@ -87,8 +87,8 @@ class MainActivity : ComponentActivity() {
val routeModel = RouteModel()
var tilt = 50.0
val useMock = false
val type = 1 // simulate 2 test 3 gpx
val useMock = true
val type = 3 // simulate 2 test 3 gpx
var currentIndex = 0
val stepData: MutableLiveData<StepData> by lazy {
@@ -317,6 +317,7 @@ class MainActivity : ComponentActivity() {
if (isNavigating()) {
updateLocation(currentLocation, navigationViewModel)
stepData.value = currentStep()
println("Step: ${stepData.value!!.instruction} ${stepData.value!!.leftStepDistance}")
if (route.currentStepIndex + 1 <= curLeg.steps.size) {
nextStepData.value = nextStep()
}
@@ -390,7 +391,7 @@ class MainActivity : ComponentActivity() {
for ((index, waypoint) in routeModel.curRoute.waypoints.withIndex()) {
if (routeModel.isNavigating()) {
val deviation = 0.0
if (index in 300..routeModel.curRoute.waypoints.size) {
if (index in 0..routeModel.curRoute.waypoints.size) {
mock.setMockLocation(waypoint[1], waypoint[0])
delay(500L) //
}
@@ -408,7 +409,7 @@ class MainActivity : ComponentActivity() {
navigationViewModel
)
val step = routeModel.currentStep()
println("Step: ${step}")
println("Step: ${step.instruction} ${step.leftStepDistance}")
if (step.leftStepDistance == 70.0) {
println("")
}

View File

@@ -33,12 +33,6 @@ abstract class NavigationRepository {
//private val nominatimUrl = "https://kouros-online.de/nominatim/"
val tomtomApiKey = "678k5v6940cSXXIS5oD92qIrDgW3RBZ3"
private val tomtomUrl = "https://api.tomtom.com/traffic/services/5/incidentDetails"
private val tomtomFields =
"{incidents{type,geometry{type,coordinates},properties{iconCategory,events{description}}}}"
abstract fun getRoute(
context: Context,
@@ -48,6 +42,7 @@ abstract class NavigationRepository {
searchFilter: SearchFilter
): String
abstract fun getTraffic(context: Context, location: Location, carOrientation: Float): String
fun getRouteDistance(
currentLocation: Location,
location: Location,
@@ -78,23 +73,7 @@ abstract class NavigationRepository {
)
}
fun getTraffic(context: Context, location: Location, carOrientation: Float): String {
val useAsset = false
val bbox = calculateSquareRadius(location.latitude, location.longitude, 15.0)
return if (useAsset) {
val trafficJson = context.resources.openRawResource(R.raw.tomtom_traffic)
trafficJson.bufferedReader().use { it.readText() }
} else {
val trafficResult = fetchUrl(
"$tomtomUrl?key=$tomtomApiKey&bbox=$bbox&fields=$tomtomFields&language=en-GB&timeValidityFilter=present",
false
)
trafficResult.replace(
"{\"incidents\":",
"{\"type\": \"FeatureCollection\", \"features\":"
)
}
}
fun fetchUrl(url: String, authenticator: Boolean): String {
try {

View File

@@ -26,4 +26,12 @@ class OsrmRepository : NavigationRepository() {
val routeLocation = "${currentLocation.longitude},${currentLocation.latitude};${location.longitude},${location.latitude}?steps=true&alternatives=0"
return fetchUrl(routeUrl + routeLocation + exclude, true)
}
override fun getTraffic(
context: Context,
location: Location,
carOrientation: Float
): String {
TODO("Not yet implemented")
}
}

View File

@@ -5,10 +5,19 @@ import android.location.Location
import com.kouros.data.R
import com.kouros.navigation.data.NavigationRepository
import com.kouros.navigation.data.SearchFilter
import com.kouros.navigation.utils.GeoUtils.calculateSquareRadius
private const val routeUrl = "https://api.tomtom.com/routing/1/calculateRoute/"
val tomtomApiKey = "678k5v6940cSXXIS5oD92qIrDgW3RBZ3"
val tomtomTrafficUrl = "https://api.tomtom.com/traffic/services/5/incidentDetails"
private val tomtomFields =
"{incidents{type,geometry{type,coordinates},properties{iconCategory,events{description}}}}"
class TomTomRepository : NavigationRepository() {
override fun getRoute(
context: Context,
@@ -17,9 +26,9 @@ class TomTomRepository : NavigationRepository() {
carOrientation: Float,
searchFilter: SearchFilter
): String {
//val routeJson = context.resources.openRawResource(R.raw.tomom_routing)
//val routeJsonString = routeJson.bufferedReader().use { it.readText() }
//return routeJsonString
val routeJson = context.resources.openRawResource(R.raw.tomom_routing)
val routeJsonString = routeJson.bufferedReader().use { it.readText() }
return routeJsonString
val url =
routeUrl + "${currentLocation.latitude},${currentLocation.longitude}:${location.latitude},${location.longitude}" +
"/json?vehicleHeading=90&sectionType=traffic&report=effectiveSettings&routeType=eco" +
@@ -33,4 +42,22 @@ class TomTomRepository : NavigationRepository() {
false
)
}
override fun getTraffic(context: Context, location: Location, carOrientation: Float): String {
val useAsset = true
val bbox = calculateSquareRadius(location.latitude, location.longitude, 15.0)
return if (useAsset) {
val trafficJson = context.resources.openRawResource(R.raw.tomtom_traffic)
trafficJson.bufferedReader().use { it.readText() }
} else {
val trafficResult = fetchUrl(
"$tomtomTrafficUrl?key=$tomtomApiKey&bbox=$bbox&fields=$tomtomFields&language=en-GB&timeValidityFilter=present",
false
)
trafficResult.replace(
"{\"incidents\":",
"{\"type\": \"FeatureCollection\", \"features\":"
)
}
}
}

View File

@@ -47,4 +47,12 @@ class ValhallaRepository : NavigationRepository() {
val routeLocation = Json.encodeToString(valhallaLocation)
return fetchUrl(routeUrl + routeLocation, true)
}
override fun getTraffic(
context: Context,
location: Location,
carOrientation: Float
): String {
TODO("Not yet implemented")
}
}

View File

@@ -136,25 +136,25 @@ open class RouteModel() {
}
return lanes
var inter = Intersection()
var nearestDistance = 100000.0f
route.currentStep().intersection.forEach {
if (it.lane.isNotEmpty()) {
val distance = location.distanceTo(location(it.location[0], it.location[1]))
val interBearing = location.bearingTo(location(it.location[0], it.location[1]))
if (distance < nearestDistance) {
nearestDistance = distance
if (distance <= NEXT_STEP_THRESHOLD * 3) {
if (route.routeEngine == RouteEngine.TOMTOM.ordinal
|| (interBearing.absoluteValue - route.currentStep().maneuver.bearingAfter.absoluteValue).absoluteValue < 20
) {
inter = it
}
}
}
}
}
return inter.lane
// var inter = Intersection()
// var nearestDistance = 100000.0f
// route.currentStep().intersection.forEach {
// if (it.lane.isNotEmpty()) {
// val distance = location.distanceTo(location(it.location[0], it.location[1]))
// val interBearing = location.bearingTo(location(it.location[0], it.location[1]))
// if (distance < nearestDistance) {
// nearestDistance = distance
// if (distance <= NEXT_STEP_THRESHOLD * 3) {
// if (route.routeEngine == RouteEngine.TOMTOM.ordinal
// || (interBearing.absoluteValue - route.currentStep().maneuver.bearingAfter.absoluteValue).absoluteValue < 20
// ) {
// inter = it
// }
// }
// }
// }
// }
// return inter.lane
}
fun updateSpeedLimit(location: Location, viewModel: ViewModel) = runBlocking {
@@ -188,7 +188,7 @@ open class RouteModel() {
fun currentStep(): StepData {
val distanceToNextStep = leftStepDistance()
// Determine the maneuver type and corresponding icon
val currentStep = route.nextStep(1) // This advances the route's state
val currentStep = route.nextStep(1)
// Safely get the street name from the maneuver
val streetName = currentStep.name
val curManeuverType = currentStep.maneuver.type
@@ -270,7 +270,8 @@ open class RouteModel() {
/** Returns the current [Step] left distance in m. */
fun leftStepDistance(): Double {
val step = route.currentStep()
var leftDistance = 0.0
println(step.index)
var leftDistance = 0F
for (i in step.waypointIndex..<step.maneuver.waypoints.size - 1) {
val loc1 = location(step.maneuver.waypoints[i][0], step.maneuver.waypoints[i][1])
val loc2 =

View File

@@ -135,7 +135,7 @@
"source": "openmaptiles",
"source-layer": "landuse",
"filter": ["==", ["get", "class"], "track"],
"paint": {"fill-color": "#DEE3CD"}
"paint": {"fill-color": "rgba(67, 67, 65, 1)"}
},
{
"id": "landuse_cemetery",
@@ -151,7 +151,7 @@
"source": "openmaptiles",
"source-layer": "landuse",
"filter": ["==", ["get", "class"], "hospital"],
"paint": {"fill-color": "#fde"}
"paint": {"fill-color": "rgba(51, 45, 48, 1)"}
},
{
"id": "landuse_school",
@@ -362,7 +362,7 @@
["==", ["get", "brunnel"], "tunnel"],
["match", ["get", "class"], ["service", "track"], true, false]
],
"layout": {"line-join": "round"},
"layout": {"line-join": "round", "visibility": "none"},
"paint": {
"line-color": "#cfcdca",
"line-dasharray": [0.5, 0.25],
@@ -535,6 +535,7 @@
["==", ["get", "brunnel"], "tunnel"],
["match", ["get", "class"], ["path", "pedestrian"], true, false]
],
"layout": {"visibility": "none"},
"paint": {
"line-color": "hsl(0,0%,100%)",
"line-dasharray": [1, 0.75],
@@ -588,7 +589,7 @@
["==", ["get", "brunnel"], "tunnel"],
["match", ["get", "class"], ["service", "track"], true, false]
],
"layout": {"line-join": "round"},
"layout": {"line-join": "round", "visibility": "none"},
"paint": {
"line-color": "#fff",
"line-width": [
@@ -616,7 +617,7 @@
],
"layout": {"line-join": "round"},
"paint": {
"line-color": "#fff4c6",
"line-color": "rgba(72, 72, 67, 1)",
"line-width": [
"interpolate",
["exponential", 1.2],

View File

@@ -6,39 +6,39 @@ koinAndroid = "4.1.1"
koinAndroidxCompose = "4.1.1"
koinComposeViewmodel = "4.1.1"
koinCore = "4.1.1"
kotlin = "2.3.0"
kotlin = "2.3.10"
coreKtx = "1.17.0"
junit = "4.13.2"
junitVersion = "1.3.0"
espressoCore = "3.7.0"
kotlinxSerializationJson = "1.9.0"
kotlinxSerializationJson = "1.10.0"
lifecycleRuntimeKtx = "2.10.0"
composeBom = "2025.12.01"
composeBom = "2026.01.01"
appcompat = "1.7.1"
material = "1.13.0"
carApp = "1.7.0"
androidx-car = "1.7.0"
objectboxKotlin = "5.0.1"
objectboxKotlin = "5.1.0"
objectboxProcessor = "5.0.1"
ui = "1.10.0"
material3 = "1.4.0"
runtimeLivedata = "1.10.0"
runtimeLivedata = "1.10.2"
foundation = "1.10.0"
maplibre-composeMaterial3 = "0.12.2"
maplibre-compose = "0.12.1"
playServicesLocation = "21.3.0"
runtime = "1.10.0"
runtime = "1.10.2"
accompanist = "0.37.3"
uiVersion = "1.10.0"
uiText = "1.10.0"
navigationCompose = "2.9.6"
uiToolingPreview = "1.10.0"
uiTooling = "1.10.0"
uiVersion = "1.10.2"
uiText = "1.10.2"
navigationCompose = "2.9.7"
uiToolingPreview = "1.10.2"
uiTooling = "1.10.2"
material3WindowSizeClass = "1.4.0"
uiGraphics = "1.10.0"
uiGraphics = "1.10.2"
window = "1.5.1"
foundationLayout = "1.10.0"
foundationLayoutVersion = "1.10.1"
foundationLayout = "1.10.2"
foundationLayoutVersion = "1.10.2"
[libraries]