[VisualAngle]地图视角切换部分代码提交
This commit is contained in:
@@ -9,6 +9,9 @@ import android.view.animation.Animation
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.ImageView
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import com.mogo.eagle.core.function.call.map.CallerVisualAngleManager
|
||||
import com.mogo.eagle.core.function.call.map.CallerVisualAngleManager.Scene.Default
|
||||
import com.mogo.eagle.core.function.call.map.CallerVisualAngleManager.Scene.Turning
|
||||
import com.mogo.eagle.core.function.hmi.R
|
||||
import kotlinx.android.synthetic.main.view_turn_light_status.view.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -35,6 +38,9 @@ class TurnLightViewStatus @JvmOverloads constructor(
|
||||
private var isRightLight :Boolean = false
|
||||
private var isDisappare :Boolean = false
|
||||
|
||||
@Volatile
|
||||
private var isVisualAngleChanged = false
|
||||
|
||||
/**
|
||||
* 转向灯动画
|
||||
*/
|
||||
@@ -46,6 +52,13 @@ class TurnLightViewStatus @JvmOverloads constructor(
|
||||
isShowNormalBg = true
|
||||
}
|
||||
|
||||
if (directionLight == 1 || directionLight == 2) {
|
||||
if (!isVisualAngleChanged) {
|
||||
isVisualAngleChanged = true
|
||||
CallerVisualAngleManager.changeVisualAngle(Turning)
|
||||
}
|
||||
}
|
||||
|
||||
//根据左右进行显示和隐藏,实际要判断每个来的时间和频度
|
||||
if (directionLight == 1) { //左转向
|
||||
if (!isLeftLight) {
|
||||
@@ -73,6 +86,8 @@ class TurnLightViewStatus @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
} else { //消失
|
||||
CallerVisualAngleManager.changeVisualAngle(Default())
|
||||
isVisualAngleChanged = false
|
||||
if (!isDisappare) {
|
||||
GlobalScope.launch(Dispatchers.Main) {
|
||||
animationDisappear()
|
||||
|
||||
@@ -6,6 +6,7 @@ import android.content.IntentFilter
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.provider.Settings.System
|
||||
import android.util.Log
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||
import com.mogo.cloud.passport.IMoGoTokenCallback
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClient
|
||||
@@ -22,6 +23,9 @@ import com.mogo.eagle.core.function.call.hmi.CallerHmiManager
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
|
||||
import com.mogo.eagle.core.function.call.map.CallerMapLocationListenerManager
|
||||
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager
|
||||
import com.mogo.eagle.core.function.call.map.CallerVisualAngleManager
|
||||
import com.mogo.eagle.core.function.call.map.CallerVisualAngleManager.Scene.Default
|
||||
import com.mogo.eagle.core.function.call.map.CallerVisualAngleManager.Scene.TooClose
|
||||
import com.mogo.eagle.core.function.v2x.events.alarm.V2XAlarmServer
|
||||
import com.mogo.eagle.core.function.v2x.events.bridge.BridgeApi
|
||||
import com.mogo.eagle.core.function.v2x.events.bridge.BridgeApi.context
|
||||
@@ -487,6 +491,7 @@ object V2XEventManager : IMoGoMapLocationListener, IMoGoTokenCallback, IV2XCallb
|
||||
scope.launch {
|
||||
val message = event.data
|
||||
val trafficData = buildTrafficData(message)
|
||||
var changeVisualAngle = false
|
||||
when (message.status) {
|
||||
1 -> {
|
||||
var tts = ""
|
||||
@@ -507,12 +512,14 @@ object V2XEventManager : IMoGoMapLocationListener, IMoGoTokenCallback, IV2XCallb
|
||||
}
|
||||
1003 -> {
|
||||
// 交叉路口碰撞预警
|
||||
changeVisualAngle = true
|
||||
appId = EventTypeEnum.TYPE_USECASE_ID_ICW.poiType.toInt()
|
||||
tts = EventTypeEnum.TYPE_USECASE_ID_ICW.tts
|
||||
content = EventTypeEnum.TYPE_USECASE_ID_ICW.content
|
||||
}
|
||||
1004 -> {
|
||||
// 交叉路口碰撞预警
|
||||
changeVisualAngle = true
|
||||
appId = EventTypeEnum.TYPE_USECASE_ID_BSW.poiType.toInt()
|
||||
tts = String.format(EventTypeEnum.TYPE_USECASE_ID_BSW.tts, getWarningDirection())
|
||||
content = EventTypeEnum.TYPE_USECASE_ID_BSW.content
|
||||
@@ -544,8 +551,16 @@ object V2XEventManager : IMoGoMapLocationListener, IMoGoTokenCallback, IV2XCallb
|
||||
}
|
||||
// 显示弹框,语音提示
|
||||
CallerHmiManager.showWarningV2X(appId, content, tts, "$appId", object : IMoGoWarningStatusListener {
|
||||
override fun onShow() {}
|
||||
val change = changeVisualAngle
|
||||
override fun onShow() {
|
||||
if (change) {
|
||||
CallerVisualAngleManager.changeVisualAngle(TooClose)
|
||||
}
|
||||
}
|
||||
override fun onDismiss() {
|
||||
if (change) {
|
||||
CallerVisualAngleManager.changeVisualAngle(Default())
|
||||
}
|
||||
}
|
||||
}, true, 5000L)
|
||||
TrafficMarkerDrawer.updateITrafficInfo(trafficData)
|
||||
|
||||
@@ -5,6 +5,7 @@ import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_V2X
|
||||
import com.mogo.eagle.core.data.enums.WarningDirectionEnum;
|
||||
import com.mogo.eagle.core.function.api.hmi.warning.IMoGoWarningStatusListener;
|
||||
import com.mogo.eagle.core.function.call.hmi.CallerHmiManager;
|
||||
import com.mogo.eagle.core.function.call.map.CallerVisualAngleManager;
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
|
||||
import com.mogo.eagle.core.function.v2x.events.bridge.BridgeApi;
|
||||
import com.mogo.eagle.core.function.v2x.events.consts.V2XConst;
|
||||
@@ -117,6 +118,7 @@ public class V2XRoadEventScenario extends AbsV2XScenario<V2XRoadEventEntity> imp
|
||||
|
||||
@Override
|
||||
public void onShow() {
|
||||
CallerVisualAngleManager.INSTANCE.changeVisualAngle(CallerVisualAngleManager.Scene.RoadEvent.INSTANCE);
|
||||
CallerHmiManager.INSTANCE.showWarning(WarningDirectionEnum.ALERT_WARNING_TOP, TimeUnit.HOURS.toMillis(1));
|
||||
V2XMessageEntity<V2XRoadEventEntity> entity = getV2XMessageEntity();
|
||||
if (entity != null && entity.isNeedAddLine()) {
|
||||
@@ -127,6 +129,7 @@ public class V2XRoadEventScenario extends AbsV2XScenario<V2XRoadEventEntity> imp
|
||||
@Override
|
||||
public void onDismiss() {
|
||||
CallerHmiManager.INSTANCE.dismissWarning(WarningDirectionEnum.ALERT_WARNING_TOP);
|
||||
CallerVisualAngleManager.INSTANCE.changeVisualAngle(new CallerVisualAngleManager.Scene.Default(3, TimeUnit.SECONDS));
|
||||
clearPOI();
|
||||
release();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
package com.mogo.eagle.core.function.call.map
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.SystemClock
|
||||
import android.util.Log
|
||||
import com.mogo.eagle.core.data.map.MogoLatLng
|
||||
import com.mogo.eagle.core.function.call.map.CallerVisualAngleManager.Scene.Default
|
||||
import com.mogo.eagle.core.function.call.map.CallerVisualAngleManager.Scene.LowSpeed
|
||||
import com.mogo.eagle.core.utilcode.kotlin.safeCancel
|
||||
import com.mogo.map.uicontroller.VisualAngleMode
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.android.asCoroutineDispatcher
|
||||
import kotlinx.coroutines.internal.synchronized
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.TimeUnit.SECONDS
|
||||
|
||||
/**
|
||||
* 高精地图视角管理类
|
||||
*/
|
||||
object CallerVisualAngleManager {
|
||||
|
||||
private const val TAG = "VisualAngle"
|
||||
|
||||
private const val MaxDisplayThreshold = 20_000 //最大展示阈值
|
||||
|
||||
private var scope: CoroutineScope = acquireScope()
|
||||
@Synchronized
|
||||
get() {
|
||||
if (field.isActive) {
|
||||
return field
|
||||
}
|
||||
val scope = acquireScope()
|
||||
field = scope
|
||||
return field
|
||||
}
|
||||
|
||||
private var defaultDelayJob: Job? = null
|
||||
|
||||
private fun acquireScope(): CoroutineScope {
|
||||
return CoroutineScope(Handler(Looper.getMainLooper()).asCoroutineDispatcher("change-visual-angle") + SupervisorJob())
|
||||
}
|
||||
|
||||
private interface IAttach {
|
||||
val angle: VisualAngleMode
|
||||
val priority: Int
|
||||
}
|
||||
|
||||
sealed class Scene private constructor(): IAttach {
|
||||
|
||||
/**
|
||||
* 默认视图
|
||||
* @param delay: 表示多少稍后,默认值为2
|
||||
* @param unit: 时间单位,默认为秒
|
||||
*/
|
||||
class Default(val delay: Long = 2, val unit: TimeUnit = SECONDS): Scene() {
|
||||
|
||||
override val angle: VisualAngleMode = VisualAngleMode.MODE_MEDIUM_SIGHT
|
||||
|
||||
override val priority: Int = 0
|
||||
|
||||
override fun toString(): String {
|
||||
return "Default(delay=$delay, unit=$unit, angle=$angle, priority=$priority)"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 变道-接收到转向灯信息号
|
||||
*/
|
||||
object Turning: Scene() {
|
||||
|
||||
override val angle: VisualAngleMode = VisualAngleMode.MAP_STYLE_VR_ANGLE_TOP
|
||||
|
||||
override val priority: Int = 0
|
||||
}
|
||||
|
||||
/**
|
||||
* 后方车辆离自车过近
|
||||
*/
|
||||
object TooClose: Scene() {
|
||||
|
||||
override val angle: VisualAngleMode = VisualAngleMode.MAP_STYLE_VR_ANGLE_300
|
||||
|
||||
override val priority: Int = 0
|
||||
}
|
||||
|
||||
/**
|
||||
* 道路事件
|
||||
*/
|
||||
object RoadEvent: Scene() {
|
||||
|
||||
override val angle: VisualAngleMode = VisualAngleMode.MODE_LONG_SIGHT
|
||||
|
||||
override val priority: Int = 0
|
||||
}
|
||||
|
||||
/**
|
||||
* 车量低速行驶
|
||||
*/
|
||||
class LowSpeed(val lat: Double, val lon: Double): Scene() {
|
||||
|
||||
override val angle: VisualAngleMode = VisualAngleMode.MODE_CLOSE_SIGHT
|
||||
|
||||
override val priority: Int = 0
|
||||
|
||||
override fun toString(): String {
|
||||
return "LowSpeed(lat=$lat, lon=$lon, angle=$angle, priority=$priority)"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 十字路口
|
||||
*/
|
||||
object CrossRoad: Scene() {
|
||||
override val angle: VisualAngleMode = VisualAngleMode.MAP_STYLE_VR_ANGLE_CROSS
|
||||
override val priority: Int = 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 业务实体,不对外暴露
|
||||
* @param target: 目标场景
|
||||
* @param isDisplay: 是否正在展示
|
||||
* @param triggerTime: 触发时间
|
||||
*/
|
||||
private data class Record(val target: Scene, var isDisplay: Boolean = false, val triggerTime: Long): Comparable<Record> {
|
||||
override fun compareTo(other: Record): Int {
|
||||
//大根堆
|
||||
if (triggerTime != other.triggerTime) {
|
||||
//时间越晚,越靠近堆顶
|
||||
return if (triggerTime > other.triggerTime) -1 else 1
|
||||
}
|
||||
//如果时间一样,优先级越高,越靠近堆顶
|
||||
return other.target.priority - target.priority
|
||||
}
|
||||
}
|
||||
|
||||
private val heap by lazy {
|
||||
/**
|
||||
* 堆, 大根堆还是小根堆由[Record.compareTo]方法决定
|
||||
*/
|
||||
PriorityQueue<Record>()
|
||||
}
|
||||
|
||||
@OptIn(InternalCoroutinesApi::class)
|
||||
fun changeVisualAngle(scene: Scene) {
|
||||
val triggerTime = SystemClock.elapsedRealtime()
|
||||
scope.launch {
|
||||
val displayed = getDisplayed()
|
||||
if (displayed == null) {
|
||||
val top = getTop() //堆顶
|
||||
if (top != null && top.target.priority > scene.priority) {
|
||||
doChangeAngle(top)
|
||||
synchronized(heap) {
|
||||
heap += Record(scene, triggerTime = triggerTime)
|
||||
}
|
||||
} else {
|
||||
doChangeAngle(Record(scene, triggerTime = triggerTime))
|
||||
}
|
||||
Log.d(TAG, "没有正在展示的视角,当前要展示的视角: $scene")
|
||||
} else {
|
||||
if (scene.javaClass == displayed.javaClass) {
|
||||
Log.d(TAG, "同一种场景不需要重复展示")
|
||||
return@launch
|
||||
}
|
||||
if (scene is Default) {
|
||||
Log.d(TAG, "恢复到默认视图,之前展示的视图:$displayed")
|
||||
synchronized(heap) {
|
||||
heap -= displayed
|
||||
}
|
||||
launch {
|
||||
val delay = scene.unit.toMillis(scene.delay)
|
||||
Log.d(TAG, "默认视图开启延时倒计时, 倒计时时间:${delay} ms.")
|
||||
delay(delay)
|
||||
Log.d(TAG, "默认视图结束倒计时,开始展示...")
|
||||
doChangeAngle(Record(scene, triggerTime = triggerTime))
|
||||
}.also { defaultDelayJob = it }
|
||||
} else {
|
||||
val delta = triggerTime - displayed.triggerTime
|
||||
if (delta >= MaxDisplayThreshold) {
|
||||
Log.d(TAG, "场景: $scene 触发展示,满足条件开始展示...")
|
||||
doChangeAngle(Record(scene, triggerTime = triggerTime))
|
||||
} else {
|
||||
Log.d(TAG, "场景: $scene 触发展示,但是在20s内,丢弃...")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(InternalCoroutinesApi::class)
|
||||
private fun doChangeAngle(record: Record) {
|
||||
CallerMapUIServiceManager.getMapUIController()?.also {
|
||||
record.isDisplay = true
|
||||
synchronized(heap) {
|
||||
heap += record
|
||||
}
|
||||
val target = record.target
|
||||
if (target !is Default) {
|
||||
defaultDelayJob?.safeCancel()
|
||||
}
|
||||
if (target is LowSpeed) {
|
||||
it.changeMapVisualAngle(record.target.angle, MogoLatLng(target.lat, target.lon))
|
||||
} else {
|
||||
it.changeMapVisualAngle(record.target.angle, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否有正在展示的
|
||||
*/
|
||||
@Synchronized
|
||||
private fun getDisplayed() = heap.find { it.isDisplay }
|
||||
|
||||
@Synchronized
|
||||
private fun getTop() = heap.firstOrNull()
|
||||
}
|
||||
@@ -305,3 +305,4 @@ fun Context.toast(text: CharSequence, duration: Long = 2, unit: TimeUnit = SECON
|
||||
Reminder.enqueue(activity.lifeCycleOwner, reminder)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ MOGO_LOCATION_VERSION=1.3.31
|
||||
MOGO_TELEMATIC_VERSION=1.3.31
|
||||
######## MogoAiCloudSDK Version ########
|
||||
# 自研地图
|
||||
MAP_SDK_VERSION=2.0.5.7
|
||||
MAP_SDK_VERSION=2.0.9.1
|
||||
MAP_SDK_OPERATION_VERSION=1.0.12
|
||||
# websocket
|
||||
WEBSOCKET_VERSION=1.1.7
|
||||
|
||||
Reference in New Issue
Block a user