Skip to content

Commit 9e15d4c

Browse files
committed
at least it works
1 parent 99cd4ad commit 9e15d4c

File tree

2 files changed

+126
-13
lines changed

2 files changed

+126
-13
lines changed
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package com.mapbox.navigation.core.trip.service
2+
3+
import android.util.Log
4+
import androidx.test.ext.junit.runners.AndroidJUnit4
5+
import androidx.test.platform.app.InstrumentationRegistry
6+
import com.mapbox.api.directions.v5.models.DirectionsRoute
7+
import com.mapbox.common.LogConfiguration
8+
import com.mapbox.common.LoggingLevel
9+
import com.mapbox.navigation.base.options.NavigationOptions
10+
import com.mapbox.navigation.base.route.NavigationRoute
11+
import com.mapbox.navigation.base.route.RouterOrigin
12+
import com.mapbox.navigation.base.route.toNavigationRoute
13+
import com.mapbox.navigation.core.MapboxNavigationProvider
14+
import com.mapbox.navigation.core.navigator.toFixLocation
15+
import com.mapbox.navigation.core.replay.history.ReplayEventUpdateLocation
16+
import com.mapbox.navigation.core.replay.mapToLocation
17+
import com.mapbox.navigation.core.replay.route.ReplayRouteMapper
18+
import com.mapbox.navigation.core.test.R
19+
import com.mapbox.navigation.navigator.internal.MapboxNativeNavigator
20+
import com.mapbox.navigation.navigator.internal.MapboxNativeNavigatorImpl
21+
import com.mapbox.navigator.NavigationStatus
22+
import com.mapbox.navigator.NavigationStatusOrigin
23+
import com.mapbox.navigator.NavigatorObserver
24+
import com.mapbox.navigator.RouteState
25+
import com.mapbox.navigator.SetRoutesReason
26+
import kotlinx.coroutines.Dispatchers
27+
import kotlinx.coroutines.ExperimentalCoroutinesApi
28+
import kotlinx.coroutines.async
29+
import kotlinx.coroutines.channels.awaitClose
30+
import kotlinx.coroutines.flow.Flow
31+
import kotlinx.coroutines.flow.callbackFlow
32+
import kotlinx.coroutines.flow.collect
33+
import kotlinx.coroutines.flow.filter
34+
import kotlinx.coroutines.flow.first
35+
import kotlinx.coroutines.flow.map
36+
import kotlinx.coroutines.launch
37+
import kotlinx.coroutines.runBlocking
38+
import org.junit.Assert.assertEquals
39+
import org.junit.Assert.assertTrue
40+
import org.junit.Test
41+
import org.junit.runner.RunWith
42+
43+
@RunWith(AndroidJUnit4::class)
44+
class ArtificialDriverTest {
45+
46+
@Test
47+
fun testFollowingRoute() = runBlocking<Unit>(Dispatchers.Main) {
48+
LogConfiguration.setLoggingLevel(LoggingLevel.DEBUG)
49+
getNativeNavigator { nativeNavigator ->
50+
val testRoute = getTestRoute()
51+
val replayRouteMapper = ReplayRouteMapper()
52+
val events = replayRouteMapper.mapDirectionsRouteGeometry(testRoute.directionsRoute)
53+
val result = nativeNavigator.setRoutes(testRoute, reason = SetRoutesReason.NEW_ROUTE)
54+
assertTrue("result is $result", result.isValue)
55+
val states = mutableListOf<NavigationStatus>()
56+
val statusTracking = launch {
57+
nativeNavigator.statusUpdates().collect {
58+
states.add(it.second)
59+
}
60+
}
61+
for (event in events.filterIsInstance<ReplayEventUpdateLocation>()) {
62+
val location = event.location.mapToLocation(event.eventTimestamp)
63+
assertTrue(nativeNavigator.updateLocation(location.toFixLocation()))
64+
}
65+
statusTracking.cancel()
66+
assertTrue(states.all { it.routeState == RouteState.TRACKING || it.routeState == RouteState.COMPLETE })
67+
}
68+
}
69+
70+
@OptIn(ExperimentalCoroutinesApi::class)
71+
fun MapboxNativeNavigator.statusUpdates(): Flow<Pair<NavigationStatusOrigin, NavigationStatus>> {
72+
return callbackFlow {
73+
val observer = NavigatorObserver { origin, status ->
74+
Log.d("vadzim-debug", "$origin, $status")
75+
this.trySend(Pair(origin, status))
76+
}
77+
addNavigatorObserver(observer)
78+
awaitClose {
79+
removeNavigatorObserver(observer)
80+
}
81+
}
82+
}
83+
84+
private suspend fun getNativeNavigator(block: suspend (MapboxNativeNavigator) -> Unit) {
85+
val context = InstrumentationRegistry.getInstrumentation().targetContext
86+
val mapboxNavigation = MapboxNavigationProvider.create(
87+
NavigationOptions.Builder(context)
88+
.accessToken(context.getString(R.string.mapbox_access_token))
89+
.build()
90+
)
91+
block(MapboxNativeNavigatorImpl)
92+
mapboxNavigation.onDestroy()
93+
}
94+
95+
private fun getTestRoute(): NavigationRoute {
96+
val context = InstrumentationRegistry.getInstrumentation().targetContext
97+
return DirectionsRoute.fromJson(
98+
context.resources.openRawResource(R.raw.multileg_route)
99+
.readBytes().decodeToString()
100+
).toNavigationRoute(RouterOrigin.Custom())
101+
}
102+
}

libnavigation-core/src/main/java/com/mapbox/navigation/core/replay/ReplayLocationEngine.kt

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import com.mapbox.android.core.location.LocationEngineCallback
1010
import com.mapbox.android.core.location.LocationEngineRequest
1111
import com.mapbox.android.core.location.LocationEngineResult
1212
import com.mapbox.navigation.core.replay.history.ReplayEventBase
13+
import com.mapbox.navigation.core.replay.history.ReplayEventLocation
1314
import com.mapbox.navigation.core.replay.history.ReplayEventUpdateLocation
1415
import com.mapbox.navigation.core.replay.history.ReplayEventsObserver
1516
import java.util.Date
@@ -98,15 +99,7 @@ class ReplayLocationEngine(
9899
private fun replayLocation(event: ReplayEventUpdateLocation) {
99100
val timeOffset = mapboxReplayer.eventRealtimeOffset(event.eventTimestamp)
100101
val eventLocation = event.location
101-
val location = Location(eventLocation.provider)
102-
location.longitude = eventLocation.lon
103-
location.latitude = eventLocation.lat
104-
location.time = Date().time + timeOffset.secToMillis()
105-
location.elapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos() + timeOffset.secToNanos()
106-
eventLocation.accuracyHorizontal?.toFloat()?.let { location.accuracy = it }
107-
eventLocation.bearing?.toFloat()?.let { location.bearing = it }
108-
eventLocation.altitude?.let { location.altitude = it }
109-
eventLocation.speed?.toFloat()?.let { location.speed = it }
102+
val location = eventLocation.mapToLocation(timeOffset)
110103
val locationEngineResult = LocationEngineResult.create(location)
111104
lastLocationEngineResult = locationEngineResult
112105

@@ -116,9 +109,27 @@ class ReplayLocationEngine(
116109
}
117110

118111
private companion object {
119-
private const val MILLIS_PER_SECOND = 1000.0
120-
private const val NANOS_PER_SECOND = 1e+9
121-
private fun Double.secToMillis(): Long = (this * MILLIS_PER_SECOND).toLong()
122-
private fun Double.secToNanos(): Long = (this * NANOS_PER_SECOND).toLong()
112+
113+
123114
}
124115
}
116+
117+
private const val MILLIS_PER_SECOND = 1000.0
118+
private const val NANOS_PER_SECOND = 1e+9
119+
private fun Double.secToMillis(): Long = (this * MILLIS_PER_SECOND).toLong()
120+
private fun Double.secToNanos(): Long = (this * NANOS_PER_SECOND).toLong()
121+
122+
internal fun ReplayEventLocation.mapToLocation(
123+
timeOffset: Double
124+
): Location {
125+
val location = Location(provider)
126+
location.longitude = lon
127+
location.latitude = lat
128+
location.time = Date().time + timeOffset.secToMillis()
129+
location.elapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos() + timeOffset.secToNanos()
130+
accuracyHorizontal?.toFloat()?.let { location.accuracy = it }
131+
bearing?.toFloat()?.let { location.bearing = it }
132+
altitude?.let { location.altitude = it }
133+
speed?.toFloat()?.let { location.speed = it }
134+
return location
135+
}

0 commit comments

Comments
 (0)