CheckRoute, Simulation, Closed Streets
This commit is contained in:
@@ -111,7 +111,8 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
|
||||
|
||||
var speedCameras = listOf<Elements>()
|
||||
|
||||
var lastRouteDate: LocalDateTime = LocalDateTime.now()
|
||||
|
||||
private var lastRouteCheckLocation = location(0.0, 0.0)
|
||||
|
||||
var navigationManagerStarted = false
|
||||
|
||||
@@ -461,10 +462,11 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
|
||||
* Snaps location to route and checks for deviation requiring reroute.
|
||||
*/
|
||||
private fun handleNavigationLocation(location: Location) {
|
||||
val start = System.currentTimeMillis()
|
||||
routeModel.updateLocation(location, navigationViewModel)
|
||||
val snappedLocation = snapLocation(location, routeModel.route.maneuverLocations())
|
||||
val streetName = routeModel.currentStep().street
|
||||
if (checkLocationDeviation(location, snappedLocation, streetName)) {
|
||||
if (checkLocationDeviation(location, snappedLocation, streetName)) {
|
||||
if (routeModel.navState.arrived) return
|
||||
if (guidanceAudio == 1) {
|
||||
handleGuidanceAudio()
|
||||
@@ -472,16 +474,22 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
|
||||
val currentDate = LocalDateTime.now(ZoneOffset.UTC)
|
||||
checkTraffic(currentDate, snappedLocation)
|
||||
updateSpeedCamera(snappedLocation)
|
||||
checkRoute(currentDate, snappedLocation)
|
||||
checkRoute(snappedLocation)
|
||||
updateNavigationScreen()
|
||||
checkArrival()
|
||||
}
|
||||
val end = System.currentTimeMillis()
|
||||
// Log.d(TAG, "UpdateLoction ${end-start} ms")
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the location deviation is acceptable.
|
||||
*/
|
||||
private fun checkLocationDeviation(location: Location, snappedLocation: Location, streetName: String): Boolean {
|
||||
private fun checkLocationDeviation(
|
||||
location: Location,
|
||||
snappedLocation: Location,
|
||||
streetName: String
|
||||
): Boolean {
|
||||
val distance = location.distanceTo(snappedLocation)
|
||||
when {
|
||||
distance > MAXIMAL_ROUTE_DEVIATION -> {
|
||||
@@ -493,6 +501,7 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
|
||||
distance < MAXIMAL_SNAP_CORRECTION -> {
|
||||
surfaceRenderer.updateLocation(snappedLocation, streetName)
|
||||
}
|
||||
|
||||
else -> {
|
||||
surfaceRenderer.updateLocation(location, streetName)
|
||||
}
|
||||
@@ -657,8 +666,10 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
|
||||
val newRouteModel = RouteModel()
|
||||
newRouteModel.navState = routeModel.navState.copy(routingEngine = routingEngine)
|
||||
newRouteModel.startNavigation(route)
|
||||
routeModel.curRoute.summary.trafficDelay = newRouteModel.curRoute.summary.trafficDelay
|
||||
updateNavigationScreen()
|
||||
if ((routeModel.curRoute.summary.trafficDelay - newRouteModel.curRoute.summary.trafficDelay).absoluteValue > 300) {
|
||||
routeModel.startNavigation(route)
|
||||
updateNavigationScreen()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -767,7 +778,7 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
|
||||
* Periodically requests speed camera information near the current location.
|
||||
*/
|
||||
private fun updateSpeedCamera(location: Location) {
|
||||
if (lastCameraSearch % 100 == 0) {
|
||||
if (lastCameraSearch % 200 == 0) {
|
||||
navigationViewModel.getSpeedCameras(location, 5.0)
|
||||
}
|
||||
if (speedCameras.isNotEmpty() && lastCameraSearch % 15 == 0) {
|
||||
@@ -811,24 +822,36 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
|
||||
/**
|
||||
* Checks if a new route is needed based on the time since the last update.
|
||||
*/
|
||||
private fun checkRoute(currentDate: LocalDateTime, location: Location) {
|
||||
val duration = Duration.between(currentDate, lastRouteDate)
|
||||
val routeUpdate = routeModel.curRoute.summary.duration / 4
|
||||
if (duration.abs().seconds > routeUpdate) {
|
||||
lastRouteDate = currentDate
|
||||
val destination = location(
|
||||
routeModel.navState.destination.longitude,
|
||||
routeModel.navState.destination.latitude
|
||||
)
|
||||
navigationViewModel.loadRoute(
|
||||
carContext,
|
||||
location,
|
||||
listOf(destination),
|
||||
surfaceRenderer.carOrientation
|
||||
)
|
||||
private fun checkRoute(location: Location) {
|
||||
val distance = location.distanceTo(lastRouteCheckLocation)
|
||||
if (distance > checkDistance(routeModel)) {
|
||||
Log.d(TAG, "CheckRoute $distance ${checkDistance(routeModel)}")
|
||||
if (lastRouteCheckLocation.latitude != 0.0) {
|
||||
val destination = location(
|
||||
routeModel.navState.destination.longitude,
|
||||
routeModel.navState.destination.latitude
|
||||
)
|
||||
navigationViewModel.loadRoute(
|
||||
carContext,
|
||||
location,
|
||||
listOf(destination),
|
||||
surfaceRenderer.carOrientation
|
||||
)
|
||||
}
|
||||
lastRouteCheckLocation = location
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkDistance(routeModel: RouteModel): Double {
|
||||
val factor = when (routeModel.curRoute.summary.distance) {
|
||||
in 0.0..20000.0 -> 4
|
||||
in 20000.0..100000.0 -> 5
|
||||
in 10000.0..200000.0 -> 6
|
||||
else -> 7
|
||||
}
|
||||
return (routeModel.curRoute.summary.distance / factor)
|
||||
}
|
||||
|
||||
override fun invalidateNavigationScreen() {
|
||||
navigationScreen.invalidate()
|
||||
}
|
||||
|
||||
@@ -28,9 +28,7 @@ import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.kouros.data.R
|
||||
import com.kouros.navigation.data.ClosedColor
|
||||
import com.kouros.navigation.data.Constants
|
||||
import com.kouros.navigation.data.Constants.homeVogelhart
|
||||
import com.kouros.navigation.data.HeavyColor
|
||||
import com.kouros.navigation.data.LaneColor
|
||||
import com.kouros.navigation.data.NavigationColorDark
|
||||
@@ -43,7 +41,6 @@ import com.kouros.navigation.data.SlowColor
|
||||
import com.kouros.navigation.data.SpeedColor
|
||||
import com.kouros.navigation.data.StationaryColor
|
||||
import com.kouros.navigation.data.ViewStyle
|
||||
import com.kouros.navigation.utils.GeoUtils.createEndCollection
|
||||
import com.kouros.navigation.utils.GeoUtils.createPointCollection
|
||||
import com.kouros.navigation.utils.isMetricSystem
|
||||
import com.kouros.navigation.utils.location
|
||||
@@ -143,7 +140,7 @@ fun MapLibre(
|
||||
@Composable
|
||||
fun StartEndLayer(routeData: String?) {
|
||||
if (!routeData.isNullOrEmpty()) {
|
||||
val end = createEndCollection(routeData)
|
||||
val end = createPointCollection(routeData)
|
||||
val routes = rememberGeoJsonSource(GeoJsonData.JsonString(end))
|
||||
val img = image(painterResource(R.drawable.sports_score_48px), drawAsSdf = true)
|
||||
SymbolLayer(
|
||||
@@ -186,23 +183,48 @@ fun RouteLayer(routeData: String?) {
|
||||
@Composable
|
||||
fun TrafficLayer(trafficData: Map<String, String>) {
|
||||
trafficData.forEach {
|
||||
val traffic = rememberGeoJsonSource(GeoJsonData.JsonString(it.value))
|
||||
LineLayer(
|
||||
id = "traffic-${it.key}-casing",
|
||||
source = traffic,
|
||||
color = const(Color.White),
|
||||
width = routeLineWidth(base = 2.dp, isCasing = true),
|
||||
)
|
||||
LineLayer(
|
||||
id = "traffic-${it.key}",
|
||||
source = traffic,
|
||||
color = trafficColor(it.key),
|
||||
width = routeLineWidth(base = 1.dp, isCasing = false),
|
||||
)
|
||||
if (it.key == "closed") {
|
||||
ClosedLayer(it)
|
||||
} else {
|
||||
val traffic = rememberGeoJsonSource(GeoJsonData.JsonString(it.value))
|
||||
LineLayer(
|
||||
id = "traffic-${it.key}-casing",
|
||||
source = traffic,
|
||||
color = const(Color.White),
|
||||
width = routeLineWidth(base = 2.dp, isCasing = true),
|
||||
)
|
||||
LineLayer(
|
||||
id = "traffic-${it.key}",
|
||||
source = traffic,
|
||||
color = trafficColor(it.key),
|
||||
width = routeLineWidth(base = 1.dp, isCasing = false),
|
||||
)
|
||||
}
|
||||
// TrafficIcons(it)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ClosedLayer(entry: Map.Entry<String, String>) {
|
||||
val routes = rememberGeoJsonSource(GeoJsonData.JsonString(entry.value))
|
||||
val img = image(painterResource(R.drawable.do_not_disturb_on_24px), drawAsSdf = true)
|
||||
SymbolLayer(
|
||||
id = "closed-layer",
|
||||
source = routes,
|
||||
iconColor = const(Color.Red),
|
||||
iconImage = img,
|
||||
iconSize =
|
||||
interpolate(
|
||||
type = exponential(2.0f),
|
||||
input = zoom(),
|
||||
5 to const(2.0f),
|
||||
10 to const(2.0f),
|
||||
15 to const(3.0f),
|
||||
20 to const(4.0f),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TrafficIcons(entry: Map.Entry<String, String>) {
|
||||
val featureCollection = FeatureCollection.fromJson(entry.value)
|
||||
@@ -307,7 +329,6 @@ fun trafficColor(key: String): Expression<ColorValue> {
|
||||
"stationary" -> return const(StationaryColor)
|
||||
"heavy" -> return const(HeavyColor)
|
||||
"roadworks" -> return const(RoadworksColor)
|
||||
"closed" -> return const(ClosedColor)
|
||||
"lane" -> return const(LaneColor)
|
||||
}
|
||||
return const(Color.Blue)
|
||||
|
||||
@@ -56,14 +56,14 @@ class Simulation {
|
||||
longitude = point[0]
|
||||
bearing = curBearing
|
||||
speedAccuracyMetersPerSecond = 1.0f // ~1 m/s
|
||||
speed = 9.0f
|
||||
speed = 10.0f
|
||||
time = System.currentTimeMillis()
|
||||
elapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos()
|
||||
}
|
||||
// Update your app's state as if a real GPS update occurred
|
||||
updateLocation(fakeLocation)
|
||||
// Wait before moving to the next point (e.g., every 1 second)
|
||||
delay(500)
|
||||
delay(1500)
|
||||
lastLocation = fakeLocation
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user