[MapDataCollect]高精车采逻辑优化

This commit is contained in:
renwj
2022-03-24 11:10:44 +08:00
parent e1ccfc755c
commit 31e4ee1681
11 changed files with 378 additions and 8 deletions

View File

@@ -0,0 +1,62 @@
package com.mogo.functions.test
import androidx.annotation.VisibleForTesting
import androidx.test.core.app.ActivityScenario
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import com.mogo.eagle.core.function.call.map.CallerMapDataCollectorManager
import com.mogo.eagle.core.function.hmi.ui.MoGoHmiFragment
import com.mogo.eagle.core.function.main.MainLauncherActivity
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.suspendCancellableCoroutine
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeUnit.MILLISECONDS
@RunWith(AndroidJUnit4::class)
@LargeTest
class MapDataCollectTest {
lateinit var launch: ActivityScenario<MainLauncherActivity>
@Before
fun before() {
launch = ActivityScenario.launch(MainLauncherActivity::class.java)
}
@Test
fun testTaskSent() = runBlocking {
ensureMoGoHmiFragmentShow()
delay(TimeUnit.SECONDS.toMillis(3))
CallerMapDataCollectorManager.setIsInit()
delay(TimeUnit.HOURS.toMillis(1))
}
private suspend fun ensureMoGoHmiFragmentShow(): MoGoHmiFragment = suspendCancellableCoroutine {
launch.onActivity { itx ->
val executor = Executors.newSingleThreadScheduledExecutor()
executor.scheduleAtFixedRate({
var find =
itx.supportFragmentManager.fragments.find { it is MoGoHmiFragment } as? MoGoHmiFragment
while (find == null) {
find =
itx.supportFragmentManager.fragments.find { it is MoGoHmiFragment } as? MoGoHmiFragment
}
while (!find.isResumed) {
Thread.sleep(500)
}
it.resumeWith(Result.success(find))
try {
Thread.sleep(500)
executor.shutdownNow()
} catch (e: Throwable) {
e.printStackTrace()
}
}, 50, 500, MILLISECONDS)
}
}
}

View File

@@ -144,6 +144,7 @@ ext {
mogomap : "com.mogo.map:mogo-map:${MOGO_MAP_VERSION}",
mogomapapi : "com.mogo.map:mogo-map-api:${MOGO_MAP_API_VERSION}",
mogocustommap : "com.zhidaoauto.machine:map:${MAP_SDK_VERSION}",
mogocustommapoperational : "com.zhidaoauto.map:operational:${MAP_SDK_OPERATION_VERSION}",
modulecommon : "com.mogo.module:module-common:${MOGO_MODULE_COMMON_VERSION}",
modulemap : "com.mogo.module:module-map:${MOGO_MODULE_MAP_VERSION}",

View File

@@ -14,11 +14,13 @@ import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_
import com.mogo.eagle.core.data.trafficlight.TrafficLightResult
import com.mogo.eagle.core.data.trafficlight.toTrafficLightDetail
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotProvider
import com.mogo.eagle.core.function.api.map.collect.IMoGoMapDataCollectProvider
import com.mogo.eagle.core.function.autopilot.adapter.MoGoAdasListenerImpl
import com.mogo.eagle.core.function.autopilot.adapter.MoGoAdasMsgConnectStatusListenerImpl
import com.mogo.eagle.core.function.autopilot.adapter.MoGoHandAdasMsgManager
import com.mogo.eagle.core.function.autopilot.server.AsyncDataToAutopilotServer
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.function.call.map.CallerMapDataCollectorManager
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.eagle.core.utilcode.mogo.storage.SharedPrefsMgr
import com.mogo.eagle.core.utilcode.util.ThreadUtils
@@ -46,7 +48,7 @@ import java.util.concurrent.TimeUnit
*/
@Route(path = MogoServicePaths.PATH_AUTO_PILOT)
class MoGoAutopilotProvider :
IMoGoAutopilotProvider {
IMoGoAutopilotProvider, IMoGoMapDataCollectProvider.OnMapCollectCmdListener {
private val TAG = "MoGoAutoPilotProvider"
private var mContext: Context? = null
@@ -61,6 +63,8 @@ class MoGoAutopilotProvider :
CupidLogUtils.setEnableLog(false)
// TODO 临时方案根据不同的身份标识连接不同的工控机IP
if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)) {// 司机
// 注册地图采集功能
CallerMapDataCollectorManager.registerOnMapCollectTaskListener(this)
// "192.168.1.102"
val options = AdasOptions.Builder()
.setIpcConnectionMode(AdasOptions.IPC_CONNECTION_MODE.FIXATION)
@@ -206,6 +210,16 @@ class MoGoAutopilotProvider :
}, 1000, TimeUnit.MILLISECONDS)
}
override fun onMapCollectStart(cmdId: Int, cmdTime: Long) {
val result = recordPackage(2, cmdId)
CallerLogger.d("$M_ADAS_IMPL$TAG", "开始记录包: [$cmdId, $result]")
}
override fun onMapCollectEnd(cmdId: Int, cmdTime: Long) {
val result = stopRecord(2, cmdId)
CallerLogger.d("$M_ADAS_IMPL$TAG", "结束记录包: [$cmdId, $result]")
}
override fun startAutoPilot(controlParameters: AutopilotControlParameters) {
if (AdasManager.getInstance().ipcConnectionStatus == Constants.IPC_CONNECTION_STATUS.CONNECTED) {
AdasManager.getInstance().sendAutoPilotModeReq(1, 1, controlParameters.toRouteInfo())
@@ -262,6 +276,7 @@ class MoGoAutopilotProvider :
}
override fun onDestroy() {
CallerMapDataCollectorManager.unRegisterOnMapCollectTaskListener(this)
}
override fun setAutoPilotSpeed(speed: Int): Boolean {

View File

@@ -30,6 +30,7 @@ import com.mogo.eagle.core.function.api.hmi.warning.IMoGoWarningStatusListener
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotIdentifyListenerManager
import com.mogo.eagle.core.function.call.check.CallerCheckManager
import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager
import com.mogo.eagle.core.function.call.map.CallerMapDataCollectorManager
import com.mogo.eagle.core.function.call.monitor.CallerMonitorManager
import com.mogo.eagle.core.function.hmi.R
import com.mogo.eagle.core.function.hmi.WaringConst
@@ -41,14 +42,12 @@ import com.mogo.eagle.core.function.hmi.ui.camera.CameraListView
import com.mogo.eagle.core.function.hmi.ui.notice.NoticeBannerView
import com.mogo.eagle.core.function.hmi.ui.notice.NoticeNormalBannerView
import com.mogo.eagle.core.function.hmi.ui.setting.DebugSettingView
import com.mogo.eagle.core.function.hmi.ui.tools.AdUpgradeDialog
import com.mogo.eagle.core.function.hmi.ui.tools.AutoPilotAndCheckView
import com.mogo.eagle.core.function.hmi.ui.widget.V2XNotificationView
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_HMI
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.mogo.eagle.core.utilcode.util.Utils
import com.mogo.module.common.enums.EventTypeEnum
import kotlinx.android.synthetic.main.fragment_hmi.*
import kotlinx.coroutines.*
@@ -149,9 +148,17 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
}
@OptIn(ExperimentalCoroutinesApi::class)
override fun onAutopilotRecordResult(record: RecordPanelOuterClass.RecordPanel) {
if (HmiBuildConfig.isShowBadCaseView && record.type == 1 && record.stat == 100) {
CallerDevaToolsManager.onReceiveBadCaseRecord(record)
override fun onAutopilotRecordResult(recordPanel: RecordPanelOuterClass.RecordPanel) {
if (HmiBuildConfig.isShowBadCaseView && recordPanel.type == 1 && recordPanel.stat == 100) {
CallerDevaToolsManager.onReceiveBadCaseRecord(recordPanel)
}
if (recordPanel.type == 2 && (
recordPanel.stat == 101 || //工控机采集完成-被动完成
recordPanel.stat == 100 || //工控机采集完成-主动完成
recordPanel.stat == 102 || //工控机达到最大采集时长
recordPanel.stat == 103) //工控机磁盘满了
) {
CallerMapDataCollectorManager.finish(recordPanel.id, recordPanel.stat, "", recordPanel.filename ?: "", recordPanel.note ?: "")
}
}

View File

@@ -349,6 +349,12 @@ public abstract class MainMoGoApplication extends AbsMogoApplication {
// 绑定车辆
MogoModulePaths.addModuleFunctionServer(new MogoModule(MogoServicePaths.PATH_BINDING_CAR, "IMoGoBindingcarProvider"));
// 司机身份专属模块
if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)) {
// 地图数据收集模块
MogoModulePaths.addModuleFunctionServer(new MogoModule(MogoServicePaths.PATH_MAP_DATA_COLLECT_PROVIDER, "MoGoMapDataCollector"));
}
if (!DebugConfig.isLauncher()) {
PersistentManager
.getInstance().initManager(this);

View File

@@ -51,6 +51,8 @@ dependencies {
kapt rootProject.ext.dependencies.aroutercompiler
//implementation rootProject.ext.dependencies.adasHigh
implementation rootProject.ext.dependencies.mogocustommapoperational
implementation rootProject.ext.dependencies.amapnavi3dmap
implementation rootProject.ext.dependencies.amaplocation

View File

@@ -0,0 +1,193 @@
package com.mogo.eagle.core.function.impl.collect
import android.content.Context
import android.text.TextUtils
import com.alibaba.android.arouter.facade.annotation.Route
import com.mogo.cloud.passport.IMoGoTokenCallback
import com.mogo.cloud.passport.MoGoAiCloudClient
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
import com.mogo.commons.debug.DebugConfig
import com.mogo.eagle.core.data.constants.MogoServicePaths
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_MAP
import com.mogo.eagle.core.data.map.MogoLocation
import com.mogo.eagle.core.function.api.map.collect.IMoGoMapDataCollectProvider
import com.mogo.eagle.core.function.api.map.listener.IMoGoMapLocationListener
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.function.call.map.CallerMapLocationListenerManager
import com.zhidaoauto.map.operational.open.GatherApi
import com.zhidaoauto.map.operational.open.GatherParams
import com.zhidaoauto.map.operational.open.abs.OnTaskListener
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.CopyOnWriteArrayList
import java.util.concurrent.atomic.AtomicReference
@Route(path = MogoServicePaths.PATH_MAP_DATA_COLLECT_PROVIDER)
class MoGoMapDataCollectProvider : IMoGoMapDataCollectProvider, OnTaskListener, IMoGoMapLocationListener, IMoGoTokenCallback {
companion object {
const val TAG = "MoGoMapDataCollect"
}
private val executor by lazy {
AtomicReference<GatherApi>(null)
}
private val listeners by lazy {
CopyOnWriteArrayList<IMoGoMapDataCollectProvider.OnMapCollectCmdListener>()
}
private val map: MutableMap<Int, Status> by lazy {
ConcurrentHashMap()
}
override val functionName: String = "$M_MAP$TAG"
@Volatile
private var hasInit = false
override fun init(context: Context?) {
CallerMapLocationListenerManager.addListener(functionName, this)
executor.set(context?.let {
GatherApi.also { itx ->
itx.init(it,
GatherParams.init()
.setDebugMode(DebugConfig.isDebug())
.setCoordinateType(GatherParams.COORDINATETYPE_GCJ02))
} })
executor.get()?.setOnTaskListener(this)
val carSn = MoGoAiCloudClientConfig.getInstance().sn
if (!TextUtils.isEmpty(carSn)) {
executor.get()?.setCarSn(carSn)
}
MoGoAiCloudClient.getInstance().addTokenCallbacks(this)
CallerLogger.d("$M_MAP$TAG", "--------- init --------")
CallerLogger.d("$M_MAP$TAG", "executor: ${ executor.get()?.hashCode() ?: 0 }")
}
override fun onDestroy() {
CallerMapLocationListenerManager.removeListener("$M_MAP$TAG")
CallerLogger.d("$M_MAP$TAG", "--------- onDestroy --------")
executor.get()?.setOnTaskListener(null)
listeners.clear()
map.clear()
}
override fun registerOnMapCollectTaskListener(listener: IMoGoMapDataCollectProvider.OnMapCollectCmdListener?) {
CallerLogger.d("$M_MAP$TAG", "--------- registerOnMapCollectTaskListener --------")
listener ?: return
if (listeners.contains(listener)) {
return
}
listeners += listener
}
override fun unRegisterOnMapCollectTaskListener(listener: IMoGoMapDataCollectProvider.OnMapCollectCmdListener?) {
CallerLogger.d("$M_MAP$TAG", "--------- unRegisterOnMapCollectTaskListener --------")
listener ?: return
if (!listeners.contains(listener)) {
return
}
listeners.remove(listener)
}
override fun finish(
id: Int,
state: Int,
gpsPath: String,
videoPath: String,
reason: String
) {
CallerLogger.d("$M_MAP$TAG", "-- finish:[$id, $state, $gpsPath, $videoPath, $reason]")
try {
if (isInValidStatus()) {
CallerLogger.w("$M_MAP$TAG", "-- finish: 状态无效")
return
}
if (!map.containsKey(id)) {
CallerLogger.w("$M_MAP$TAG", "-- finish: 无相关指令")
return
}
CallerLogger.d("$M_MAP$TAG", "-- finish: 结束任务[$id]")
executor.get()?.finishTask(id, state, gpsPath, videoPath, reason)
} catch (e : Throwable) {
e.printStackTrace()
CallerLogger.e("$M_MAP$TAG", "-- finish:\n$e")
} finally {
map[id] = Status.FINISH
}
}
override fun onTaskFinish(id: Int, time: Long) {
CallerLogger.d("$M_MAP$TAG", "地图模块下发结束采集指令 -> [$id, $time]")
if (!map.containsKey(id) || map[id] == Status.FINISH) {
CallerLogger.w("$M_MAP$TAG", "地图模块下发结束采集指令 -> 任务[$id]已经提前完成,无需再次请求自动驾驶模块结束采集")
return
}
CallerLogger.d("$M_MAP$TAG", "地图模块下发结束采集指令 -> [$id, $time] -> 调用自动驾驶模块,结束数据采集")
listeners.forEach {
it.onMapCollectEnd(id, time)
}
}
override fun onTaskStart(id: Int, time: Long) {
CallerLogger.d("$M_MAP$TAG", "地图模块下发开始采集指令 -> [$id, $time]")
map[id] = Status.INIT
listeners.forEach {
it.onMapCollectStart(id, time)
}
map[id] = Status.START
}
override fun setIsInit() {
if (!hasInit) {
executor.get()?.also {
hasInit = true
CallerLogger.d("$M_MAP$TAG", "告之地图sdk定义数据可以用了")
it.setIsInit()
}
}
}
override fun onLocationChanged(location: MogoLocation?) {
location ?: return
executor.get()?.updateLocation(
location.longitude,
location.latitude,
location.bearing,
location.speed,
location.provider == "GPS_SELF")
}
private fun isInValidStatus(): Boolean {
if (map.isEmpty()) {
return true
}
val iterator = map.iterator()
while (iterator.hasNext()) {
val next = iterator.next()
if (next.value == Status.FINISH) {
iterator.remove()
}
}
if (map.filter { it.value == Status.START }.isEmpty()) {
return true
}
return false
}
override fun onTokenGot(token: String?, sn: String?) {
CallerLogger.d("$M_MAP$TAG", "-- onTokenGot --> $sn")
sn?.let {
executor.get()?.setCarSn(it)
}
}
override fun onError(code: Int, msg: String?) = Unit
private sealed class Status {
object INIT : Status() //初始状态
object START : Status() //开始状态
object FINISH : Status() //完成状态
}
}

View File

@@ -0,0 +1,48 @@
package com.mogo.eagle.core.function.api.map.collect
import com.mogo.eagle.core.function.api.base.IMoGoFunctionServerProvider
/**
* @author renwj
* @date 2021/11/10 10:00 上午
* 此类主要用来同步自动驾驶定位信息给各业务方
*/
interface IMoGoMapDataCollectProvider: IMoGoFunctionServerProvider {
/**
* 注册地图组下发收集数据任务指令监听,通知自动驾驶模块开始数据采集
*/
fun registerOnMapCollectTaskListener(listener: OnMapCollectCmdListener?)
/**
* 移除任务指令监听
*/
fun unRegisterOnMapCollectTaskListener(listener: OnMapCollectCmdListener?)
/**
* 此接口用于定位准确的时候回调
*/
fun setIsInit()
/**
* 此接口是自动驾驶模块使用,用于把自动驾驶模块收集的数据给地图组
*/
fun finish(id: Int, state: Int, gpsPath: String, videoPath: String, reason: String)
interface OnMapCollectCmdListener {
/**
* 地图组下发地图数据收集开始指令
* @param cmdId 指令ID
* @param cmdTime 指令下发时间
*/
fun onMapCollectStart(cmdId: Int, cmdTime: Long)
/**
* 地图组下发地图数据收集结束指令
* @param cmdId 指令ID
* @param cmdTime 指令下发时间
*/
fun onMapCollectEnd(cmdId: Int, cmdTime: Long)
}
}

View File

@@ -0,0 +1,33 @@
package com.mogo.eagle.core.function.call.map
import com.mogo.eagle.core.data.constants.MogoServicePaths.PATH_MAP_DATA_COLLECT_PROVIDER
import com.mogo.eagle.core.function.api.map.collect.IMoGoMapDataCollectProvider
import com.mogo.eagle.core.function.call.base.CallerBase
/**
* @author renwj
* @date 2021/11/10 10:30 上午
* 此类主要提供给各业务方使用,便于业务层管理数据收集
*/
object CallerMapDataCollectorManager {
private val provider: IMoGoMapDataCollectProvider? by lazy {
CallerBase.getApiInstance(IMoGoMapDataCollectProvider::class.java, PATH_MAP_DATA_COLLECT_PROVIDER)
}
fun registerOnMapCollectTaskListener(listener: IMoGoMapDataCollectProvider.OnMapCollectCmdListener?) {
provider?.registerOnMapCollectTaskListener(listener)
}
fun unRegisterOnMapCollectTaskListener(listener: IMoGoMapDataCollectProvider.OnMapCollectCmdListener?) {
provider?.unRegisterOnMapCollectTaskListener(listener)
}
fun finish(id: Int, state: Int, gpsPath: String, videoPath: String, reason: String) {
provider?.finish(id, state, gpsPath, videoPath, reason)
}
fun setIsInit() {
provider?.setIsInit()
}
}

View File

@@ -25,6 +25,7 @@ import com.mogo.eagle.core.data.config.HdMapBuildConfig;
import com.mogo.eagle.core.data.map.MapRoadInfo;
import com.mogo.eagle.core.data.map.MogoLatLng;
import com.mogo.eagle.core.data.map.MogoLocation;
import com.mogo.eagle.core.function.call.map.CallerMapDataCollectorManager;
import com.mogo.eagle.core.function.call.map.CallerMapLocationListenerManager;
import com.mogo.eagle.core.function.call.map.CallerMapRoadListenerManager;
import com.mogo.eagle.core.function.call.map.CallerMapStyleListenerManager;
@@ -1007,6 +1008,7 @@ public class AMapViewWrapper implements IMogoMapView,
// 使用外部定位数据修改自车位置
mMapView.getLocationClient().updateRTKAutoPilotLocation(bean);
CallerMapUIServiceManager.INSTANCE.getSingletonLocationClient(getContext()).updateLocation(bean);
CallerMapDataCollectorManager.INSTANCE.setIsInit();
}
@Override
@@ -1030,6 +1032,7 @@ public class AMapViewWrapper implements IMogoMapView,
// 使用外部定位数据修改自车位置
mMapView.getLocationClient().updateRTKAutoPilotLocation(bean);
CallerMapUIServiceManager.INSTANCE.getSingletonLocationClient(getContext()).updateLocation(bean);
CallerMapDataCollectorManager.INSTANCE.setIsInit();
}
@Override

View File

@@ -77,7 +77,7 @@ dependencies {
api rootProject.ext.dependencies.mogoserviceapi
api rootProject.ext.dependencies.mogo_core_utils
implementation rootProject.ext.dependencies.mogo_core_data
implementation rootProject.ext.dependencies.mogo_core_function_call
api rootProject.ext.dependencies.mogo_core_function_call
} else {
api project(":libraries:mogo-map")
api project(":libraries:mogo-map-api")
@@ -85,7 +85,7 @@ dependencies {
api project(':services:mogo-service-api')
api project(':core:mogo-core-utils')
implementation project(':core:mogo-core-data')
implementation project(':core:mogo-core-function-call')
api project(':core:mogo-core-function-call')
}
}