diff --git a/app/src/main/java/com/kouros/navigation/MainActivity.kt b/app/src/main/java/com/kouros/navigation/MainActivity.kt index c692f4f..f8eba19 100644 --- a/app/src/main/java/com/kouros/navigation/MainActivity.kt +++ b/app/src/main/java/com/kouros/navigation/MainActivity.kt @@ -350,8 +350,8 @@ class MainActivity : ComponentActivity() { var bearing: Double if (routeModel.isNavigating()) { snapedLocation = snapLocation(location, routeModel.route.maneuverLocations()) + routeModel.updateLocation(location) bearing = routeModel.currentStep().bearing - routeModel.updateLocation(snapedLocation) instruction.postValue(routeModel.currentStep()) } else { bearing = cameraPosition.value!!.bearing diff --git a/automotive/.gitignore b/automotive/.gitignore deleted file mode 100644 index 42afabf..0000000 --- a/automotive/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/automotive/build.gradle.kts b/automotive/build.gradle.kts deleted file mode 100644 index 60668d0..0000000 --- a/automotive/build.gradle.kts +++ /dev/null @@ -1,47 +0,0 @@ -plugins { - alias(libs.plugins.android.application) - alias(libs.plugins.kotlin.android) -} - -android { - namespace = "com.kouros.navigation.automotive" - compileSdk { - version = release(36) - } - - defaultConfig { - applicationId = "com.kouros.navigation.automotive" - minSdk = 35 - targetSdk = 36 - versionCode = 1 - versionName = "1.0" - - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles( - getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro" - ) - } - } - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - } - kotlinOptions { - jvmTarget = "11" - } -} - -dependencies { - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.appcompat) - implementation(libs.material) - testImplementation(libs.junit) - androidTestImplementation(libs.androidx.junit) - androidTestImplementation(libs.androidx.espresso.core) -} \ No newline at end of file diff --git a/automotive/proguard-rules.pro b/automotive/proguard-rules.pro deleted file mode 100644 index 481bb43..0000000 --- a/automotive/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/automotive/src/androidTest/java/com/kouros/navigation/automotive/ExampleInstrumentedTest.kt b/automotive/src/androidTest/java/com/kouros/navigation/automotive/ExampleInstrumentedTest.kt deleted file mode 100644 index e41c673..0000000 --- a/automotive/src/androidTest/java/com/kouros/navigation/automotive/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.kouros.navigation.automotive - -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.ext.junit.runners.AndroidJUnit4 - -import org.junit.Test -import org.junit.runner.RunWith - -import org.junit.Assert.* - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("com.kouros.navigation.automotive", appContext.packageName) - } -} \ No newline at end of file diff --git a/automotive/src/main/AndroidManifest.xml b/automotive/src/main/AndroidManifest.xml deleted file mode 100644 index 69a24f2..0000000 --- a/automotive/src/main/AndroidManifest.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/automotive/src/main/res/drawable/ic_launcher_background.xml b/automotive/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 07d5da9..0000000 --- a/automotive/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/automotive/src/main/res/drawable/ic_launcher_foreground.xml b/automotive/src/main/res/drawable/ic_launcher_foreground.xml deleted file mode 100644 index 2b068d1..0000000 --- a/automotive/src/main/res/drawable/ic_launcher_foreground.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/automotive/src/main/res/mipmap-anydpi/ic_launcher.xml b/automotive/src/main/res/mipmap-anydpi/ic_launcher.xml deleted file mode 100644 index 6f3b755..0000000 --- a/automotive/src/main/res/mipmap-anydpi/ic_launcher.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/automotive/src/main/res/mipmap-anydpi/ic_launcher_round.xml b/automotive/src/main/res/mipmap-anydpi/ic_launcher_round.xml deleted file mode 100644 index 6f3b755..0000000 --- a/automotive/src/main/res/mipmap-anydpi/ic_launcher_round.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/automotive/src/main/res/mipmap-hdpi/ic_launcher.webp b/automotive/src/main/res/mipmap-hdpi/ic_launcher.webp deleted file mode 100644 index c209e78..0000000 Binary files a/automotive/src/main/res/mipmap-hdpi/ic_launcher.webp and /dev/null differ diff --git a/automotive/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/automotive/src/main/res/mipmap-hdpi/ic_launcher_round.webp deleted file mode 100644 index b2dfe3d..0000000 Binary files a/automotive/src/main/res/mipmap-hdpi/ic_launcher_round.webp and /dev/null differ diff --git a/automotive/src/main/res/mipmap-mdpi/ic_launcher.webp b/automotive/src/main/res/mipmap-mdpi/ic_launcher.webp deleted file mode 100644 index 4f0f1d6..0000000 Binary files a/automotive/src/main/res/mipmap-mdpi/ic_launcher.webp and /dev/null differ diff --git a/automotive/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/automotive/src/main/res/mipmap-mdpi/ic_launcher_round.webp deleted file mode 100644 index 62b611d..0000000 Binary files a/automotive/src/main/res/mipmap-mdpi/ic_launcher_round.webp and /dev/null differ diff --git a/automotive/src/main/res/mipmap-xhdpi/ic_launcher.webp b/automotive/src/main/res/mipmap-xhdpi/ic_launcher.webp deleted file mode 100644 index 948a307..0000000 Binary files a/automotive/src/main/res/mipmap-xhdpi/ic_launcher.webp and /dev/null differ diff --git a/automotive/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/automotive/src/main/res/mipmap-xhdpi/ic_launcher_round.webp deleted file mode 100644 index 1b9a695..0000000 Binary files a/automotive/src/main/res/mipmap-xhdpi/ic_launcher_round.webp and /dev/null differ diff --git a/automotive/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/automotive/src/main/res/mipmap-xxhdpi/ic_launcher.webp deleted file mode 100644 index 28d4b77..0000000 Binary files a/automotive/src/main/res/mipmap-xxhdpi/ic_launcher.webp and /dev/null differ diff --git a/automotive/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/automotive/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp deleted file mode 100644 index 9287f50..0000000 Binary files a/automotive/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp and /dev/null differ diff --git a/automotive/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/automotive/src/main/res/mipmap-xxxhdpi/ic_launcher.webp deleted file mode 100644 index aa7d642..0000000 Binary files a/automotive/src/main/res/mipmap-xxxhdpi/ic_launcher.webp and /dev/null differ diff --git a/automotive/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/automotive/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp deleted file mode 100644 index 9126ae3..0000000 Binary files a/automotive/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp and /dev/null differ diff --git a/automotive/src/main/res/values-night/themes.xml b/automotive/src/main/res/values-night/themes.xml deleted file mode 100644 index 68b1bf6..0000000 --- a/automotive/src/main/res/values-night/themes.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - \ No newline at end of file diff --git a/automotive/src/main/res/values/colors.xml b/automotive/src/main/res/values/colors.xml deleted file mode 100644 index f8c6127..0000000 --- a/automotive/src/main/res/values/colors.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - #FFBB86FC - #FF6200EE - #FF3700B3 - #FF03DAC5 - #FF018786 - #FF000000 - #FFFFFFFF - \ No newline at end of file diff --git a/automotive/src/main/res/values/strings.xml b/automotive/src/main/res/values/strings.xml deleted file mode 100644 index f6be987..0000000 --- a/automotive/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - automotive - \ No newline at end of file diff --git a/automotive/src/main/res/values/themes.xml b/automotive/src/main/res/values/themes.xml deleted file mode 100644 index 23e83b0..0000000 --- a/automotive/src/main/res/values/themes.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - \ No newline at end of file diff --git a/automotive/src/test/java/com/kouros/navigation/automotive/ExampleUnitTest.kt b/automotive/src/test/java/com/kouros/navigation/automotive/ExampleUnitTest.kt deleted file mode 100644 index 45bc852..0000000 --- a/automotive/src/test/java/com/kouros/navigation/automotive/ExampleUnitTest.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.kouros.navigation.automotive - -import org.junit.Test - -import org.junit.Assert.* - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} \ No newline at end of file diff --git a/common/car/src/main/java/com/kouros/navigation/car/MapView.kt b/common/car/src/main/java/com/kouros/navigation/car/MapView.kt index 7b813d9..a12a6c9 100644 --- a/common/car/src/main/java/com/kouros/navigation/car/MapView.kt +++ b/common/car/src/main/java/com/kouros/navigation/car/MapView.kt @@ -15,6 +15,8 @@ import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.graphics.Path +import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.rememberVectorPainter import androidx.compose.ui.res.vectorResource @@ -45,7 +47,13 @@ import org.maplibre.spatialk.geojson.Position @Composable -fun cameraState(width: Int, height: Int, position: CameraPosition?, tilt: Double, preview: Boolean): CameraState { +fun cameraState( + width: Int, + height: Int, + position: CameraPosition?, + tilt: Double, + preview: Boolean +): CameraState { val padding = getPaddingValues(width, height, preview) return rememberCameraState( firstPosition = @@ -118,12 +126,13 @@ fun DrawImage(location: Location) { Box( modifier = Modifier + .size(48.dp, 48.dp) .padding(start = 450.dp - 30.dp, top = 350.dp - 30.dp) .drawBehind { with(painter) { draw( size = Size(60F, 60F), - colorFilter = tint + colorFilter = tint, ) } }) @@ -145,7 +154,6 @@ fun DrawImage(location: Location) { drawText(measuredText) } } - .fillMaxSize() ) } diff --git a/common/car/src/main/java/com/kouros/navigation/car/NavigationSession.kt b/common/car/src/main/java/com/kouros/navigation/car/NavigationSession.kt index 46463a3..8a9b3ab 100644 --- a/common/car/src/main/java/com/kouros/navigation/car/NavigationSession.kt +++ b/common/car/src/main/java/com/kouros/navigation/car/NavigationSession.kt @@ -23,9 +23,11 @@ import com.kouros.navigation.car.screen.NavigationScreen import com.kouros.navigation.car.screen.RequestPermissionScreen import com.kouros.navigation.car.screen.SearchScreen import com.kouros.navigation.data.Constants.MAXIMAL_ROUTE_DEVIATION +import com.kouros.navigation.data.Constants.MAXIMAL_SNAP_CORRECTION import com.kouros.navigation.data.Constants.TAG import com.kouros.navigation.data.ObjectBox import com.kouros.navigation.utils.NavigationUtils.snapLocation +import com.kouros.navigation.utils.location import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay @@ -44,7 +46,7 @@ class NavigationSession : Session(), NavigationScreen.Listener { var locationIndex = 0 - val simulate = true + val simulate = false var mLocationListener: LocationListenerCompat = LocationListenerCompat { location: Location? -> updateLocation(location) @@ -160,7 +162,7 @@ class NavigationSession : Session(), NavigationScreen.Listener { updateLocation(location) locationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, - /* minTimeMs= */ 100, + /* minTimeMs= */ 500, /* minDistanceM= */ 0f, mLocationListener ) @@ -179,18 +181,13 @@ class NavigationSession : Session(), NavigationScreen.Listener { fun simulate(location: Location?) { if (routeModel.isNavigating() && locationIndex < routeModel.route.waypoints.size) { coroutineScope.launch { - delay( - 100 - ) + if (locationIndex >= routeModel.route.waypoints.size) { + return@launch + } val loc = routeModel.route.waypoints[locationIndex] val curLocation = Location(LocationManager.GPS_PROVIDER) - if ( locationIndex == 1500) { - curLocation.longitude = loc[0] + 0.003 - curLocation.latitude = loc[1] + 0.003 - } else { - curLocation.longitude = loc[0] - curLocation.latitude = loc[1] - } + curLocation.longitude = loc[0]// + 0.00001 * locationIndex + curLocation.latitude = loc[1] //+ 0.00001 * locationIndex curLocation.speed = 15F update(curLocation) locationIndex += 1 @@ -207,12 +204,22 @@ class NavigationSession : Session(), NavigationScreen.Listener { fun update(location: Location) { if (routeModel.isNavigating()) { + val snapedLocation = snapLocation(location, routeModel.route.maneuverLocations()) + val distance = location.distanceTo(snapedLocation) + println(distance) + if (distance > MAXIMAL_ROUTE_DEVIATION) { + // navigationScreen.calculateNewRoute() + //return + } routeModel.updateLocation(location) navigationScreen.updateTrip() - } - val result = surfaceRenderer.updateLocation(location) - if (!result) { - navigationScreen.stopNavigation() + if (distance < MAXIMAL_SNAP_CORRECTION) { + surfaceRenderer.updateLocation(snapedLocation) + } else { + surfaceRenderer.updateLocation(location) + } + } else { + surfaceRenderer.updateLocation(location) } } diff --git a/common/car/src/main/java/com/kouros/navigation/car/SurfaceRenderer.kt b/common/car/src/main/java/com/kouros/navigation/car/SurfaceRenderer.kt index 5d5d834..6ba6c73 100644 --- a/common/car/src/main/java/com/kouros/navigation/car/SurfaceRenderer.kt +++ b/common/car/src/main/java/com/kouros/navigation/car/SurfaceRenderer.kt @@ -26,6 +26,7 @@ import androidx.savedstate.setViewTreeSavedStateRegistryOwner import com.kouros.navigation.car.navigation.RouteCarModel import com.kouros.navigation.data.Constants import com.kouros.navigation.data.Constants.MAXIMAL_ROUTE_DEVIATION +import com.kouros.navigation.data.Constants.NEXT_STEP_THRESHOLD import com.kouros.navigation.data.Constants.SHOW_THREED_BUILDING import com.kouros.navigation.model.RouteModel import com.kouros.navigation.utils.NavigationUtils.getBooleanKeyValue @@ -189,7 +190,7 @@ class SurfaceRenderer( @Composable fun ShowPosition(cameraState: CameraState, position: CameraPosition?) { - var cameraDuration = duration(position) + val cameraDuration = duration(position) var bearing = position!!.bearing var zoom = position.zoom var target = position.target @@ -197,9 +198,8 @@ class SurfaceRenderer( if (!preview) { DrawImage(lastLocation) } else { - cameraDuration = 3.seconds bearing = 0.0 - zoom = 11.0 + zoom = previewZoom() target = Position(centerLocation.longitude, centerLocation.latitude) localTilt = 0.0 } @@ -224,10 +224,13 @@ class SurfaceRenderer( } private fun duration(position: CameraPosition?): Duration { + if (preview) { + return 3.seconds + } val cameraDuration = if ((lastBearing - position!!.bearing).absoluteValue > 20.0) { - 0.4.seconds + 2.seconds } else { - 1.seconds + 2.seconds } return cameraDuration } @@ -250,31 +253,24 @@ class SurfaceRenderer( } } - fun updateLocation(location: Location) : Boolean { + fun updateLocation(location: Location) { synchronized(this) { if (!preview) { - var snapedLocation = location - var bearing: Double - bearing = cameraPosition.value!!.bearing + var bearing = cameraPosition.value!!.bearing if (routeModel.isNavigating()) { - snapedLocation = snapLocation(location, routeModel.route.maneuverLocations()) bearing = routeModel.currentStep().bearing - if (snapedLocation.longitude == 0.0) { - //reRoute() - return false - } } val zoom = if (!panView) { - calculateZoom(snapedLocation.speed.toDouble()) + calculateZoom(location.speed.toDouble()) } else { cameraPosition.value!!.zoom } - updateCameraPosition(bearing, zoom, Position(snapedLocation.longitude, snapedLocation.latitude)) + updateCameraPosition(bearing, zoom, Position(location.longitude, location.latitude)) lastBearing = cameraPosition.value!!.bearing - lastLocation = snapedLocation + lastLocation = location } else { val bearing = 0.0 - val zoom = 14.0 + val zoom = previewZoom() updateCameraPosition( bearing, zoom, @@ -282,7 +278,6 @@ class SurfaceRenderer( ) } } - return true } private fun updateCameraPosition(bearing: Double, zoom: Double, target: Position) { @@ -310,6 +305,23 @@ class SurfaceRenderer( preview = true } + + private fun previewZoom(): Double { + if (routeModel.isNavigating()) { + when (routeModel.route.distance) { + in 0.0..10.0 -> { + return 14.0 + } + in 10.0..20.0 -> { + return 12.0 + } + in 20.0..30.0 -> { + return 11.0 + } + } + } + return 10.0 + } companion object { private const val TAG = "MapRenderer" diff --git a/common/car/src/main/java/com/kouros/navigation/car/navigation/Gpx.kt b/common/car/src/main/java/com/kouros/navigation/car/navigation/Gpx.kt index 65d139d..691ff92 100644 --- a/common/car/src/main/java/com/kouros/navigation/car/navigation/Gpx.kt +++ b/common/car/src/main/java/com/kouros/navigation/car/navigation/Gpx.kt @@ -1,13 +1,7 @@ package com.kouros.navigation.car.navigation -import android.R -import android.app.Activity import android.location.Location -import android.os.Bundle import android.os.Environment -import android.view.Menu -import android.view.View -import android.widget.TextView import org.xml.sax.SAXException import java.io.File import java.io.FileInputStream diff --git a/common/car/src/main/java/com/kouros/navigation/car/navigation/RouteCarModel.kt b/common/car/src/main/java/com/kouros/navigation/car/navigation/RouteCarModel.kt index 95a68f4..966dc45 100644 --- a/common/car/src/main/java/com/kouros/navigation/car/navigation/RouteCarModel.kt +++ b/common/car/src/main/java/com/kouros/navigation/car/navigation/RouteCarModel.kt @@ -86,11 +86,7 @@ class RouteCarModel() : RouteModel() { when (distanceLeft) { in 0.0..NEXT_STEP_THRESHOLD -> { return null -// if (maneuver.streetNames != null && maneuver.streetNames!!.isNotEmpty()) { -// text = maneuver.streetNames!![0] -// } } - else -> { if (maneuver.streetNames != null && maneuver.streetNames!!.isNotEmpty()) { text = maneuver.streetNames!![0] @@ -118,6 +114,7 @@ class RouteCarModel() : RouteModel() { type = Maneuver.TYPE_STRAIGHT currentTurnIcon = createCarIcon(carContext, R.drawable.ic_turn_name_change) } + ManeuverType.Destination.value, ManeuverType.DestinationRight.value, ManeuverType.DestinationLeft.value, @@ -125,35 +122,51 @@ class RouteCarModel() : RouteModel() { type = Maneuver.TYPE_DESTINATION currentTurnIcon = createCarIcon(carContext, R.drawable.ic_turn_destination) } + ManeuverType.Right.value -> { type = Maneuver.TYPE_TURN_NORMAL_RIGHT currentTurnIcon = createCarIcon(carContext, R.drawable.ic_turn_normal_right) } + ManeuverType.Left.value -> { type = Maneuver.TYPE_TURN_NORMAL_LEFT currentTurnIcon = createCarIcon(carContext, R.drawable.ic_turn_normal_left) } + ManeuverType.RampRight.value -> { type = Maneuver.TYPE_OFF_RAMP_SLIGHT_RIGHT currentTurnIcon = createCarIcon(carContext, R.drawable.ic_turn_slight_right) } + ManeuverType.RampLeft.value -> { type = Maneuver.TYPE_TURN_NORMAL_LEFT currentTurnIcon = createCarIcon(carContext, R.drawable.ic_turn_normal_left) } + ManeuverType.ExitRight.value -> { type = Maneuver.TYPE_TURN_SLIGHT_RIGHT - currentTurnIcon = createCarIcon(carContext, R.drawable.ic_turn_slight_right) + currentTurnIcon = createCarIcon(carContext, R.drawable.ic_turn_slight_right) } ManeuverType.StayRight.value -> { type = Maneuver.TYPE_KEEP_RIGHT currentTurnIcon = createCarIcon(carContext, R.drawable.ic_turn_name_change) } + ManeuverType.StayLeft.value -> { type = Maneuver.TYPE_KEEP_LEFT currentTurnIcon = createCarIcon(carContext, R.drawable.ic_turn_name_change) } + + ManeuverType.RoundaboutEnter.value -> { + type = Maneuver.TYPE_ROUNDABOUT_ENTER_CCW + currentTurnIcon = createCarIcon(carContext, R.drawable.ic_roundabout_ccw) + } + + ManeuverType.RoundaboutExit.value -> { + type = Maneuver.TYPE_ROUNDABOUT_EXIT_CCW + currentTurnIcon = createCarIcon(carContext, R.drawable.ic_roundabout_ccw) + } } maneuverType = type return Pair(type, currentTurnIcon) diff --git a/common/car/src/main/java/com/kouros/navigation/car/screen/NavigationScreen.kt b/common/car/src/main/java/com/kouros/navigation/car/screen/NavigationScreen.kt index 8ba3fe3..f3394d2 100644 --- a/common/car/src/main/java/com/kouros/navigation/car/screen/NavigationScreen.kt +++ b/common/car/src/main/java/com/kouros/navigation/car/screen/NavigationScreen.kt @@ -5,6 +5,8 @@ import android.content.Intent import android.location.Location import android.location.LocationManager import android.os.CountDownTimer +import android.os.Handler +import android.os.Looper import androidx.car.app.CarContext import androidx.car.app.Screen import androidx.car.app.model.Action @@ -46,6 +48,8 @@ class NavigationScreen( } var currentNavigationLocation = Location(LocationManager.GPS_PROVIDER) + + var calculateNewRoute = false val vieModel = ViewModel(NavigationRepository()) val observer = Observer { route -> if (route.isNotEmpty()) { @@ -80,7 +84,11 @@ class NavigationScreen( .build() ) return if (routeModel.isNavigating()) { - getNavigationTemplate(actionStripBuilder) + if (calculateNewRoute) { + getNavigationLoadingTemplate(actionStripBuilder) + } else { + getNavigationTemplate(actionStripBuilder) + } } else { getNavigationEndTemplate(actionStripBuilder) } @@ -155,6 +163,14 @@ class NavigationScreen( } } + fun getNavigationLoadingTemplate(actionStripBuilder: ActionStrip.Builder): NavigationTemplate { + return NavigationTemplate.Builder() + .setNavigationInfo(RoutingInfo.Builder().setLoading(true).build()) + .setActionStrip(actionStripBuilder.build()) + .setBackgroundColor(CarColor.SECONDARY) + .build() + } + fun getRoutingInfo(): RoutingInfo { var currentDistance = routeModel.currentDistance val displayUnit = if (currentDistance > 1000.0) { @@ -281,6 +297,21 @@ class NavigationScreen( invalidate() } + fun calculateNewRoute() { + calculateNewRoute = true + invalidate() + val mainThreadhandler = Handler(carContext.mainLooper) + mainThreadhandler.post { + object : CountDownTimer(5000, 1000) { + override fun onTick(millisUntilFinished: Long) { } + override fun onFinish() { + calculateNewRoute = false + stopNavigation() + } + }.start() + } + } + fun reRoute() { NavigationMessage(carContext).createAlert() vieModel.loadRoute(surfaceRenderer.lastLocation, currentNavigationLocation) @@ -293,4 +324,4 @@ class NavigationScreen( } invalidate() } -} \ No newline at end of file +} diff --git a/common/car/src/main/java/com/kouros/navigation/car/screen/SearchScreen.kt b/common/car/src/main/java/com/kouros/navigation/car/screen/SearchScreen.kt index ca57a6a..5384c54 100644 --- a/common/car/src/main/java/com/kouros/navigation/car/screen/SearchScreen.kt +++ b/common/car/src/main/java/com/kouros/navigation/car/screen/SearchScreen.kt @@ -17,7 +17,7 @@ import com.kouros.navigation.data.Category import com.kouros.navigation.data.Constants import com.kouros.navigation.data.NavigationRepository import com.kouros.navigation.data.Place -import com.kouros.navigation.data.nominatim.Search +import com.kouros.navigation.data.nominatim.SearchResult import com.kouros.navigation.model.ViewModel @@ -34,9 +34,9 @@ class SearchScreen( Category(id = Constants.CONTACTS, name = carContext.getString(R.string.contacts)) ) - lateinit var searchResult: Search + lateinit var searchResult: List - val observer = Observer { newSearch -> + val observer = Observer> { newSearch -> println(newSearch) searchResult = newSearch invalidate() @@ -93,13 +93,9 @@ class SearchScreen( return SearchTemplate.Builder( object : SearchCallback { - override fun onSearchTextChanged(searchText: String) { - //doSearch(searchText, searchItemListBuilder) - } - override fun onSearchSubmitted(searchTerm: String) { isSearchComplete = true - viewModel.searchPlaces(searchTerm) + viewModel.searchPlaces(searchTerm, location) } }) .setHeaderAction(Action.BACK) @@ -111,15 +107,9 @@ class SearchScreen( @SuppressLint("DefaultLocale") fun doSearch(searchItemListBuilder: ItemList.Builder) { searchResult.forEach { - println(it.displayName) - //val name: String = address.getAddressLine(0) - //addressLocation.latitude = address.latitude - //adressLocation.longitude = address.longitude - //val distance = location.distanceTo(addressLocation) - //val dist = String.format("%.1f", (distance / 1000)) searchItemListBuilder.addItem( Row.Builder() - .setTitle(it.displayName) + .setTitle("${(it.distance/1000).toInt()} km ${it.displayName} ") .setOnClickListener { val place = Place( name = it.displayName, @@ -127,7 +117,8 @@ class SearchScreen( longitude = it.lon.toDouble(), street = it.address.road, city = it.address.city, - postalCode = it.address.postcode + postalCode = it.address.postcode, + distance = it.distance ) setResult(place) finish() @@ -136,8 +127,6 @@ class SearchScreen( .build() ) } - - // val itemList = searchItemListBuilder.build() invalidate() } } \ No newline at end of file diff --git a/common/data/objectbox-models/default.json b/common/data/objectbox-models/default.json index 90a8be7..410e39e 100644 --- a/common/data/objectbox-models/default.json +++ b/common/data/objectbox-models/default.json @@ -5,7 +5,7 @@ "entities": [ { "id": "3:3556253001994555353", - "lastPropertyId": "10:2074102010889685023", + "lastPropertyId": "11:1275950563592034592", "name": "Place", "properties": [ { @@ -53,6 +53,11 @@ "id": "10:2074102010889685023", "name": "distance", "type": 7 + }, + { + "id": "11:1275950563592034592", + "name": "lastDate", + "type": 6 } ], "relations": [] diff --git a/common/data/objectbox-models/default.json.bak b/common/data/objectbox-models/default.json.bak index fb11a20..887b252 100644 --- a/common/data/objectbox-models/default.json.bak +++ b/common/data/objectbox-models/default.json.bak @@ -5,7 +5,7 @@ "entities": [ { "id": "3:3556253001994555353", - "lastPropertyId": "10:2074102010889685023", + "lastPropertyId": "11:1275950563592034592", "name": "Place", "properties": [ { @@ -53,32 +53,11 @@ "id": "10:2074102010889685023", "name": "distance", "type": 7 - } - ], - "relations": [] - }, - { - "id": "4:4849917137448238840", - "lastPropertyId": "3:6908702166041138446", - "name": "ObjectBoxTile", - "properties": [ - { - "id": "1:6365540590424804057", - "name": "id", - "type": 6, - "flags": 1 }, { - "id": "2:8979494032513344145", - "name": "key", - "indexId": "3:8164654097637798551", - "type": 9, - "flags": 2048 - }, - { - "id": "3:6908702166041138446", - "name": "bitmap", - "type": 23 + "id": "11:1275950563592034592", + "name": "lastDate", + "type": 10 } ], "relations": [] @@ -92,11 +71,13 @@ "modelVersionParserMinimum": 5, "retiredEntityUids": [ 5232739161494262087, - 1670248357005659634 + 1670248357005659634, + 4849917137448238840 ], "retiredIndexUids": [ 1988419626350568402, - 5426976851182536573 + 5426976851182536573, + 8164654097637798551 ], "retiredPropertyUids": [ 2083347946807922223, @@ -106,7 +87,10 @@ 3637730979227083476, 8954406503424388478, 7467083398837280132, - 6885676442906238720 + 6885676442906238720, + 6365540590424804057, + 8979494032513344145, + 6908702166041138446 ], "retiredRelationUids": [], "version": 1 diff --git a/common/data/src/main/java/com/kouros/navigation/data/Color.kt b/common/data/src/main/java/com/kouros/navigation/data/Color.kt index 38520a3..cc61e1f 100644 --- a/common/data/src/main/java/com/kouros/navigation/data/Color.kt +++ b/common/data/src/main/java/com/kouros/navigation/data/Color.kt @@ -2,6 +2,6 @@ package com.kouros.navigation.data import androidx.compose.ui.graphics.Color -val NavigationColor = Color(0xFF1965D9) +val NavigationColor = Color(0xFF094DB6) -val RouteColor = Color(0xFF2E75E1) +val RouteColor = Color(0xFF5582D0) diff --git a/common/data/src/main/java/com/kouros/navigation/data/Data.kt b/common/data/src/main/java/com/kouros/navigation/data/Data.kt index 54b4862..53c5595 100644 --- a/common/data/src/main/java/com/kouros/navigation/data/Data.kt +++ b/common/data/src/main/java/com/kouros/navigation/data/Data.kt @@ -22,6 +22,8 @@ import android.net.Uri import io.objectbox.annotation.Entity import io.objectbox.annotation.Id import kotlinx.serialization.Serializable +import java.time.LocalDate +import java.util.Date data class Category( val id: String, @@ -41,7 +43,8 @@ data class Place( var street: String? = null, var distance: Float = 0F, @Transient - var avatar: Uri? = null + var avatar: Uri? = null, + var lastDate: Long = 0 ) data class ContactData( @@ -148,7 +151,9 @@ object Constants { const val NEXT_STEP_THRESHOLD = 100.0 - const val MAXIMAL_ROUTE_DEVIATION = 70.0 + const val MAXIMAL_SNAP_CORRECTION = 50.0 + + const val MAXIMAL_ROUTE_DEVIATION = 100.0 } diff --git a/common/data/src/main/java/com/kouros/navigation/data/Route.kt b/common/data/src/main/java/com/kouros/navigation/data/Route.kt index c7d5962..0e5ce48 100644 --- a/common/data/src/main/java/com/kouros/navigation/data/Route.kt +++ b/common/data/src/main/java/com/kouros/navigation/data/Route.kt @@ -92,7 +92,11 @@ data class Route ( fun maneuverLocations(): List { val beginShapeIndex = currentManeuver().beginShapeIndex - val endShapeIndex = currentManeuver().endShapeIndex + val endShapeIndex = if (currentManeuver().endShapeIndex >= waypoints.size) { + waypoints.size + } else { + currentManeuver().endShapeIndex + 1 + } return pointLocations.subList(beginShapeIndex, endShapeIndex) } diff --git a/common/data/src/main/java/com/kouros/navigation/data/nominatim/SearchResult.kt b/common/data/src/main/java/com/kouros/navigation/data/nominatim/SearchResult.kt index b5e9a60..4bb7043 100644 --- a/common/data/src/main/java/com/kouros/navigation/data/nominatim/SearchResult.kt +++ b/common/data/src/main/java/com/kouros/navigation/data/nominatim/SearchResult.kt @@ -25,6 +25,6 @@ data class SearchResult( @SerializedName("address") var address: Address, @SerializedName("name") var name: String = "", @SerializedName("display_name") var displayName: String = "", - @SerializedName("boundingbox") var boundingbox: ArrayList = arrayListOf() - + @SerializedName("boundingbox") var boundingbox: ArrayList = arrayListOf(), + var distance : Float = 0.0F ) \ No newline at end of file diff --git a/common/data/src/main/java/com/kouros/navigation/data/valhalla/Maneuvers.kt b/common/data/src/main/java/com/kouros/navigation/data/valhalla/Maneuvers.kt index a446fa6..830917a 100644 --- a/common/data/src/main/java/com/kouros/navigation/data/valhalla/Maneuvers.kt +++ b/common/data/src/main/java/com/kouros/navigation/data/valhalla/Maneuvers.kt @@ -22,11 +22,12 @@ data class Maneuvers( @SerializedName("length") var length: Double = 0.0, @SerializedName("cost") var cost: Double = 0.0, @SerializedName("verbal_multi_cue") var verbalMultiCue: Boolean = false, - @SerializedName("begin_shape_index") var beginShapeIndex: Int, - @SerializedName("end_shape_index") var endShapeIndex: Int, + @SerializedName("begin_shape_index") var beginShapeIndex: Int = 0, + @SerializedName("end_shape_index") var endShapeIndex: Int = 0, @SerializedName("highway") var highway: Boolean = false, @SerializedName("sign") var sign: Sign = Sign(), @SerializedName("travel_mode") var travelMode: String = "", @SerializedName("travel_type") var travelType: String = "", + @SerializedName("roundabout_exit_count") var roundaboutExitCount: Int = 0 ) \ No newline at end of file diff --git a/common/data/src/main/java/com/kouros/navigation/model/RouteModel.kt b/common/data/src/main/java/com/kouros/navigation/model/RouteModel.kt index 6e87ee7..6512624 100644 --- a/common/data/src/main/java/com/kouros/navigation/model/RouteModel.kt +++ b/common/data/src/main/java/com/kouros/navigation/model/RouteModel.kt @@ -27,7 +27,7 @@ open class RouteModel() { /* current shapeIndex */ - private var currentShapeIndex = 0 + private var currentShapeIndex = 0 var distanceToStepEnd = 0F @@ -63,7 +63,7 @@ open class RouteModel() { fun updateLocation(location: Location) { var nearestDistance = 100000.0f - route.currentManeuverIndex = -1 + route.currentManeuverIndex = -1 // find maneuver for ((i, maneuver) in route.maneuvers.withIndex()) { val beginShapeIndex = maneuver.beginShapeIndex @@ -83,8 +83,15 @@ open class RouteModel() { if (maneuver.streetNames != null && maneuver.streetNames.isNotEmpty()) { text = maneuver.streetNames[0] } - val curLocation = location(route.pointLocations[currentShapeIndex].latitude(), route.pointLocations[currentShapeIndex].longitude()) - val nextLocation = location(route.pointLocations[currentShapeIndex+1].latitude(), route.pointLocations[currentShapeIndex+1].longitude()) + // TODO: +1 check + val curLocation = location( + route.pointLocations[currentShapeIndex].latitude(), + route.pointLocations[currentShapeIndex].longitude() + ) + val nextLocation = location( + route.pointLocations[currentShapeIndex + 1].latitude(), + route.pointLocations[currentShapeIndex + 1].longitude() + ) bearing = curLocation.bearingTo(nextLocation) val distanceStepLeft = leftStepDistance() * 1000 when (distanceStepLeft) { @@ -120,17 +127,14 @@ open class RouteModel() { distanceToStepEnd = 0F val loc1 = Location(LocationManager.GPS_PROVIDER) val loc2 = Location(LocationManager.GPS_PROVIDER) - loc1.longitude = route.waypoints[i][0] - loc1.latitude = route.waypoints[i][1] - loc2.longitude = route.waypoints[i + 1][0] - loc2.latitude = route.waypoints[i + 1][1] - bearing = loc1.bearingTo(loc2).absoluteValue - for (j in i + 1..endShapeIndex) { - loc1.longitude = route.waypoints[j - 1][0] - loc1.latitude = route.waypoints[j - 1][1] - loc2.longitude = route.waypoints[j][0] - loc2.latitude = route.waypoints[j][1] - distanceToStepEnd += loc1.distanceTo(loc2) + if (i + 1 < route.waypoints.size) { + for (j in i + 1..endShapeIndex) { + loc1.longitude = route.waypoints[j - 1][0] + loc1.latitude = route.waypoints[j - 1][1] + loc2.longitude = route.waypoints[j][0] + loc2.latitude = route.waypoints[j][1] + distanceToStepEnd += loc1.distanceTo(loc2) + } } } } diff --git a/common/data/src/main/java/com/kouros/navigation/model/ViewModel.kt b/common/data/src/main/java/com/kouros/navigation/model/ViewModel.kt index 54abc70..a0b31e0 100644 --- a/common/data/src/main/java/com/kouros/navigation/model/ViewModel.kt +++ b/common/data/src/main/java/com/kouros/navigation/model/ViewModel.kt @@ -13,10 +13,14 @@ import com.kouros.navigation.data.ObjectBox.boxStore import com.kouros.navigation.data.Place import com.kouros.navigation.data.Place_ import com.kouros.navigation.data.nominatim.Search +import com.kouros.navigation.data.nominatim.SearchResult import com.kouros.navigation.utils.location import io.objectbox.kotlin.boxFor import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.ZoneOffset class ViewModel(private val repository: NavigationRepository) : ViewModel() { @@ -32,8 +36,8 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() { MutableLiveData>() } - val searchPlaces: MutableLiveData by lazy { - MutableLiveData() + val searchPlaces: MutableLiveData> by lazy { + MutableLiveData>() } val contactAddress: MutableLiveData> by lazy { @@ -44,15 +48,20 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() { fun loadPlaces(location: Location) { viewModelScope.launch(Dispatchers.IO) { try { - val pl = mutableListOf() val placeBox = boxStore.boxFor(Place::class) - pl.addAll(placeBox.all) - for (place in pl) { + val query = placeBox + .query(Place_.name.notEqual("")) + .orderDesc(Place_.lastDate) + .build() + val results = query.find() + query.close() + for (place in results) { val plLocation = location(place.latitude, place.longitude) val distance = repository.getRouteDistance(location, plLocation) place.distance = distance.toFloat() + println(place.lastDate) } - places.postValue(pl) + places.postValue(results) } catch (e: Exception) { e.printStackTrace() } @@ -121,12 +130,21 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() { } } - fun searchPlaces(search: String) { + fun searchPlaces(search: String, location: Location) { viewModelScope.launch(Dispatchers.IO) { val placesJson = repository.searchPlaces(search) val gson = GsonBuilder().serializeNulls().create() val places = gson.fromJson(placesJson, Search::class.java) - searchPlaces.postValue(places) + val distPlaces = mutableListOf() + places.forEach { + val plLocation = + location(latitude = it.lat.toDouble(), longitude = it.lon.toDouble()) + val distance = plLocation.distanceTo(location) + it.distance = distance + distPlaces.add(it) + } + val sortedList = distPlaces.sortedWith(compareBy({ it.distance })) + searchPlaces.postValue(sortedList) } } @@ -140,9 +158,12 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() { .build() val results = query.find() query.close() - if (results.isEmpty()) { - placeBox.put(place) + if (results.isNotEmpty()) { + placeBox.remove(results.first()) } + val current = LocalDateTime.now(ZoneOffset.UTC) + place.lastDate = current.atZone(ZoneOffset.UTC).toEpochSecond() + placeBox.put(place) } catch (e: Exception) { e.printStackTrace() } @@ -160,7 +181,7 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() { val results = query.find() query.close() if (results.isNotEmpty()) { - placeBox.remove(place) + placeBox.remove(results.first()) } } catch (e: Exception) { e.printStackTrace() diff --git a/common/data/src/main/java/com/kouros/navigation/utils/NavigationUtils.kt b/common/data/src/main/java/com/kouros/navigation/utils/NavigationUtils.kt index 5a16d57..9a03b66 100644 --- a/common/data/src/main/java/com/kouros/navigation/utils/NavigationUtils.kt +++ b/common/data/src/main/java/com/kouros/navigation/utils/NavigationUtils.kt @@ -56,21 +56,16 @@ object NavigationUtils { apply() } } - fun snapLocation(location: Location, stepCoordinates: List): Location { + fun snapLocation(location: Location, stepCoordinates: List) : Location { + val newLocation = location(latitude = location.latitude, longitude = location.longitude) val oldPoint = Point.fromLngLat(location.longitude, location.latitude) - val oldLocation = location(location.latitude, location.longitude) if (stepCoordinates.size > 1) { val pointFeature = TurfMisc.nearestPointOnLine(oldPoint, stepCoordinates) val point = pointFeature.geometry() as Point - location.latitude = point.latitude() - location.longitude = point.longitude() - val distance = oldLocation.distanceTo(location) - if (distance > MAXIMAL_ROUTE_DEVIATION) { - println("Distance to big") - return location(0.0, 0.0) - } + newLocation.latitude = point.latitude() + newLocation.longitude = point.longitude() } - return location + return newLocation } fun decodePolyline(encoded: String, vararg precisionOptional: Int): List> { diff --git a/settings.gradle.kts b/settings.gradle.kts index 2553d80..e8a721d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -30,7 +30,3 @@ include( ) - -include(":common:automotive") -include(":app:automotive") -include(":automotive")