[2.13.0-arch-opt] v2x remove

This commit is contained in:
zhongchao
2023-02-17 21:31:27 +08:00
parent 18f3954545
commit d5474743bf
143 changed files with 160 additions and 269 deletions

View File

@@ -1,5 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mogo.eagle.core.function.biz">
<application>
<receiver android:name="com.mogo.eagle.function.biz.v2x.v2n.test.TestV2XReceiver">
<intent-filter>
<action android:name="com.v2x.test_panel_control" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
</application>
</manifest>

View File

@@ -17,6 +17,8 @@ import com.mogo.eagle.function.biz.v2x.overview.OverViewDataManager
import com.mogo.eagle.function.biz.v2x.overview.db.OverviewDb
import com.mogo.eagle.function.biz.v2x.road.LineUploadManager
import com.mogo.eagle.function.biz.v2x.trafficlight.core.MogoTrafficLightManager
import com.mogo.eagle.function.biz.v2x.v2n.V2XEventManager
import com.mogo.eagle.function.biz.v2x.v2n.V2XPoiLoader.Companion.v2xPoiLoader
import com.mogo.eagle.function.biz.v2x.vip.VipCarManager
@Route(path = MogoServicePaths.PATH_FUNC_BIZ)
@@ -35,6 +37,10 @@ class FuncBizProvider : IMoGoFuncBizProvider {
OverviewDb.getDb(context)
MogoTrafficLightManager.INSTANCE.initServer(context)
VipCarManager.INSTANCE.initServer(context)
if(!(AppIdentityModeUtils.isBus(FunctionBuildConfig.appIdentityMode)
&& AppIdentityModeUtils.isPassenger(FunctionBuildConfig.appIdentityMode))){
V2XEventManager.init(context)
}
if(AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)){
LineUploadManager.getInstance(context)?.init()
}
@@ -84,12 +90,21 @@ class FuncBizProvider : IMoGoFuncBizProvider {
OverViewDataManager.getAllV2XEventsByLineId(MoGoAiCloudClientConfig.getInstance().sn)
}
override fun queryV2XEvents() {
v2xPoiLoader.queryWholeRoadEvents()
}
override fun onDestroy() {
noticeSocketManager.release()
dispatchAutoPilotManager.release()
cronTaskManager.release()
VipCarManager.INSTANCE.destroy()
if(!(AppIdentityModeUtils.isBus(FunctionBuildConfig.appIdentityMode)
&& AppIdentityModeUtils.isPassenger(FunctionBuildConfig.appIdentityMode))){
V2XEventManager.onDestroy()
}
if(AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)){
mContext?.let {
LineUploadManager.getInstance(it)?.onDestroy()

View File

@@ -0,0 +1,398 @@
package com.mogo.eagle.function.biz.v2x.v2n
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.os.Handler
import android.os.Looper
import android.util.Log
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_ALIAS_CODE_CLOUD_V2N
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_LINK_CLOUD
import com.mogo.eagle.core.data.deva.chain.ChainConstant.Companion.CHAIN_LINK_LOG_CLOUD_V2N
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.data.enums.EventTypeEnumNew
import com.mogo.eagle.core.data.enums.EventTypeHelper
import com.mogo.eagle.core.data.enums.TrafficTypeEnum
import com.mogo.eagle.core.data.map.MogoLocation
import com.mogo.eagle.core.data.map.entity.V2XMessageEntity
import com.mogo.eagle.core.data.map.entity.V2XRoadEventEntity
import com.mogo.eagle.core.data.msgbox.MsgBoxBean
import com.mogo.eagle.core.data.msgbox.MsgBoxType
import com.mogo.eagle.core.data.msgbox.V2XMsg
import com.mogo.eagle.core.data.traffic.TrafficData
import com.mogo.eagle.core.data.v2x.V2XAdvanceWarning
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotIdentifyListener
import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener
import com.mogo.eagle.core.function.api.hmi.warning.IMoGoWarningStatusListener
import com.mogo.eagle.core.function.api.map.angle.*
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotIdentifyListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager
import com.mogo.eagle.core.function.call.hmi.CallerHmiManager
import com.mogo.eagle.core.function.call.map.CallerMapIdentifyManager
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.msgbox.CallerMsgBoxManager
import com.mogo.eagle.function.biz.v2x.v2n.alarm.V2XAlarmServer
import com.mogo.eagle.function.biz.v2x.v2n.bridge.BridgeApi
import com.mogo.eagle.function.biz.v2x.v2n.consts.V2XConst.BROADCAST_SCENE_EXTRA_KEY
import com.mogo.eagle.function.biz.v2x.v2n.consts.V2XConst.BROADCAST_SCENE_HANDLER_ACTION
import com.mogo.eagle.function.biz.v2x.v2n.receiver.SceneBroadcastReceiver
import com.mogo.eagle.function.biz.v2x.v2n.scenario.impl.V2XScenarioManager
import com.mogo.eagle.function.biz.v2x.v2n.utils.toRoadMarker
import com.mogo.eagle.core.data.v2x.V2XEvent
import com.mogo.eagle.core.data.v2x.V2XMarkerCardResult
import com.mogo.eagle.core.data.v2x.V2XWarningTarget
import com.mogo.eagle.core.function.api.cloud.IMoGoCloudListener
import com.mogo.eagle.core.function.call.cloud.CallerCloudListenerManager
import com.mogo.eagle.function.biz.v2x.v2n.V2XPoiLoader.Companion.v2xPoiLoader
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.Logger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_V2X
import com.mogo.eagle.core.utilcode.util.Utils
import com.mogo.eagle.function.biz.v2x.v2n.network.callback.IV2XCallback
import com.mogo.eagle.function.biz.v2x.v2n.utils.toV2XRoadEventEntity
import com.zhjt.service.chain.ChainLog
import com.zhjt.service.chain.TracingConstants
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.android.asCoroutineDispatcher
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import java.util.concurrent.atomic.AtomicBoolean
import mogo.telematics.pad.MessagePad
object V2XEventManager : IMoGoChassisLocationGCJ02Listener, IV2XCallback,
IMoGoAutopilotIdentifyListener, IMoGoCloudListener {
private const val TAG = "V2XEventManager"
private val scope: CoroutineScope by lazy {
CoroutineScope(Handler(Looper.getMainLooper()).asCoroutineDispatcher(TAG))
}
private val hasInit by lazy { AtomicBoolean(false) }
fun init(context: Context) {
BridgeApi.init(context)
if (hasInit.compareAndSet(false, true)) {
registerListener()
v2xPoiLoader.startLoopPoi()
// 注册广播接收场景弹窗使用的
SceneBroadcastReceiver.register(context)
}
}
private fun registerListener() {
CallerChassisLocationGCJ02ListenerManager.addListener(TAG, 1,this)
v2xPoiLoader.addCallback(this)
CallerCloudListenerManager.addListener(TAG,this)
CallerAutopilotIdentifyListenerManager.addListener(TAG, this)
}
private fun unRegisterListener() {
CallerChassisLocationGCJ02ListenerManager.removeListener(TAG)
v2xPoiLoader.removeCallback(this)
CallerCloudListenerManager.removeListener(TAG)
CallerAutopilotIdentifyListenerManager.removeListener(TAG)
}
override fun onChassisLocationGCJ02(mogoLocation: MogoLocation?) {
BridgeApi.location.set(mogoLocation)
mogoLocation?.let {
v2xPoiLoader.updateCheck(mogoLocation.longitude,mogoLocation.latitude)
refreshCarState(mogoLocation)
}
}
private fun refreshCarState(location: MogoLocation) {
// 巡航处理
val v2XRoadEventEntity = V2XAlarmServer.getDriveFrontAlarmEvent(
BridgeApi.v2xMarker()?.v2XRoadEventEntityList, location
)
if (v2XRoadEventEntity != null) {
val distance = v2XRoadEventEntity.distance
val min = if (EventTypeEnumNew.isCloudSocketEvent(v2XRoadEventEntity.poiType)) 0 else 5
CallerLogger.d(
"$M_V2X$TAG",
"--- trigger show before ---:data=>[${location.longitude}, ${location.latitude}, ${location.gnssSpeed}], distance: $distance, minDistance: $min, poiType: ${v2XRoadEventEntity.poiType}"
)
if (distance >= min) {
CallerLogger.d(
"$M_V2X$TAG",
"--- trigger show ---:poiType:" + v2XRoadEventEntity.poiType
)
val v2XMessageEntity = V2XMessageEntity<V2XRoadEventEntity>()
v2XMessageEntity.type = V2XMessageEntity.V2XTypeEnum.ALERT_ROAD_WARNING
v2XMessageEntity.content = v2XRoadEventEntity
V2XScenarioManager.getInstance().handlerMessage(v2XMessageEntity)
}
}
}
/**
* V2XEvent事件回调
*/
@ChainLog(
linkChainLog = CHAIN_LINK_LOG_CLOUD_V2N,
linkCode = CHAIN_LINK_CLOUD,
endpoint = TracingConstants.Endpoint.PAD,
nodeAliasCode = CHAIN_ALIAS_CODE_CLOUD_V2N,
paramIndexes = [0],
clientPkFileName = "sn"
)
override fun onAck(event: V2XEvent) {
Log.d("$M_V2X$TAG", "OK->: $event")
when (event) {
is V2XEvent.ForwardsWarning -> {
handleAdvanceWarningEvent(event)
}
is V2XEvent.Marker -> {
event.data.result?.let {
handleRoadMarkerEvent(it)
}
}
is V2XEvent.Road -> {
handleRoadMarkerEvent(event.data)
}
is V2XEvent.Warning -> {
handleWarningTargetEvent(event.data)
}
is V2XEvent.RoadAI -> {
if (FunctionBuildConfig.isV2NFromCar) {
return
}
handleRoadMarkerEvent(event.data.toRoadMarker())
}
is V2XEvent.RoadEventX -> {
handleRoadMarkerEvent(event.data.toRoadMarker())
}
else -> {
Logger.e(TAG, "onAck other event: $event")
}
}
}
@SuppressLint("NewApi")
override fun onAutopilotIdentifyPlanningObj(planningObjects: List<MessagePad.PlanningObject>?) {
super.onAutopilotIdentifyPlanningObj(planningObjects)
if (!FunctionBuildConfig.isV2NFromCar) {
return
}
planningObjects?.let {
if (it.isNotEmpty()) {
val first = it.stream()
.filter { planningObj: MessagePad.PlanningObject -> planningObj.type >= 1000 }
.findFirst()
if (first.isPresent) {
val poiType = when (first.get().type) {
// 1004 -> { //V2N_RSM,静止事件,包括异常停车、异常静止障碍物
// }
1005 -> { //V2N_RSI,施工事件,包括锥桶或者挡板围城的施工场景,是个多边形包围区域
EventTypeEnumNew.TYPE_SOCKET_ROAD_SHIGONG.poiType
}
1007 -> { //三角牌
EventTypeEnumNew.FOURS_ACCIDENT_04.poiType
}
else -> {
return
}
}
CallerLogger.d("$M_V2X$TAG", "poiType : $poiType , 触发道路事件")
val trackedObj =
CallerMapIdentifyManager.getIdentifyObj(first.get().uuid.toString())
trackedObj?.let { t ->
CallerLogger.d("$M_V2X$TAG", "polygon size : ${(t.polygonList.size)}")
val v2XMessageEntity = V2XMessageEntity<V2XRoadEventEntity>()
v2XMessageEntity.type = V2XMessageEntity.V2XTypeEnum.ALERT_ROAD_WARNING
v2XMessageEntity.content = t.toRoadMarker(poiType).toV2XRoadEventEntity()
V2XScenarioManager.getInstance().handlerMessage(v2XMessageEntity)
}
}
}
}
}
private fun handleWarningTargetEvent(data: V2XWarningTarget) {
val v2xMessageEntity = V2XMessageEntity<V2XWarningTarget>()
v2xMessageEntity.type = V2XMessageEntity.V2XTypeEnum.ALERT_THE_FRONT_WEAKNESS
// 设置数据
v2xMessageEntity.content = data
val intent = Intent(BROADCAST_SCENE_HANDLER_ACTION)
intent.putExtra(BROADCAST_SCENE_EXTRA_KEY, v2xMessageEntity)
LocalBroadcastManager.getInstance(Utils.getApp()).sendBroadcast(intent)
}
private fun handleRoadMarkerEvent(data: V2XMarkerCardResult) {
try {
scope.launch(Dispatchers.Default) {
BridgeApi.v2xMarker()?.analysisV2XRoadEvent(data)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
//todo 可优化与obu解析类似
private fun handleAdvanceWarningEvent(event: V2XEvent.ForwardsWarning) {
scope.launch {
val message = event.data
val trafficData = buildTrafficData(message)
var changeVisualAngle = false
when (message.status) {
1 -> {
var tempAppId = 0
var tempTts = ""
var tempContent = ""
when (message.typeId) {
1001 -> {
// 弱势交通碰撞预警
EventTypeHelper.getVRU { appId, tts, content ->
tempAppId = appId
tempTts = tts
tempContent = content
}
}
1002 -> {
// 弱势交通逆行预警
EventTypeHelper.getVRURI { appId, tts, content ->
tempAppId = appId
tempTts = tts
tempContent = content
}
}
1003 -> {
// 交叉路口碰撞预警
changeVisualAngle = true
tempAppId = EventTypeEnumNew.TYPE_USECASE_ID_ICW.poiType.toInt()
tempTts = EventTypeEnumNew.TYPE_USECASE_ID_ICW.tts
tempContent = EventTypeEnumNew.TYPE_USECASE_ID_ICW.content
}
1004 -> {
// 交叉路口碰撞预警
changeVisualAngle = true
tempAppId = EventTypeEnumNew.TYPE_USECASE_ID_BSW.poiType.toInt()
tempTts = String.format(
EventTypeEnumNew.TYPE_USECASE_ID_BSW.tts,
getWarningDirection()
)
tempContent = EventTypeEnumNew.TYPE_USECASE_ID_BSW.content
}
1006 -> {
// 逆向超车预警
tempAppId = EventTypeEnumNew.TYPE_USECASE_ID_DNPW.poiType.toInt()
tempTts = EventTypeEnumNew.TYPE_USECASE_ID_DNPW.tts
tempContent = EventTypeEnumNew.TYPE_USECASE_ID_DNPW.content
}
1005 -> {
// 闯红灯预警
tempAppId = EventTypeEnumNew.TYPE_USECASE_ID_IVP_RED.poiType.toInt()
tempTts = EventTypeEnumNew.TYPE_USECASE_ID_IVP_RED.tts
tempContent = EventTypeEnumNew.TYPE_USECASE_ID_IVP_RED.content
}
2001 -> {
// 最优车道100061
EventTypeHelper.getOptLine { appId, tts, content ->
tempAppId = appId
tempTts = tts
tempContent = content
}
}
3001 -> {
// 前方道路拥堵预警
EventTypeHelper.getTJW { appId, tts, content ->
tempAppId = appId
tempTts = tts
tempContent = content
}
}
}
// 不显示弹框,其它保留
if (tempContent.isEmpty() || tempTts.isEmpty()) {
Log.d("MsgBox-V2XEventManager", "alertContent或ttsContent为空!")
}
CallerMsgBoxManager.saveMsgBox(
MsgBoxBean(
MsgBoxType.V2X,
V2XMsg(
tempAppId.toString(),
tempContent,
tempTts
)
)
)
CallerHmiManager.warningV2X(
tempAppId.toString(),
tempContent,
tempTts,
object : IMoGoWarningStatusListener {
val change = changeVisualAngle
override fun onShow() {
if (change) {
CallerVisualAngleManager.changeAngle(TooClose)
}
}
override fun onDismiss() {
if (change) {
CallerVisualAngleManager.changeAngle(Default())
}
}
}
)
CallerMapUIServiceManager.getMarkerService()?.updateITrafficInfo(trafficData)
}
2 -> {
CallerMapUIServiceManager.getMarkerService()?.updateITrafficInfo(trafficData)
}
3 -> {
trafficData.uuid?.let {
CallerMapUIServiceManager.getMarkerService()?.removeCvxRvInfoIndInfo(it)
}
}
}
}
}
private fun getWarningDirection(): String {
return "" //TODO renwj 原来的逻辑,预警方向先写死, 后续做兼容
}
private fun buildTrafficData(message: V2XAdvanceWarning): TrafficData {
return TrafficData().apply {
type = when (message.objectType) {
1 -> TrafficTypeEnum.TYPE_TRAFFIC_ID_PEOPLE
2 -> TrafficTypeEnum.TYPE_TRAFFIC_ID_BICYCLE
3 -> TrafficTypeEnum.TYPE_TRAFFIC_ID_TA_CHE
4 -> TrafficTypeEnum.TYPE_TRAFFIC_ID_MOTO
6 -> TrafficTypeEnum.TYPE_TRAFFIC_ID_BUS
8 -> TrafficTypeEnum.TYPE_TRAFFIC_ID_TRUCK
9 -> TrafficTypeEnum.TYPE_TRAFFIC_ID_CAMERA
else -> TrafficTypeEnum.TYPE_TRAFFIC_ID_WEI_ZHI
}
uuid = message.objectId
lat = message.position?.lat ?: 0.0
lon = message.position?.lon ?: 0.0
heading = message.heading ?: 0.0
threatLevel = message.threatLevel ?: -1
}
}
override fun onFail(msg: String) {
CallerLogger.e("$M_V2X$TAG", "Error: $msg")
}
fun onDestroy() {
if (hasInit.compareAndSet(true, false)) {
try {
scope.cancel()
} catch (e: Throwable) {
e.printStackTrace()
} finally {
unRegisterListener()
}
v2xPoiLoader.stopLoopPoi()
}
}
}

View File

@@ -0,0 +1,184 @@
package com.mogo.eagle.function.biz.v2x.v2n
import android.os.Handler
import android.os.Looper
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
import com.mogo.eagle.core.data.enums.DataSourceType
import com.mogo.eagle.core.data.msgbox.MsgBoxBean
import com.mogo.eagle.core.data.msgbox.MsgBoxType
import com.mogo.eagle.core.data.msgbox.V2XMsg
import com.mogo.eagle.core.data.v2x.V2XEvent
import com.mogo.eagle.core.data.v2x.V2XMarkerResponse
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager
import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxManager
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
import com.mogo.eagle.function.biz.v2x.v2n.network.V2XRefreshModel
import com.mogo.eagle.function.biz.v2x.v2n.network.callback.IV2XCallback
import com.mogo.eagle.function.biz.v2x.v2n.network.callback.IV2XRefreshCallback
import com.mogo.eagle.function.biz.v2x.v2n.utils.DistanceUtils
import java.util.concurrent.CopyOnWriteArrayList
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicReference
class V2XPoiLoader private constructor() {
companion object {
private const val TAG = "V2XPoiLoader"
val v2xPoiLoader by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
V2XPoiLoader()
}
}
private val lastLongitude by lazy { AtomicReference(0.0) }
private val lastLatitude by lazy { AtomicReference(0.0) }
private val realLongitude by lazy { AtomicReference(0.0) }
private val realLatitude by lazy { AtomicReference(0.0) }
private val handler by lazy {
Handler(Looper.getMainLooper())
}
private val cbs by lazy {
CopyOnWriteArrayList<IV2XCallback>()
}
/**
* 添加相关信息接口回调
* @param cb 要添加的回调接口
*/
fun addCallback(cb: IV2XCallback) {
if (cbs.contains(cb)) {
return
}
cbs += cb
}
/**
* 移除相关信息接口回调
* @param cb 要移除的回调接口
*/
fun removeCallback(cb: IV2XCallback) {
if (!cbs.contains(cb)) {
return
}
cbs.remove(cb)
}
fun updateCheck(longitude: Double, latitude: Double) {
realLongitude.set(longitude)
realLatitude.set(latitude)
val oldLon = lastLongitude.get()
val oldLat = lastLatitude.get()
var update = false
try {
if (oldLon == 0.0 || oldLat == 0.0) {
handler.removeCallbacks(refreshTask)
handler.post(refreshTask)
update = true
return
}
if (DistanceUtils.calculateLineDistance(oldLon, oldLat, longitude, latitude) >= 200f) {
handler.removeCallbacks(refreshTask)
handler.post(refreshTask)
update = true
}
} finally {
if (update) {
lastLatitude.set(latitude)
lastLongitude.set(longitude)
}
}
}
/**
* 开启loop Poi事件
*/
fun startLoopPoi() {
handler.removeCallbacks(refreshTask)
handler.post(refreshTask)
}
private val refreshTask = object : Runnable {
override fun run() {
V2XRefreshModel.querySnapshot(
longitude = realLongitude.get(), latitude = realLatitude.get(),
refreshCallback
)
handler.postDelayed(this, TimeUnit.SECONDS.toMillis(60))
}
}
fun stopLoopPoi() {
handler.removeCallbacks(refreshTask)
lastLatitude.set(0.0)
lastLongitude.set(0.0)
}
private val refreshCallback = object : IV2XRefreshCallback<V2XMarkerResponse> {
override fun onSuccess(result: V2XMarkerResponse) {
cbs.forEach {
it.onAck(V2XEvent.Marker(result))
}
}
override fun onFail(msg: String?) {
cbs.forEach {
it.onFail(msg ?: "")
}
}
}
/**
* 查询全览路径上的事件信息
*/
fun queryWholeRoadEvents() {
V2XRefreshModel.roadEventDispose()
val sn = MoGoAiCloudClientConfig.getInstance().sn
val lineId = getLineId()
if (lineId > 0) {
realQueryV2xEvents(lineId.toString(), sn)
} else {
UiThreadHandler.postDelayed({
realQueryV2xEvents(getLineId().toString(), sn)
}, 500)
}
}
private fun getLineId(): Long {
var lineId: Long = -1
val parameter = CallerAutoPilotStatusListenerManager.getAutoPilotStatusInfo()
.autopilotControlParameters
if (parameter != null) {
if (parameter.autoPilotLine != null) {
lineId = parameter.autoPilotLine!!.lineId
CallerLogger.d(SceneConstant.M_V2X + TAG, "lineId为:$lineId")
} else {
CallerLogger.d(SceneConstant.M_V2X + TAG, "parameter.autoPilotLine为null")
}
} else {
CallerLogger.d(SceneConstant.M_V2X + TAG, "parameter为null")
}
return lineId
}
private fun realQueryV2xEvents(lineId: String, sn: String) {
V2XRefreshModel.getRoadEvents(lineId, sn) {
val size = it?.size ?: 0
if (size > 0) {
val msgBoxBean =
MsgBoxBean(MsgBoxType.V2X, V2XMsg("", "查询到当前全程共${size}个事件", ""))
msgBoxBean.sourceType = DataSourceType.SUMMARY
CallerMsgBoxManager.saveMsgBox(msgBoxBean)
}
}
}
}

View File

@@ -0,0 +1,120 @@
package com.mogo.eagle.function.biz.v2x.v2n.alarm;
import com.mogo.eagle.core.data.enums.EventTypeEnumNew;
import com.mogo.eagle.core.data.map.MogoLocation;
import com.mogo.eagle.core.data.map.entity.MarkerLocation;
import com.mogo.eagle.core.data.map.entity.V2XRoadEventEntity;
import com.mogo.eagle.core.utilcode.mogo.logger.Logger;
import com.mogo.eagle.core.utilcode.util.DrivingDirectionUtils;
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;
import io.netty.util.internal.ConcurrentSet;
/**
* @author donghongyu
* e-mail : 1358506549@qq.com
* date : 2020/4/13 11:02 AM
* desc :
* 这里是车机端自己实现预警信息的触发操作首先获取当前车位置周围2公里范围的道路事件
* 普通模式根据当前「车辆位置」及「行驶方向」判断「车辆前方」「500米」是否有道路事件需要触发。
* 导航模式根据当前「路径规划」及「行驶方向」判断「路径前方」「500米」是否有道路事件需要触发。
* 疲劳驾驶:根据服务端下发的触发条件进行触发
* <p>
* version: 1.0
*/
public class V2XAlarmServer {
private static final String TAG = "V2XAlarmServer";
// 记录道路播报的事件
private static final ConcurrentSet<V2XRoadEventEntity> showedEvents = new ConcurrentSet<>();
/**
* 获取当前车辆前方距离最近的道路事件
*/
public static V2XRoadEventEntity getDriveFrontAlarmEvent(
CopyOnWriteArrayList<V2XRoadEventEntity> v2XRoadEventEntityList,
MogoLocation currentLocation) {
try {
//Logger.d(TAG, "getDriveFrontAlarmEvent --- 1 ---" + currentLocation );
if (!showedEvents.isEmpty()) {
Iterator<V2XRoadEventEntity> iterator = showedEvents.iterator();
while (iterator.hasNext()) {
V2XRoadEventEntity next = iterator.next();
if (next == null) {
continue;
}
MarkerLocation poiLocation = next.getLocation();
if (poiLocation == null) {
continue;
}
if (isOutOfRange(poiLocation.getLon(), poiLocation.getLat(), currentLocation.getLongitude(), currentLocation.getLatitude(), currentLocation.getHeading())) {
iterator.remove();
}
}
}
//Logger.d(TAG, "getDriveFrontAlarmEvent --- 2 ---" + currentLocation);
if (currentLocation != null && v2XRoadEventEntityList != null) {
// 因为集合是按照距离排序后的所以这里检索出来第一个就发出警告
for (V2XRoadEventEntity v2XRoadEventEntity : v2XRoadEventEntityList) {
// 0、道路事件必须有朝向角度>=0;
//Logger.d(TAG, "entity:" + v2XRoadEventEntity.getLocation());
if (v2XRoadEventEntity.getLocation().getAngle() >= 0) {
// 计算车辆距离指定气泡的距离
MarkerLocation eventLocation = v2XRoadEventEntity.getLocation();
// 1、判断是否到达了触发距离,20 ~ 500,
double distance = v2XRoadEventEntity.getDistance();
//Logger.d(TAG, "distance:" + distance);
if (distance <= 500) {
if (EventTypeEnumNew.GHOST_PROBE.getPoiType().equals(v2XRoadEventEntity.getPoiType())) {
if (distance > 25) {
continue;
}
}
// 2、道路事件方向与当前行驶方向角度偏差《20度以内
double carBearing = currentLocation.getHeading();
double eventBearing = eventLocation.getAngle();
double diffAngle = DrivingDirectionUtils.getAngleDiff(carBearing, eventBearing);
//Logger.d(TAG, "car_bearing:" + carBearing + ",eventBearing:" + eventBearing + ",diffAngle:" + diffAngle);
if (diffAngle <= 20) {
// 3、计算当前车辆行驶方向与事件位置之间夹角《20度保证道路事件在车辆前方
double eventAngle = DrivingDirectionUtils.getDegreeOfCar2Poi(
currentLocation.getLongitude(),
currentLocation.getLatitude(),
eventLocation.getLon(),
eventLocation.getLat(),
(int) currentLocation.getHeading()
);
//Logger.d(TAG, "eventAngle:" + eventAngle);
if (0 <= eventAngle && eventAngle <= 20) {
if (showedEvents.contains(v2XRoadEventEntity)) {
return null;
}
//Logger.d(TAG, "showed---");
showedEvents.add(v2XRoadEventEntity);
return v2XRoadEventEntity;
}
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
Logger.w(TAG, "error: " + e.getMessage());
}
return null;
}
private static boolean isOutOfRange(double poi_lon, double poi_lat, double car_lon, double car_lat, double car_angle) {
return !isFrontOfCar(poi_lon, poi_lat, car_lon, car_lat, car_angle);
}
private static boolean isFrontOfCar(double poi_lon, double poi_lat, double car_lon, double car_lat, double car_angle) {
double degree = DrivingDirectionUtils.getDegreeOfCar2Poi(car_lon, car_lat, poi_lon, poi_lat, (int)car_angle);
return degree <= 90;
}
}

View File

@@ -0,0 +1,60 @@
package com.mogo.eagle.function.biz.v2x.v2n.bridge
import android.content.Context
import com.alibaba.android.arouter.launcher.ARouter
import com.mogo.eagle.core.data.map.MogoLocation
import com.mogo.eagle.function.biz.v2x.v2n.consts.MoGoV2XServicePaths
import com.mogo.eagle.core.utilcode.util.Utils
import com.mogo.eagle.function.biz.v2x.v2n.manager.IMoGoPersonWarnPolylineManager
import com.mogo.eagle.function.biz.v2x.v2n.manager.IMoGoStopPolylineManager
import com.mogo.eagle.function.biz.v2x.v2n.manager.IMoGoV2XMarkerManager
import com.mogo.eagle.function.biz.v2x.v2n.manager.IMoGoWarnPolylineManager
import java.lang.ref.WeakReference
import java.util.concurrent.atomic.AtomicReference
internal object BridgeApi {
private val context by lazy {
AtomicReference<WeakReference<Context>>(null)
}
val location by lazy {
AtomicReference<MogoLocation>()
}
private val v2xMarker by lazy {
ARouter.getInstance().build(MoGoV2XServicePaths.PATH_V2X_MARKER_MANAGER).navigation(context()) as? IMoGoV2XMarkerManager
}
private val v2xWarnPolyline by lazy {
ARouter.getInstance().build(MoGoV2XServicePaths.PATH_V2X_WARN_POLYLINE_MANAGER).navigation(
context()
) as? IMoGoWarnPolylineManager
}
private val v2xPersonWarnPolyline by lazy {
ARouter.getInstance().build(MoGoV2XServicePaths.PATH_V2X_PERSON_WARN_POLYLINE_MANAGER).navigation(
context()
) as? IMoGoPersonWarnPolylineManager
}
private val v2xStopPolyline by lazy {
ARouter.getInstance().build(MoGoV2XServicePaths.PATH_V2X_STOP_POLYLINE_MANAGER).navigation(
context()
) as? IMoGoStopPolylineManager
}
fun init(context: Context) {
BridgeApi.context.set(WeakReference(context))
}
fun context(): Context = context.get()?.get() ?: Utils.getApp()
fun v2xMarker() = v2xMarker
fun v2xWarnPolyline() = v2xWarnPolyline
fun v2xPersonWarnPolyline() = v2xPersonWarnPolyline
fun v2xStopPolyline() = v2xStopPolyline
}

View File

@@ -0,0 +1,41 @@
package com.mogo.eagle.function.biz.v2x.v2n.consts;
import androidx.annotation.Keep;
/**
* author : donghongyu
* e-mail : 1358506549@qq.com
* date : 2020/4/17 7:35 PM
* desc : 对外服务模块路径
* version: 1.0
* 使用方式:
* Arouter.getInstance().path("").navigate()
*/
@Keep
public class MoGoV2XServicePaths {
/**
* V2X 道路事件POI点
*/
@Keep
public static final String PATH_V2X_MARKER_MANAGER = "/v2xMarkerManager/api";
/**
* V2X 道路事件与车辆的连接线
*/
@Keep
public static final String PATH_V2X_WARN_POLYLINE_MANAGER = "/v2xWarnPolylineManager/api";
/**
* V2X 二轮车和行人连接线
*/
@Keep
public static final String PATH_V2X_PERSON_WARN_POLYLINE_MANAGER = "/v2xPersonWarnPolylineManager/api";
/**
* V2X 停止线连接线
*/
@Keep
public static final String PATH_V2X_STOP_POLYLINE_MANAGER = "/v2xStopPolylineManager/api";
}

View File

@@ -0,0 +1,25 @@
package com.mogo.eagle.function.biz.v2x.v2n.consts;
/**
* author : donghongyu
* e-mail : 1358506549@qq.com
* date : 2020-01-2114:10
* desc : V2X使用到的常量
* version: 1.0
*/
public class V2XConst {
/**
* V2X 场景广播 Action
*/
public static final String BROADCAST_SCENE_HANDLER_ACTION = "com.v2x.scene_handler_broadcast";
public static final String BROADCAST_SCENE_EXTRA_KEY = "V2XMessageEntity";
/**
* V2X预警日志tag
*/
public static final String LOG_NAME_WARN = "liyz";
}

View File

@@ -0,0 +1,27 @@
package com.mogo.eagle.function.biz.v2x.v2n.manager;
import android.content.Context;
import com.alibaba.android.arouter.facade.template.IProvider;
import com.mogo.eagle.core.data.v2x.DrawLineInfo;
import com.mogo.map.overlay.IMogoPolyline;
/**
* 绘制可变宽度和渐变的线,
*/
public interface IMoGoPersonWarnPolylineManager extends IProvider {
/**
* 绘制连接线,人物和二轮车
*
* @param context
* @param info
*/
void drawPersonWarnPolyline(Context context, DrawLineInfo info);
/**
* 移除连接线
*/
void clearLine();
IMogoPolyline getMogoPersonWarnPolyline();
}

View File

@@ -0,0 +1,27 @@
package com.mogo.eagle.function.biz.v2x.v2n.manager;
import android.content.Context;
import com.alibaba.android.arouter.facade.template.IProvider;
import com.mogo.eagle.core.data.v2x.DrawLineInfo;
import com.mogo.map.overlay.IMogoPolyline;
/**
* 绘制可变宽度和渐变的线
*/
public interface IMoGoStopPolylineManager extends IProvider {
/**
* 绘制连接线,目标车,与当前车辆间连线
*
* @param context
* @param info
*/
void drawStopPolyline(Context context, DrawLineInfo info);
/**
* 移除连接线
*/
void clearLine();
IMogoPolyline getMogoStopPolyline();
}

View File

@@ -0,0 +1,41 @@
package com.mogo.eagle.function.biz.v2x.v2n.manager;
import android.content.Context;
import com.alibaba.android.arouter.facade.template.IProvider;
import com.mogo.eagle.core.data.map.entity.V2XRoadEventEntity;
import com.mogo.map.marker.IMogoMarker;
import com.mogo.map.marker.IMogoMarkerClickListener;
import com.mogo.eagle.core.data.v2x.V2XMarkerCardResult;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* author : donghongyu
* e-mail : 1358506549@qq.com
* date : 2020/4/17 8:15 PM
* desc : V2X 涉及到的地图 POI 点的绘制
* version: 1.0
*/
public interface IMoGoV2XMarkerManager extends IProvider {
/**
* 获取所有的道路事件点,探路事件,返回结果是按照距离当前车辆从近到远排列好的
*
* @return 按从近到远排列好的道路事件
*/
CopyOnWriteArrayList<V2XRoadEventEntity> getV2XRoadEventEntityList();
/**
* 从探路数据和新鲜事儿的路况信息中解析出道路事件信息
*/
void analysisV2XRoadEvent(V2XMarkerCardResult markerCardResult);
/**
* 绘制正在预警的道路事件的POI点
* @param context
* @param roadEventEntity
* @return
*/
IMogoMarker drawableAlarmPOI(Context context, V2XRoadEventEntity roadEventEntity, IMogoMarkerClickListener clickListener);
}

View File

@@ -0,0 +1,27 @@
package com.mogo.eagle.function.biz.v2x.v2n.manager;
import android.content.Context;
import com.alibaba.android.arouter.facade.template.IProvider;
import com.mogo.eagle.core.data.v2x.DrawLineInfo;
import com.mogo.map.overlay.IMogoPolyline;
/**
* 绘制可变宽度和渐变的线
*/
public interface IMoGoWarnPolylineManager extends IProvider {
/**
* 绘制连接线,目标车,与当前车辆间连线
*
* @param context
* @param info
*/
void drawWarnPolyline(Context context, DrawLineInfo info);
/**
* 移除连接线
*/
void clearLine();
IMogoPolyline getMogoWarnPolyline();
}

View File

@@ -0,0 +1,87 @@
package com.mogo.eagle.function.biz.v2x.v2n.manager.impl;
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_V2X;
import android.content.Context;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.mogo.eagle.core.data.map.MogoLatLng;
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
import com.mogo.eagle.function.biz.v2x.v2n.consts.MoGoV2XServicePaths;
import com.mogo.eagle.function.biz.v2x.v2n.consts.V2XConst;
import com.mogo.eagle.core.data.v2x.DrawLineInfo;
import com.mogo.eagle.function.biz.v2x.v2n.manager.IMoGoPersonWarnPolylineManager;
import com.mogo.map.overlay.IMogoOverlayManager;
import com.mogo.map.overlay.IMogoPolyline;
import com.mogo.map.overlay.MogoPolylineOptions;
import java.util.ArrayList;
import java.util.List;
/**
* 绘制行人和二轮车连线
*/
@Route(path = MoGoV2XServicePaths.PATH_V2X_PERSON_WARN_POLYLINE_MANAGER)
public class MoGoPersonWarnPolylineManager implements IMoGoPersonWarnPolylineManager {
private static IMogoPolyline mMogoPolyline;
@Override
public void drawPersonWarnPolyline(Context context, DrawLineInfo info) {
if (info == null) {
return;
}
try {
if (mMogoPolyline != null) {
mMogoPolyline.remove();
}
// 连接线参数
MogoPolylineOptions options = new MogoPolylineOptions().setGps(true);
// 渐变色
List<Integer> colors = new ArrayList<>();
colors.add(0x0DE32F46);
colors.add(0xD9E32F46);
colors.add(0x0DE32F46);
// 线条粗细,渐变,渐变色值
CallerLogger.INSTANCE.d(M_V2X + V2XConst.LOG_NAME_WARN, "MoGoPersonWarnPolylineManager width = " + info.getWidth());
options.width(info.getWidth()).useGradient(true).colorValues(colors);
List<MogoLatLng> locations = info.getLocations();
for (int i = 0; i < locations.size(); i++) {
options.add(locations.get(i));
}
// 绘制线的对象
IMogoOverlayManager overlay = CallerMapUIServiceManager.INSTANCE.getOverlayManager();
if (overlay != null) {
mMogoPolyline = overlay.addPolyline(options);
mMogoPolyline.setTransparency(0.5f);
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void clearLine() {
if (mMogoPolyline != null) {
mMogoPolyline.remove();
mMogoPolyline = null;
}
}
@Override
public void init(Context context) {
}
/**
* @return 绘制连接线的对象
*/
@Override
public IMogoPolyline getMogoPersonWarnPolyline() {
return mMogoPolyline;
}
}

View File

@@ -0,0 +1,86 @@
package com.mogo.eagle.function.biz.v2x.v2n.manager.impl;
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_V2X;
import android.content.Context;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.mogo.eagle.core.data.map.MogoLatLng;
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
import com.mogo.eagle.function.biz.v2x.v2n.consts.MoGoV2XServicePaths;
import com.mogo.eagle.function.biz.v2x.v2n.consts.V2XConst;
import com.mogo.eagle.core.data.v2x.DrawLineInfo;
import com.mogo.eagle.function.biz.v2x.v2n.manager.IMoGoStopPolylineManager;
import com.mogo.map.overlay.IMogoOverlayManager;
import com.mogo.map.overlay.IMogoPolyline;
import com.mogo.map.overlay.MogoPolylineOptions;
import java.util.ArrayList;
import java.util.List;
/**
* 当前车辆与道路事件的连接线
*/
@Route(path = MoGoV2XServicePaths.PATH_V2X_STOP_POLYLINE_MANAGER)
public class MoGoStopPolylineManager implements IMoGoStopPolylineManager {
private static IMogoPolyline mMogoPolyline;
@Override
public void drawStopPolyline(Context context, DrawLineInfo info) {
if (info == null) {
return;
}
try {
if (mMogoPolyline != null) {
mMogoPolyline.remove();
}
// 连接线参数
MogoPolylineOptions options = new MogoPolylineOptions()
.setGps(true);
List<Integer> colors = new ArrayList<>();
colors.add(0x0DE32F46);
colors.add(0xD9E32F46);
colors.add(0x0DE32F46);
CallerLogger.INSTANCE.d(M_V2X + V2XConst.LOG_NAME_WARN, "MoGoStopPolylineManager roadWidth = " + info.getWidth());
// 线条粗细,渐变,渐变色值
// 当前车辆位置
options.width(info.getWidth() == 0.0 ? 60 : info.getWidth()).useGradient(true).colorValues(colors);
List<MogoLatLng> locations = info.getLocations();
for (int i = 0; i < locations.size(); i++) {
options.add(locations.get(i));
}
// 绘制线的对象
IMogoOverlayManager overlay = CallerMapUIServiceManager.INSTANCE.getOverlayManager();
if (overlay != null) {
mMogoPolyline = overlay.addPolyline(options);
}
if (mMogoPolyline != null) {
mMogoPolyline.setTransparency(0.5f);
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void clearLine() {
if (mMogoPolyline != null) {
mMogoPolyline.remove();
mMogoPolyline = null;
}
}
@Override
public void init(Context context) {
}
@Override
public IMogoPolyline getMogoStopPolyline() {
return mMogoPolyline;
}
}

View File

@@ -0,0 +1,153 @@
package com.mogo.eagle.function.biz.v2x.v2n.manager.impl;
import static com.mogo.commons.module.ServiceConst.CARD_TYPE_NOVELTY;
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_V2X;
import android.content.Context;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.mogo.cloud.commons.utils.CoordinateUtils;
import com.mogo.eagle.core.data.enums.EventTypeEnumNew;
import com.mogo.eagle.core.data.map.MogoLatLng;
import com.mogo.eagle.core.data.map.MogoLocation;
import com.mogo.eagle.core.data.map.entity.MarkerExploreWay;
import com.mogo.eagle.core.data.map.entity.MarkerLocation;
import com.mogo.eagle.core.data.map.entity.MarkerShowEntity;
import com.mogo.eagle.core.data.map.entity.V2XRoadEventEntity;
import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager;
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager;
import com.mogo.eagle.function.biz.v2x.v2n.consts.MoGoV2XServicePaths;
import com.mogo.eagle.function.biz.v2x.v2n.manager.IMoGoV2XMarkerManager;
import com.mogo.eagle.function.biz.v2x.v2n.marker.V2XMarkerAdapter;
import com.mogo.eagle.function.biz.v2x.v2n.utils.MapUtils;
import com.mogo.eagle.core.data.v2x.V2XMarkerCardResult;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
import com.mogo.map.marker.IMogoMarker;
import com.mogo.map.marker.IMogoMarkerClickListener;
import com.mogo.map.marker.MogoMarkerOptions;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* author : donghongyu
* e-mail : 1358506549@qq.com
* date : 2020/4/17 9:57 PM
* desc : V2X 涉及到的地图 POI 点的绘制
* version: 1.0
*/
@Route(path = MoGoV2XServicePaths.PATH_V2X_MARKER_MANAGER)
public class MoGoV2XMarkerManager implements IMoGoV2XMarkerManager {
private static final String TAG = "MoGoV2XMarkerManager";
// 记录所有的:新鲜事儿的道路事件点、探路事件
private final CopyOnWriteArraySet<V2XRoadEventEntity> mV2XRoadEventEntityArrayList = new CopyOnWriteArraySet<>();
@Override
public void init(Context context) {}
@Override
public CopyOnWriteArrayList<V2XRoadEventEntity> getV2XRoadEventEntityList() {
CopyOnWriteArrayList<V2XRoadEventEntity> roadEventEntities = new CopyOnWriteArrayList<>();
// 当前车辆数据
MogoLocation currentLocation = CallerChassisLocationGCJ02ListenerManager.INSTANCE.getChassisLocationGCJ02();
if (currentLocation != null) {
// 重新计算距离
for (V2XRoadEventEntity v2XRoadEventEntity : mV2XRoadEventEntityArrayList) {
// 事件位置
MarkerLocation location = v2XRoadEventEntity.getLocation();
if (location != null) {
float calculateDistance = CoordinateUtils.calculateLineDistance(location.getLat(), location.getLon(),
currentLocation.getLatitude(), currentLocation.getLongitude());
v2XRoadEventEntity.setDistance(calculateDistance);
}
roadEventEntities.add(v2XRoadEventEntity);
}
// 按照与当前车辆距离排序
for (int i = 0; i < roadEventEntities.size(); i++) {
for (int j = i; j > 0; j--) {
if (roadEventEntities.get(j).getDistance() < roadEventEntities.get(j - 1).getDistance()) {
V2XRoadEventEntity v2XRoadEventEntity = roadEventEntities.get(j - 1);
roadEventEntities.set(j - 1, roadEventEntities.get(j));
roadEventEntities.set(j, v2XRoadEventEntity);
}
}
}
}
return roadEventEntities;
}
@Override
public void analysisV2XRoadEvent(V2XMarkerCardResult markerCardResult) {
try {
//当没有预警提示的时候重新绘制地图POI点
if (markerCardResult != null) {
// 清除上次的道路事件, 这里注意,道路事件的触发和这里是异步操作会触发异常
mV2XRoadEventEntityArrayList.clear();
// 获取探路以及新鲜事儿
List<MarkerExploreWay> exploreWayList = markerCardResult.getExploreWay();
if (exploreWayList != null) {
for (MarkerExploreWay markerExploreWay : exploreWayList) {
if (EventTypeEnumNew.isRoadEvent(markerExploreWay.getPoiType())) {
MarkerLocation markerLocation = markerExploreWay.getLocation();
// 记录道路事件
V2XRoadEventEntity v2XRoadEventEntity = new V2XRoadEventEntity();
v2XRoadEventEntity.setLocation(markerLocation);
// 探路目前只有上报拥堵
String poi = markerExploreWay.getPoiType();
v2XRoadEventEntity.setPoiType(poi);
v2XRoadEventEntity.setNoveltyInfo(markerExploreWay);
v2XRoadEventEntity.setExpireTime(20000);
mV2XRoadEventEntityArrayList.add(v2XRoadEventEntity);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public IMogoMarker drawableAlarmPOI(Context context, V2XRoadEventEntity roadEventEntity, IMogoMarkerClickListener clickListener) {
try {
// 清除原来的大而全的新鲜事儿
if (roadEventEntity.getLocation() != null) {
// 道路事件,或者水波纹扩散效果
MogoMarkerOptions optionsRipple = new MogoMarkerOptions()
.data(roadEventEntity)
.latitude(roadEventEntity.getLocation().getLat())
.longitude(roadEventEntity.getLocation().getLon());
optionsRipple.anchor(0.5f, 0.5f);
MarkerShowEntity markerShowEntity = new MarkerShowEntity();
MarkerExploreWay markerExploreWay = roadEventEntity.getNoveltyInfo();
markerShowEntity.setBindObj(markerExploreWay);
markerShowEntity.setChecked(false);
markerShowEntity.setTextContent(markerExploreWay.getAddr());
markerShowEntity.setMarkerLocation(markerExploreWay.getLocation());
markerShowEntity.setMarkerType(CARD_TYPE_NOVELTY);
optionsRipple.icons(V2XMarkerAdapter.getV2XRoadEventViewGif(context, roadEventEntity));
optionsRipple.period(1);
IMogoMarker ret = Objects.requireNonNull(CallerMapUIServiceManager.INSTANCE.getMarkerService()).drawMarker(markerShowEntity);
// 当前Marker设置为最上面
if (ret != null) {
ret.setToTop();
}
// 缩放地图
MapUtils.zoomMap(
new MogoLatLng(roadEventEntity.getLocation().getLat(),
roadEventEntity.getLocation().getLon()
), context);
return ret;
} else {
CallerLogger.INSTANCE.e(M_V2X + TAG, "Location 必须进行初始化!!!!!");
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}

View File

@@ -0,0 +1,99 @@
package com.mogo.eagle.function.biz.v2x.v2n.manager.impl;
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_V2X;
import android.content.Context;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.mogo.eagle.core.data.map.MogoLatLng;
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
import com.mogo.eagle.function.biz.v2x.v2n.consts.MoGoV2XServicePaths;
import com.mogo.eagle.core.data.v2x.DrawLineInfo;
import com.mogo.eagle.function.biz.v2x.v2n.manager.IMoGoWarnPolylineManager;
import com.mogo.map.overlay.IMogoOverlayManager;
import com.mogo.map.overlay.IMogoPolyline;
import com.mogo.map.overlay.MogoPolylineOptions;
import java.util.ArrayList;
import java.util.List;
/**
* 当前车辆与道路事件的连接线
*/
@Route(path = MoGoV2XServicePaths.PATH_V2X_WARN_POLYLINE_MANAGER)
public class MoGoWarnPolylineManager implements IMoGoWarnPolylineManager {
private static IMogoPolyline mMogoPolyline;
private static final String TAG = "V2XWarningMarker";
@Override
public void drawWarnPolyline(Context context, DrawLineInfo info) {
if (info == null) {
return;
}
try {
if (mMogoPolyline != null) {
mMogoPolyline.remove();
}
// 连接线参数
MogoPolylineOptions options = new MogoPolylineOptions()
.setGps(true);
List<Integer> colors = new ArrayList<>();
if (info.isHasStopLines()) {
colors.add(0x0D3036FF);
colors.add(0xD93036FF);
colors.add(0x0D3036FF);
} else {
colors.add(0x0DE32F46);
colors.add(0xD9E32F46);
colors.add(0x0DE32F46);
}
CallerLogger.INSTANCE.d(M_V2X + TAG, "MoGoWarnPolylineManager roadWidth = " + info.getWidth());
// 线条粗细,渐变,渐变色值
options.width(info.getWidth() == 0.0 ? 60 : info.getWidth()).useGradient(true).colorValues(colors);
List<MogoLatLng> locations = info.getLocations();
for (int i = 0; i < locations.size(); i++) {
options.add(locations.get(i));
}
// 绘制线的对象
IMogoOverlayManager overlay = CallerMapUIServiceManager.INSTANCE.getOverlayManager();
if (overlay != null) {
mMogoPolyline = overlay.addPolyline(options);
}
if (mMogoPolyline != null) {
mMogoPolyline.setTransparency(0.5f);
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void clearLine() {
if (mMogoPolyline != null) {
mMogoPolyline.remove();
mMogoPolyline = null;
} else {
CallerLogger.INSTANCE.d(M_V2X + TAG, "mMogoPolyline==null");
}
}
@Override
public void init(Context context) {
}
/**
* @return 绘制连接线的对象
*/
@Override
public IMogoPolyline getMogoWarnPolyline() {
return mMogoPolyline;
}
}

View File

@@ -0,0 +1,135 @@
package com.mogo.eagle.function.biz.v2x.v2n.marker;
import android.content.Context;
import android.graphics.Bitmap;
import com.mogo.eagle.core.data.enums.EventTypeEnumNew;
import com.mogo.eagle.core.data.map.entity.V2XRoadEventEntity;
import com.mogo.eagle.core.function.v2x.R;
import com.mogo.eagle.function.biz.v2x.v2n.view.V2XMarkerRoadEventView;
import java.util.ArrayList;
/**
* author : donghongyu
* e-mail : 1358506549@qq.com
* date : 2020-01-1015:55
* desc : V2X 地图气泡
* version: 1.0
*/
public class V2XMarkerAdapter {
/**
* 返回道路事件
*/
public static Bitmap getV2XRoadEventMarkerView(Context context, V2XRoadEventEntity alarmInfo, int imageRes) {
return new V2XMarkerRoadEventView(context, alarmInfo).setBackground(imageRes).getView();
}
/**
* 返回道路事件gif序列图集合
*/
public static ArrayList<Bitmap> getV2XRoadEventViewGif(Context context, V2XRoadEventEntity alarmInfo) {
ArrayList<Bitmap> bitmapArrayList;
if (EventTypeEnumNew.ALERT_TRAFFIC_LIGHT_SUGGEST.getPoiType().equals(alarmInfo.getPoiType())
|| EventTypeEnumNew.ALERT_TRAFFIC_LIGHT_WARNING.getPoiType().equals(alarmInfo.getPoiType())
|| EventTypeEnumNew.FOURS_BLOCK_UP.getPoiType().equals(alarmInfo.getPoiType())
|| EventTypeEnumNew.ALERT_CAR_TROUBLE_WARNING.getPoiType().equals(alarmInfo.getPoiType())) {
bitmapArrayList = getV2XRoadEventOrangeMarkerView(context, alarmInfo);
} else {
bitmapArrayList = getV2XRoadEventRedMarkerView(context, alarmInfo);
}
return bitmapArrayList;
}
/**
* 返回红色扩散效果的序列
*/
public static ArrayList<Bitmap> getV2XRoadEventRedMarkerView(Context context, V2XRoadEventEntity alarmInfo) {
ArrayList<Bitmap> icons = new ArrayList<>();
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00011));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00012));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00013));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00014));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00015));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00016));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00017));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00018));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00019));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00020));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00021));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00022));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00023));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00024));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00025));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00026));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00027));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00028));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00029));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00030));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00031));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00032));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00033));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00034));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00035));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00036));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00037));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00038));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00039));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00040));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00041));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00042));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00043));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00044));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00045));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00046));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00047));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_red_00048));
return icons;
}
/**
* 返回橘色色扩散效果的序列
*/
public static ArrayList<Bitmap> getV2XRoadEventOrangeMarkerView(Context context, V2XRoadEventEntity alarmInfo) {
ArrayList<Bitmap> icons = new ArrayList<>();
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00011));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00012));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00013));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00014));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00015));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00016));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00017));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00018));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00019));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00020));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00021));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00022));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00023));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00024));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00025));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00026));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00027));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00028));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00029));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00030));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00031));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00032));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00033));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00034));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00035));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00036));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00037));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00038));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00039));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00040));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00041));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00042));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00043));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00044));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00045));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00046));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00047));
icons.add(V2XMarkerAdapter.getV2XRoadEventMarkerView(context, alarmInfo, R.drawable.v_to_x_warning_circle_orange_00048));
return icons;
}
}

View File

@@ -0,0 +1,118 @@
package com.mogo.eagle.function.biz.v2x.v2n.network
import com.elegant.network.utils.GsonUtil
import com.elegant.network.utils.SignUtil
import com.elegant.utils.CommonUtils
import com.mogo.cloud.network.RetrofitFactory
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
import com.mogo.commons.AbsMogoApplication
import com.mogo.commons.constants.HostConst
import com.mogo.commons.network.ParamsUtil
import com.mogo.eagle.core.data.v2x.V2XEventData
import com.mogo.eagle.core.data.v2x.V2XLocation
import com.mogo.eagle.core.data.v2x.V2XMarkerResponse
import com.mogo.eagle.function.biz.v2x.v2n.network.api.V2XApiService
import com.mogo.eagle.function.biz.v2x.v2n.network.body.V2XRefreshEntity
import com.mogo.eagle.function.biz.v2x.v2n.network.callback.IV2XRefreshCallback
import com.mogo.eagle.core.network.MoGoRetrofitFactory
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
import com.mogo.eagle.core.utilcode.util.DeviceUtils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
internal class V2XRefreshModel {
companion object {
private const val TAG = "V2XRefreshModel"
fun querySnapshot(
longitude: Double,
latitude: Double,
callback: IV2XRefreshCallback<V2XMarkerResponse>?
): Disposable? {
val retrofit = RetrofitFactory.getInstance(HostConst.getEagleHost()) ?: return null
return retrofit
.create(V2XApiService::class.java)
.querySnapshotSync(buildParams(longitude, latitude))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ data ->
if (data == null) {
callback?.onFail("returned data is null.")
return@subscribe
}
if (data.code != 0 && data.code != 200) {
callback?.onFail("code:${data.code}, msg: ${data.msg}")
} else {
callback?.onSuccess(data)
}
}, {
callback?.onFail(it.message)
})
}
private fun buildParams(
longitude: Double,
latitude: Double,
): Map<String, Any> = mutableMapOf<String, Any>().apply {
putAll(ParamsUtil.getStaticParams().let {
val handled = mutableMapOf<String, Any>()
it.asIterable().forEach { itx ->
val value = itx.value
if (value != null) {
handled[itx.key] = value
}
}
handled
})
this["netType"] = CommonUtils.getNetworkType(AbsMogoApplication.getApp())
this["cellId"] = DeviceUtils.getCellId() ?: ""
this["sn"] = MoGoAiCloudClientConfig.getInstance().sn
this["ticket"] = MoGoAiCloudClientConfig.getInstance().token
this["sig"] = SignUtil.createSign(this, "JGjZx6")
this["data"] = GsonUtil.jsonFromObject(V2XRefreshEntity().apply {
limit = 999
location = V2XLocation().also {
it.lat = latitude
it.lon = longitude
}
radius = 1000
dataType.add("CARD_TYPE_ROAD_CONDITION")
viewPush = true
})
}
private var v2xEventDisposable: Disposable? = null
fun roadEventDispose(){
if (v2xEventDisposable != null && !v2xEventDisposable!!.isDisposed) {
v2xEventDisposable!!.dispose()
}
}
fun getRoadEvents(lineId: String, sn: String, onSuccess:((List<V2XEventData>?) -> Unit)){
v2xEventDisposable = MoGoRetrofitFactory.getInstance(HostConst.getHost())
.create(V2XApiService::class.java)
.queryAllV2XEventsByLineId(lineId, sn)
.map {
if (it.code == 200 || it.code == 0) {
CallerLogger.d(SceneConstant.M_V2X + TAG, "请求成功size为${it.result?.v2XEventList?.size}")
return@map it.result?.v2XEventList
} else {
CallerLogger.d(SceneConstant.M_V2X + TAG, "请求失败code为${it.code}")
return@map ArrayList()
}
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
onSuccess.invoke(it)
}
}
}
}

View File

@@ -0,0 +1,18 @@
package com.mogo.eagle.function.biz.v2x.v2n.network.api
import com.mogo.eagle.core.data.v2x.V2XEventResult
import com.mogo.eagle.core.data.v2x.V2XMarkerResponse
import io.reactivex.Maybe
import io.reactivex.Observable
import retrofit2.http.*
internal interface V2XApiService {
@FormUrlEncoded
@POST("eagle-eye-dns/yycp-launcherSnapshot/launcherSnapshot/querySnapshotSync")
fun querySnapshotSync(@FieldMap parameters: Map<String, @JvmSuppressWildcards Any>): Maybe<V2XMarkerResponse?>
@GET("/eagleEye-mis/config/queryV2NInformation")
fun queryAllV2XEventsByLineId(@Query("lineId") lineId: String, @Query("sn") sn: String): Observable<V2XEventResult>
}

View File

@@ -0,0 +1,39 @@
package com.mogo.eagle.function.biz.v2x.v2n.network.body
import androidx.annotation.Keep
import com.mogo.eagle.core.data.v2x.V2XLocation
/**
* 刷新地图信息接口
*/
@Keep
internal class V2XRefreshEntity {
@JvmField
var dataType: MutableList<String> = mutableListOf() // 要查询的类型
@JvmField
var limit = 50 // 请求数量
@JvmField
var radius = 2000 // 地理围栏半径(米)
@JvmField
var location // 坐标
: V2XLocation? = null
@JvmField
var sn: String? = null
@JvmField
var onlyFocus // 是否仅查询已关注的好友
= false
@JvmField
var onlySameCity // 是否仅查询注册城市相同的同城用户
= false
@JvmField
var viewPush // 是否走V2X通道 true-401011false -401001
= false
@JvmField
var onlyRealUser = false
}

View File

@@ -0,0 +1,24 @@
package com.mogo.eagle.function.biz.v2x.v2n.network.callback
import com.mogo.eagle.core.data.v2x.V2XEvent
interface IV2XCallback {
/**
* 获取到V2X事件成功回调
* @param event
* - 参数说明:目前此参数支持以下类型
* - [V2XEvent.ForwardsWarning]: 路口碰撞预警、盲区预警等预警事件, 数据实体取自[V2XEvent.ForwardsWarning.data]
* - [V2XEvent.Road]: 道路事件, 数据实体取自[V2XEvent.Road.data]
* - [V2XEvent.Warning]: 预警目标物事件, 数据实体取自[V2XEvent.Warning.data]
* - [V2XEvent.Marker]: 道路标记事件, 数据实体取自[V2XEvent.Marker.data]
*/
fun onAck(event: V2XEvent)
/**
* V2X事件获取过程中出现的异常信息用于问题排查
* @param msg 异常信息
*/
fun onFail(msg: String)
}

View File

@@ -0,0 +1,11 @@
package com.mogo.eagle.function.biz.v2x.v2n.network.callback
/**
* 刷新回调
*/
internal interface IV2XRefreshCallback<T> {
fun onSuccess(result: T)
fun onFail(msg: String?)
}

View File

@@ -0,0 +1,35 @@
package com.mogo.eagle.function.biz.v2x.v2n.receiver
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.mogo.eagle.core.data.map.entity.V2XMessageEntity
import com.mogo.eagle.function.biz.v2x.v2n.consts.V2XConst
import com.mogo.eagle.function.biz.v2x.v2n.scenario.impl.V2XScenarioManager
class SceneBroadcastReceiver : BroadcastReceiver() {
companion object {
fun register(context: Context) {
val localReceiver = SceneBroadcastReceiver()
val localBroadcastManager = LocalBroadcastManager.getInstance(context)
val intentFilter = IntentFilter()
intentFilter.addAction(V2XConst.BROADCAST_SCENE_HANDLER_ACTION)
localBroadcastManager.registerReceiver(localReceiver, intentFilter)
}
}
override fun onReceive(context: Context?, intent: Intent?) {
try {
val v2XMessageEntity =
intent?.getSerializableExtra(V2XConst.BROADCAST_SCENE_EXTRA_KEY) as? V2XMessageEntity<*>
v2XMessageEntity?.let {
V2XScenarioManager.getInstance().handlerMessage(it)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}

View File

@@ -0,0 +1,198 @@
package com.mogo.eagle.function.biz.v2x.v2n.remove
import android.os.Handler
import android.os.HandlerThread
import android.util.Log
import com.mogo.cloud.commons.utils.CoordinateUtils
import com.mogo.eagle.core.data.map.MogoLocation
import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationWGS84ListenerManager
import com.mogo.eagle.core.utilcode.util.DrivingDirectionUtils
import com.mogo.map.marker.IMogoMarker
import com.mogo.map.overlay.IMogoPolyline
import kotlinx.coroutines.Runnable
import java.util.*
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicReference
data class MarkerWrapper(val id: String, val lon: Double, val lat: Double, val coordinateType: Int, var markers: ArrayList<IMogoMarker>? = null, var lines: ArrayList<IMogoPolyline>? = null) {
fun addLine(line: IMogoPolyline) {
var ll = this.lines
if (ll == null) {
ll = ArrayList()
this.lines = ll
}
ll.add(line)
}
fun addMarker(marker: IMogoMarker) {
var mm = this.markers
if (mm == null) {
mm = ArrayList()
this.markers = mm
}
mm.add(marker)
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as MarkerWrapper
if (id != other.id) return false
return true
}
override fun hashCode(): Int {
return id.hashCode()
}
}
object MarkerRemoveManager {
private const val TAG = "MarkerManager"
private val showedMarkers by lazy { LinkedList<MarkerWrapper>() }
private val toRemoveMakers by lazy { LinkedList<MarkerWrapper>() }
private val isFirstAdd by lazy { AtomicBoolean(false) }
private val elapsedDistances by lazy { ConcurrentHashMap<MarkerWrapper, Double>() }
private val lastCarLocation by lazy { AtomicReference<Pair<Double, Double>>() }
private val lastGpsLocation by lazy { AtomicReference<Pair<Double, Double>>() }
private val checkTask = object : Runnable {
override fun run() {
try {
Log.d(TAG, "--- checkTask --- 1 ---")
if (lastCarLocation.get() == null) {
return
}
Log.d(TAG, "--- checkTask --- 2 ---")
if (lastGpsLocation.get() == null) {
return
}
Log.d(TAG, "--- checkTask --- 3 ---")
val toRemove = toRemoveMakers.iterator()
val carLoc = AtomicReference<MogoLocation>()
while (toRemove.hasNext()) {
val marker = toRemove.next()
if (carLoc.get() == null) {
carLoc.set(if (marker.coordinateType == 0) {
//高德坐标
CallerChassisLocationGCJ02ListenerManager.getChassisLocationGCJ02()
} else {
//高精坐标
CallerChassisLocationWGS84ListenerManager.getChassisLocationWGS84()
})
}
val currentLocation = carLoc.get()
val lastLocation = if (marker.coordinateType == 0) lastCarLocation.get() else lastGpsLocation.get()
if (currentLocation != null && lastLocation != null) {
val delta = CoordinateUtils.calculateLineDistance(currentLocation.longitude, currentLocation.latitude, lastLocation.first, lastLocation.second)
Log.d(TAG, "--- checkTask --- 4 ---:delta:$delta, id:${marker.id}")
var elapsed = elapsedDistances[marker]
if (elapsed == null) {
elapsed = delta.toDouble()
} else {
elapsed += delta
}
Log.d(TAG, "--- checkTask --- 5 ---:delta:$delta, elapsed:${elapsed}, id: ${marker.id}")
if (elapsed >= 200) {
var removeMarkerError = false
marker.markers?.forEach {
try {
Log.e(TAG, "--- checkTask --- remove marker: $it, id: ${marker.id}")
it.setVisible(false)
it.destroy()
} catch (t: Throwable) {
t.printStackTrace()
removeMarkerError = true
Log.e(TAG, "--- checkTask --- remove marker error:${t.message}, id: ${marker.id}")
}
}
var removeLineError = false
marker.lines?.forEach {
try {
it.isVisible = false
Log.e(TAG, "--- checkTask --- remove line : $it, id:${marker.id}")
it.destroy()
} catch (t: Throwable) {
t.printStackTrace()
removeLineError = true
Log.e(TAG, "--- checkTask --- remove line error:${t.message}, id: ${marker.id}")
}
}
if (!removeLineError && !removeMarkerError) {
toRemove.remove()
synchronized(elapsedDistances) {
elapsedDistances.remove(marker)
}
}
} else {
elapsedDistances[marker] = elapsed
}
}
}
val iterator = showedMarkers.iterator()
while (iterator.hasNext()) {
val marker = iterator.next()
if (carLoc.get() == null) {
carLoc.set(if (marker.coordinateType == 0) {
//高德坐标
CallerChassisLocationGCJ02ListenerManager.getChassisLocationGCJ02()
} else {
//高精坐标
CallerChassisLocationWGS84ListenerManager.getChassisLocationWGS84()
})
}
val location = carLoc.get()
if (location != null) {
val angle = DrivingDirectionUtils.getDegreeOfCar2Poi2(location.longitude, location.latitude, marker.lon, marker.lat, location.heading)
if (angle >= 90) {
iterator.remove()
synchronized(toRemoveMakers) {
toRemoveMakers.offer(marker)
}
}
}
}
} catch (t: Throwable) {
t.printStackTrace()
} finally {
val gcInfo = CallerChassisLocationGCJ02ListenerManager.getChassisLocationGCJ02()
lastCarLocation.set((gcInfo?.longitude ?: 0.0) to (gcInfo?.latitude ?: 0.0))
val wgsInfo = CallerChassisLocationWGS84ListenerManager.getChassisLocationWGS84()
lastGpsLocation.set((wgsInfo?.longitude ?: 0.0) to (wgsInfo?.latitude ?: 0.0))
handler.postDelayed(this, 1000)
}
}
}
private val handler by lazy {
val thread = HandlerThread("check_marker_expired")
thread.start()
Handler(thread.looper)
}
fun addMarker(marker: MarkerWrapper) {
Log.d(TAG, "=== addMarker ====: $marker")
synchronized(showedMarkers) {
showedMarkers.offer(marker)
}
if (isFirstAdd.compareAndSet(false,true)) {
handler.postDelayed(checkTask, 1000)
}
}
}

View File

@@ -0,0 +1,41 @@
package com.mogo.eagle.function.biz.v2x.v2n.scenario;
import com.mogo.eagle.core.data.map.entity.V2XMessageEntity;
/**
* author : donghongyu
* e-mail : 1358506549@qq.com
* date : 2020/5/15 4:13 PM
* desc : V2X安全驾驶场景接口
* version: 1.0
*/
public interface IV2XScenario {
/**
* 展示场景
*/
void show();
/**
* 关闭场景
*/
void close();
/**
* 绘制POI
*/
void drawPOI();
/**
* 清除POI
*/
void clearPOI();
/**
* 是否是相同的场景,如果是说明重复的场景,需要根据场景进行不同的处理
*
* @param v2XMessageEntity 要比较的场景
* @return true-相同的场景false-不同场景
*/
boolean isSameScenario(V2XMessageEntity v2XMessageEntity);
}

View File

@@ -0,0 +1,15 @@
package com.mogo.eagle.function.biz.v2x.v2n.scenario;
import com.mogo.eagle.core.data.map.entity.V2XMessageEntity;
/**
* author : donghongyu
* e-mail : 1358506549@qq.com
* date : 2020/5/15 3:47 PM
* desc : V2X安全驾驶场景管理
* version: 1.0
*/
public interface IV2XScenarioManager {
void handlerMessage(V2XMessageEntity v2XMessageEntity);
}

View File

@@ -0,0 +1,66 @@
package com.mogo.eagle.function.biz.v2x.v2n.scenario.impl;
import androidx.annotation.Nullable;
import com.mogo.eagle.core.data.map.entity.V2XMessageEntity;
import com.mogo.eagle.function.biz.v2x.v2n.scenario.IV2XScenario;
import com.mogo.eagle.function.biz.v2x.v2n.scenario.view.IV2XMarker;
import java.util.concurrent.atomic.AtomicReference;
/**
* author : donghongyu
* e-mail : 1358506549@qq.com
* date : 2020/5/15 5:01 PM
* desc :
* version: 1.0
*/
public abstract class AbsV2XScenario<T> implements IV2XScenario {
protected String TAG = "AbsV2XScenario";
private IV2XMarker mV2XMarker;
private final AtomicReference<V2XMessageEntity> mV2XMessageEntity = new AtomicReference<>();
protected AbsV2XScenario() {
}
public abstract void init(@Nullable V2XMessageEntity<T> v2XMessageEntity);
@Override
public void close() {
// clearPOI();
}
/**
* 释放资源
*/
public void release() {
mV2XMessageEntity.set(null);
mV2XMarker = null;
}
public IV2XMarker getV2XMarker() {
return mV2XMarker;
}
public void setV2XMarker(@Nullable IV2XMarker mV2XMarker) {
this.mV2XMarker = mV2XMarker;
}
public void setV2XMessageEntity(@Nullable V2XMessageEntity<T> mV2XMessageEntity) {
this.mV2XMessageEntity.set(mV2XMessageEntity);
}
public V2XMessageEntity<T> getV2XMessageEntity() {
return mV2XMessageEntity.get();
}
@Override
public boolean isSameScenario(@Nullable V2XMessageEntity v2XMessageEntity) {
V2XMessageEntity old = mV2XMessageEntity.get();
if (old == null) {
return false;
}
return old.equals(v2XMessageEntity);
}
}

View File

@@ -0,0 +1,101 @@
package com.mogo.eagle.function.biz.v2x.v2n.scenario.impl;
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_V2X;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.mogo.commons.module.status.MogoStatusManager;
import com.mogo.eagle.core.data.config.HmiBuildConfig;
import com.mogo.eagle.core.data.map.entity.V2XMessageEntity;
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager;
import com.mogo.eagle.function.biz.v2x.v2n.scenario.IV2XScenarioManager;
import com.mogo.eagle.function.biz.v2x.v2n.scenario.scene.road.V2XRoadEventScenario;
import com.mogo.eagle.function.biz.v2x.v2n.scenario.scene.warning.V2XFrontWarningScenario;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
import com.mogo.eagle.core.utilcode.util.ThreadUtils;
import com.mogo.map.uicontroller.IMogoMapUIController;
import com.mogo.map.uicontroller.VisualAngleMode;
/**
* author : donghongyu
* e-mail : 1358506549@qq.com
* date : 2020/5/15 4:22 PM
* desc : 场景管理的分发
* version: 1.0
*/
public class V2XScenarioManager implements IV2XScenarioManager {
private static V2XScenarioManager mV2XScenarioManager;
private static final String TAG = "V2XScenarioManager";
private AbsV2XScenario mV2XScenario = null;
private V2XScenarioManager() {
}
public static V2XScenarioManager getInstance() {
if (mV2XScenarioManager == null) {
synchronized (V2XScenarioManager.class) {
if (mV2XScenarioManager == null) {
mV2XScenarioManager = new V2XScenarioManager();
}
}
}
return mV2XScenarioManager;
}
@Override
public void handlerMessage(V2XMessageEntity v2XMessageEntity) {
CallerLogger.INSTANCE.d(M_V2X + TAG, "处理V2X场景" + (v2XMessageEntity == null ? "null" : v2XMessageEntity.toString()));
try {
synchronized (V2XScenarioManager.class) {
// 展示
ThreadUtils.runOnUiThread(() -> {
// 提取之前存储的场景
if (v2XMessageEntity != null) {
// 如果没有拿到之前的,根据类型分发
switch (v2XMessageEntity.getType()) {
case V2XMessageEntity.V2XTypeEnum.ALERT_ROAD_WARNING:
mV2XScenario = new V2XRoadEventScenario();
break;
case V2XMessageEntity.V2XTypeEnum.ALERT_THE_FRONT_WEAKNESS:
if (HmiBuildConfig.isShowCloudWeaknessTrafficView) { //默认关闭云端弱势交通
sceneChange();
if (MogoStatusManager.getInstance().isVrMode()) {
mV2XScenario = new V2XFrontWarningScenario();
} else {
mV2XScenario = null;
}
}
break;
default:
mV2XScenario = null;
CallerLogger.INSTANCE.e(M_V2X + TAG, "当前V2X消息类型未定义:" + v2XMessageEntity);
return;
}
// 展示最新的消息
if (mV2XScenario != null) {
mV2XScenario.init(v2XMessageEntity);
}
}
});
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* http://wiki.zhidaohulian.com/pages/viewpage.action?pageId=52833468
* 道路事件触发后,切换到中景
*/
private void sceneChange() {
IMogoMapUIController mapUiController = CallerMapUIServiceManager.INSTANCE.getMapUIController();
if (mapUiController != null && mapUiController.getCurrentMapVisualAngle() != VisualAngleMode.MODE_MEDIUM_SIGHT) {
mapUiController.changeMapVisualAngle(VisualAngleMode.MODE_MEDIUM_SIGHT, null);
}
}
}

View File

@@ -0,0 +1,220 @@
package com.mogo.eagle.function.biz.v2x.v2n.scenario.scene.airoad
import android.animation.ArgbEvaluator
import android.graphics.Color
import android.os.Handler
import android.os.Looper
import android.view.animation.DecelerateInterpolator
import androidx.core.util.Pair
import com.mogo.cloud.commons.utils.*
import com.mogo.eagle.core.data.map.MogoLatLng
import com.mogo.eagle.core.data.map.entity.V2XRoadEventEntity
import com.mogo.eagle.core.function.call.autopilot.*
import com.mogo.eagle.core.function.call.map.*
import com.mogo.eagle.function.biz.v2x.v2n.scenario.scene.road.V2XAiRoadEventMarker
import com.mogo.eagle.core.utilcode.mogo.logger.Logger
import com.mogo.eagle.core.utilcode.util.DrivingDirectionUtils
import com.mogo.map.MogoMap
import com.mogo.map.overlay.IMogoPolyline
import com.mogo.map.overlay.MogoPolylineOptions
import java.util.*
import java.util.concurrent.atomic.AtomicReference
import java.util.concurrent.ConcurrentHashMap
import com.mogo.eagle.function.biz.v2x.v2n.remove.MarkerRemoveManager
import com.mogo.eagle.function.biz.v2x.v2n.remove.MarkerWrapper
/**
* Ai云道路施工事件道路颜色标记类
*/
class AiRoadMarker {
companion object {
@JvmField
val aiMakers = ConcurrentHashMap<String, AiRoadMarker>()
}
private val TAG = "AiRoadMarker"
private val marker by lazy { AtomicReference<Marker>() }
private val overlayManager by lazy {
CallerMapUIServiceManager.getOverlayManager()
}
private val START_COLOR = Color.parseColor("#002ABAD9")
private val END_COLOR = Color.parseColor("#66FF7A30")
private val roadMarker by lazy { V2XAiRoadEventMarker() }
private val line = AtomicReference<IMogoPolyline>()
private val handler by lazy {
Handler(Looper.getMainLooper())
}
private val checkExpiredTask = Runnable {
val poi = this.marker.get()
val car = CallerChassisLocationWGS84ListenerManager.getChassisLocationWGS84()
if (poi != null && car != null) {
val distance = CoordinateUtils.calculateLineDistance(car.longitude, car.latitude, poi.poi_lon, poi.poi_lat)
if (distance < 500) {
unMarker(poi)
}
}
}
private val options by lazy {
MogoPolylineOptions().apply {
zIndex(40000f)
setGps(true)
width(50f)
useGradient(true)
}
}
fun marker(marker: Marker, drawMarker: Boolean, drawRoadLine: Boolean = false) {
val location = CallerChassisLocationWGS84ListenerManager.getChassisLocationWGS84() ?: return
this.marker.set(marker)
val wrapper = MarkerWrapper(marker.id, marker.poi_lon, marker.poi_lat, 1, null, null)
if (drawMarker) {
marker.entity?.apply { roadMarker.drawMarkers(this, wrapper) }
}
if (drawRoadLine) {
//施工中心点前方的自车行驶方向上300米距离
val l1 = MogoMap.getInstance().mogoMap.getCenterLineRangeInfo(marker.poi_lon, marker.poi_lat, location.heading.toFloat(), 300f)
//施工中心点后方的自车行驶方向上300米距离
Logger.d(TAG, "--- marker --- 3 --- l1: $l1")
val l2 = MogoMap.getInstance().mogoMap.getCenterLineRangeInfo(marker.poi_lon, marker.poi_lat, location.heading.toFloat(), -300f)
if (l1.points.isEmpty() || l2.points.isEmpty()) {
Logger.d(TAG, "--- marker --- 3 --- return ----")
return
}
Logger.d(TAG, "--- marker --- 4 --- l2: $l2")
val points = LinkedList<MogoLatLng>()
if (l2 != null && l2.points.isNotEmpty()) {
points.addAll(l2.points.reversed().map {
MogoLatLng(it.second, it.first)
})
}
val centerX= marker.poi_lon
val centerY = marker.poi_lat
Logger.d(TAG, "--- marker --- 5 --- marker: $marker")
val farthestPoint = marker.polygon?.let {
var find: Pair<Double, Double> = Pair(centerX, centerY)
var min = Long.MAX_VALUE
for (p in it) {
val angle = DrivingDirectionUtils.getDegreeOfCar2Poi2(centerX, centerY, p.first, p.second, location.heading)
if (angle < min) {
min = angle
find = p
}
}
MogoLatLng(find.second, find.first)
} ?: MogoLatLng(centerY, centerX)
marker.farthestPoint = Pair(farthestPoint.lon, farthestPoint.lat)
Logger.d(TAG, "--- marker --- 6 --- marker: $marker")
if (l1 != null && l1.points.isNotEmpty()) {
for (l in l1.points) {
if (DrivingDirectionUtils.getDegreeOfCar2Poi2(farthestPoint.lon, farthestPoint.lat, l.first, l.second, (location.heading + 180)) < 90L) {
points.add(l.let { MogoLatLng(it.second, it.first) })
}
}
}
if (points.size <= 1) {
return
}
val evaluator = ArgbEvaluator()
val interceptor = DecelerateInterpolator(1.5f)
val total = points.size
val colors = ArrayList<Int>()
(0..total).forEach { i ->
colors += evaluator.evaluate(interceptor.getInterpolation(i * 1f / total), START_COLOR, END_COLOR) as Int
}
var line = line.get()
options.points(points)
options.colorValues(colors)
Logger.d(TAG, "--- marker --- 7 --- points: ${points.size}")
if (line == null || line.isDestroyed) {
val l = overlayManager?.addPolyline(options)
this.line.set(l)
line = l
} else {
line.setOption(options)
}
if (!line.isVisible) {
line.isVisible = true
}
if (line != null) {
wrapper.addLine(line)
}
}
MarkerRemoveManager.addMarker(wrapper)
}
private fun removeLine() {
val old = line.get()
Logger.d(TAG, "--- removeRedLine --- 1 ---")
if (old != null) {
Logger.d(TAG, "--- removeRedLine --- 2 ---")
line.set(null)
old.isVisible = false
old.remove()
}
}
private fun unMarker(marker: Marker) {
Logger.d(TAG, "--- unMarker ---")
this.marker.set(null)
removeLine()
roadMarker.removeMarkers()
handler.removeCallbacks(checkExpiredTask)
}
fun receive() {
Logger.d(TAG, "receive --- 1 ---")
val poi = this.marker.get()
val car = CallerChassisLocationWGS84ListenerManager.getChassisLocationWGS84()
if (poi != null && car != null) {
val distance = CoordinateUtils.calculateLineDistance(car.longitude, car.latitude, poi.poi_lon, poi.poi_lat)
Logger.d(TAG, "receive --- 2 ---:car:[${car.longitude}, ${car.latitude}] -> poi:[${poi.poi_lon}, ${poi.poi_lat}] --> distance:$distance")
if (distance < 500) {
checkExpired()
} else {
handler.removeCallbacks(checkExpiredTask)
}
} else {
if (poi != null) {
checkExpired()
}
}
}
private fun checkExpired() {
handler.removeCallbacks(checkExpiredTask)
handler.postDelayed(checkExpiredTask, 10000)
}
data class Marker(
val id: String,
val poiType: String,
val poi_lat: Double,
val poi_lon: Double,
val poi_angle: Double,
val polygon: List<Pair<Double, Double>>? = null,
var farthestPoint: Pair<Double, Double>? = null,
var entity: V2XRoadEventEntity? = null
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as Marker
if (id != other.id) return false
return true
}
override fun hashCode(): Int {
return id.hashCode()
}
}
}

View File

@@ -0,0 +1,76 @@
package com.mogo.eagle.function.biz.v2x.v2n.scenario.scene.road
import android.graphics.Color
import com.mogo.eagle.core.data.enums.EventTypeEnumNew
import com.mogo.eagle.core.data.map.MogoLatLng
import com.mogo.eagle.core.data.map.entity.V2XRoadEventEntity
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager
import com.mogo.eagle.function.biz.v2x.v2n.bridge.BridgeApi.context
import com.mogo.eagle.function.biz.v2x.v2n.bridge.BridgeApi.v2xMarker
import com.mogo.eagle.function.biz.v2x.v2n.remove.MarkerWrapper
import com.mogo.map.marker.IMogoMarker
import com.mogo.map.overlay.IMogoPolyline
import com.mogo.map.overlay.MogoPolylineOptions
import java.util.concurrent.atomic.AtomicReference
class V2XAiRoadEventMarker {
private val current = AtomicReference<Pair<IMogoPolyline?, List<IMogoMarker>?>>()
private val overlayManager by lazy { CallerMapUIServiceManager.getOverlayManager() }
fun drawMarkers(entity: V2XRoadEventEntity, wrapper: MarkerWrapper) {
val polygon = entity.noveltyInfo.polygon
v2xMarker()?.drawableAlarmPOI(context(), entity, null)?.also {
wrapper.addMarker(it)
}
if (polygon != null && polygon.isNotEmpty() && entity.poiType != EventTypeEnumNew.TYPE_SOCKET_ROAD_JINGZHI.poiType) {
val options = MogoPolylineOptions()
val colors = ArrayList<Int>()
colors.add(Color.argb(204, 237, 172, 21))
colors.add(Color.argb(0, 255, 255, 255))
options.colorValues(colors)
val points = ArrayList<MogoLatLng>()
for (p in polygon) {
points.add(MogoLatLng(p.first, p.second))
}
if (points.size > 2) {
points.add(points[0])
}
options.points(points)
options.useGradient(true)
options.useFacade(true)
options.setGps(true)
options.width(5f)
options.zIndex(75000f)
options.maxIndex(800000f)
val line = overlayManager?.addPolyline(options)
line?.let {
current.set(Pair(line, wrapper.markers))
line.isVisible = true
wrapper.addLine(line)
}
}
}
fun removeMarkers() {
val prev = current.get()
if (prev != null) {
realRemove(prev)
}
}
private fun realRemove(pair: Pair<IMogoPolyline?, List<IMogoMarker>?>) {
val line = pair.first
if (line != null && line.isVisible) {
line.remove()
}
val markers = pair.second
if (markers != null && markers.isNotEmpty()) {
for (m in markers) {
m.remove()
}
}
}
}

View File

@@ -0,0 +1,77 @@
package com.mogo.eagle.function.biz.v2x.v2n.scenario.scene.road;
import android.util.Log;
import androidx.core.util.Pair;
import com.mogo.eagle.core.data.enums.EventTypeEnumNew;
import com.mogo.eagle.core.data.map.entity.MarkerExploreWay;
import com.mogo.eagle.core.data.map.entity.MarkerLocation;
import com.mogo.eagle.core.data.map.entity.V2XRoadEventEntity;
import com.mogo.eagle.function.biz.v2x.v2n.bridge.BridgeApi;
import com.mogo.eagle.function.biz.v2x.v2n.manager.IMoGoV2XMarkerManager;
import com.mogo.eagle.function.biz.v2x.v2n.remove.MarkerWrapper;
import com.mogo.eagle.function.biz.v2x.v2n.remove.MarkerRemoveManager;
import com.mogo.eagle.function.biz.v2x.v2n.scenario.scene.airoad.AiRoadMarker;
import com.mogo.eagle.function.biz.v2x.v2n.scenario.view.IV2XMarker;
import com.mogo.map.marker.IMogoMarker;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* 道路V2X事件的Marker
*/
public class V2XRoadEventMarker implements IV2XMarker<V2XRoadEventEntity> {
@Override
public void drawPOI(V2XRoadEventEntity entity) {
try {
// 清除道路事件
IMoGoV2XMarkerManager marker = BridgeApi.INSTANCE.v2xMarker();
if (marker != null) {
if (entity != null) {
Log.d("RWJ", "V2XRoadEventMarker:" + entity.getPoiType());
if (isAiRoadEvent(entity.getPoiType())) {
MarkerExploreWay noveltyInfo = entity.getNoveltyInfo();
Log.d("RWJ", "V2XRoadEventMarker -> noveltyInfo:" + noveltyInfo);
if (noveltyInfo != null) {
Pair<Double, Double> gpsLocation = noveltyInfo.getGpsLocation();
List<Pair<Double, Double>> polygons = noveltyInfo.getPolygon();
if (gpsLocation != null && polygons != null) {
MarkerLocation location = noveltyInfo.getLocation();
AiRoadMarker.Marker m = new AiRoadMarker.Marker(noveltyInfo.getInfoId(), noveltyInfo.getPoiType(), gpsLocation.second, gpsLocation.first, location.getAngle(), polygons, null, entity);
AiRoadMarker aiMarker = new AiRoadMarker();
aiMarker.marker(m, true, isDrawRoadLine(m.getPoiType()));
AiRoadMarker.aiMakers.put(noveltyInfo.getInfoId(), aiMarker);
}
}
} else {
IMogoMarker iMarker = marker.drawableAlarmPOI(BridgeApi.INSTANCE.context(), entity, null);
if (iMarker != null) {
Log.d("RWJ", "V2XRoadEventMarker:" + entity.getPoiType() + "--- add Marker");
ArrayList<IMogoMarker> markers = new ArrayList<>();
markers.add(iMarker);
String id = entity.getLocation().getLon() + "_" + entity.getLocation().getLat();
MarkerRemoveManager.INSTANCE.addMarker(new MarkerWrapper(id, entity.getLocation().getLon(), entity.getLocation().getLat(), 0, markers, null));
} else {
Log.d("RWJ", "V2XRoadEventMarker:" + entity.getPoiType() + "--- return empty marker");
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private boolean isAiRoadEvent(String poiType) {
return Objects.equals(poiType, EventTypeEnumNew.TYPE_SOCKET_ROAD_SHIGONG.getPoiType())
&& Objects.equals(poiType, EventTypeEnumNew.FOURS_ACCIDENT_04.getPoiType())
&& Objects.equals(poiType, EventTypeEnumNew.TYPE_SOCKET_ROAD_JINGZHI.getPoiType())
&& Objects.equals(poiType, EventTypeEnumNew.TYPE_SOCKET_ROAD_SHIGU.getPoiType());
}
private boolean isDrawRoadLine(String poiType) {
return EventTypeEnumNew.TYPE_SOCKET_ROAD_SHIGONG.getPoiType().equals(poiType);
}
}

View File

@@ -0,0 +1,186 @@
package com.mogo.eagle.function.biz.v2x.v2n.scenario.scene.road;
import com.mogo.commons.AbsMogoApplication;
import com.mogo.eagle.core.data.enums.EventTypeEnumNew;
import com.mogo.eagle.core.data.enums.WarningDirectionEnum;
import com.mogo.eagle.core.data.map.entity.MarkerExploreWay;
import com.mogo.eagle.core.data.map.entity.MarkerLocation;
import com.mogo.eagle.core.data.map.entity.V2XMessageEntity;
import com.mogo.eagle.core.data.map.entity.V2XRoadEventEntity;
import com.mogo.eagle.core.data.msgbox.MsgBoxBean;
import com.mogo.eagle.core.data.msgbox.MsgBoxType;
import com.mogo.eagle.core.data.msgbox.V2XMsg;
import com.mogo.eagle.core.function.api.hmi.warning.IMoGoWarningStatusListener;
import com.mogo.eagle.core.function.api.map.angle.Default;
import com.mogo.eagle.core.function.api.map.angle.RoadEvent;
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotControlManager;
import com.mogo.eagle.core.function.call.hmi.CallerHmiManager;
import com.mogo.eagle.core.function.call.map.CallerVisualAngleManager;
import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxManager;
import com.mogo.eagle.function.biz.v2x.v2n.scenario.impl.AbsV2XScenario;
import com.mogo.eagle.function.biz.v2x.v2n.scenario.view.IV2XMarker;
import com.mogo.eagle.core.network.utils.GsonUtil;
import com.mogo.eagle.core.utilcode.mogo.logger.Logger;
import com.mogo.eagle.core.utilcode.mogo.storage.SharedPrefsMgr;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
* author : donghongyu
* e-mail : 1358506549@qq.com
* date : 2020/5/15 5:37 PM
* desc : 道路预警场景
* version: 1.0
*/
public class V2XRoadEventScenario extends AbsV2XScenario<V2XRoadEventEntity> implements IMoGoWarningStatusListener {
private static final String TAG = "V2XRoadEventScenario";
public V2XRoadEventScenario() {
setV2XMarker(new V2XRoadEventMarker());
}
@Override
public void init(V2XMessageEntity<V2XRoadEventEntity> v2XMessageEntity) {
try {
Logger.d(TAG, "v2XMessageEntity:" + GsonUtil.jsonFromObject(v2XMessageEntity));
V2XRoadEventEntity v2XRoadEventEntity = v2XMessageEntity.getContent();
if (v2XRoadEventEntity != null) {
if (!isSameScenario(v2XMessageEntity)) {
// 更新要提醒的数据
setV2XMessageEntity(v2XMessageEntity);
show();
} else {
// 更新要提醒的数据
setV2XMessageEntity(v2XMessageEntity);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void show() {
try {
if (getV2XMessageEntity() != null && getV2XMessageEntity().getContent() != null) {
//只展示不播报 不广播
V2XMessageEntity<V2XRoadEventEntity> entity = getV2XMessageEntity();
V2XRoadEventEntity content = entity.getContent();
if (content != null && !Objects.equals(content.getPoiType(), EventTypeEnumNew.TYPE_SOCKET_ROAD_SHIGONG.getPoiType())
&& !Objects.equals(content.getPoiType(), EventTypeEnumNew.TYPE_SOCKET_ROAD_JINGZHI.getPoiType())
&& !Objects.equals(content.getPoiType(), EventTypeEnumNew.TYPE_SOCKET_ROAD_SHIGU.getPoiType())
&& !Objects.equals(content.getPoiType(), EventTypeEnumNew.TYPE_SOCKET_ROAD_CONGESTION.getPoiType())) {
content.getTts(false);
}
showWindow();
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void showWindow() {
V2XMessageEntity<V2XRoadEventEntity> entity = getV2XMessageEntity();
V2XRoadEventEntity content = entity != null ? entity.getContent() : null;
if (content != null) {
// //显示警告红边
String alarmText = content.getAlarmContent();
String ttsText = content.getTts();
if (alarmText == null || alarmText.isEmpty()
|| ttsText == null || ttsText.isEmpty()) {
Logger.d("MsgBox-V2XRoadScenario", "alertContent或ttsContent为空!");
}
String poiType = content.getPoiType();
if (EventTypeEnumNew.TYPE_SOCKET_ROAD_SHIGONG.getPoiType().equals(poiType) ||
EventTypeEnumNew.TYPE_SOCKET_ROAD_JINGZHI.getPoiType().equals(poiType) ||
EventTypeEnumNew.TYPE_SOCKET_ROAD_CONGESTION.getPoiType().equals(poiType) ||
EventTypeEnumNew.TYPE_SOCKET_ROAD_SHIGU.getPoiType().equals(poiType)) {
MarkerExploreWay noveltyInfo = content.getNoveltyInfo();
if (noveltyInfo != null) {
MarkerLocation eventLocation = noveltyInfo.getLocation();
if (eventLocation != null) {
double distance = content.getDistance();
alarmText = String.format(alarmText, Math.round(distance) + "");
ttsText = String.format(ttsText, Math.round(distance) + "");
}
}
}
//占道施工预警
if (poiType.equals("10006") || poiType.equals("100061")) {
long currentTime = System.currentTimeMillis() / 1000;
long oldTime = SharedPrefsMgr.getInstance(AbsMogoApplication.getApp()).getLong("roadwork", 0);
if (currentTime - oldTime > 60) { //超过一分钟,才会继续播报重复提醒
SharedPrefsMgr.getInstance(AbsMogoApplication.getApp()).putLong("roadwork", System.currentTimeMillis() / 1000);
CallerAutoPilotControlManager.sendTripInfo(5, "", "", "", false);
}
}
CallerMsgBoxManager.INSTANCE.saveMsgBox(
new MsgBoxBean(
MsgBoxType.V2X,
new V2XMsg(poiType,
alarmText,
ttsText)
)
);
CallerHmiManager.INSTANCE.warningV2X(poiType, alarmText,
ttsText, this,WarningDirectionEnum.ALERT_WARNING_TOP,
TimeUnit.SECONDS.toMillis(5));
}
}
@Override
public void drawPOI() {
IV2XMarker marker = getV2XMarker();
if (marker != null) {
// 重置告警信息
marker.drawPOI(getV2XMessageEntity().getContent());
}
}
@Override
public void clearPOI() {
// IV2XMarker marker = getV2XMarker();
// if (marker != null) {
// marker.clearPOI();
// }
}
@Override
public void onShow() {
if (isNeedChangeAngle()) {
CallerVisualAngleManager.INSTANCE.changeAngle(RoadEvent.INSTANCE);
}
V2XMessageEntity<V2XRoadEventEntity> entity = getV2XMessageEntity();
if (entity != null) {
V2XRoadEventEntity content = entity.getContent();
if (content != null) {
if (entity.isNeedAddLine() && !EventTypeEnumNew.TYPE_SOCKET_ROAD_CONGESTION.getPoiType().equals(content.getPoiType())) {
drawPOI();
}
}
}
}
private boolean isNeedChangeAngle() {
V2XMessageEntity<V2XRoadEventEntity> entity = getV2XMessageEntity();
V2XRoadEventEntity content = entity != null ? entity.getContent() : null;
if (content == null) {
return true;
}
return !EventTypeEnumNew.GHOST_PROBE.getPoiType().equals(content.getPoiType());
}
@Override
public void onDismiss() {
CallerHmiManager.INSTANCE.dismissWarning(WarningDirectionEnum.ALERT_WARNING_TOP);
if (isNeedChangeAngle()) {
CallerVisualAngleManager.INSTANCE.changeAngle(new Default(3, TimeUnit.SECONDS));
}
release();
}
}

View File

@@ -0,0 +1,174 @@
package com.mogo.eagle.function.biz.v2x.v2n.scenario.scene.warning;
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_V2X;
import android.graphics.Color;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import androidx.annotation.Nullable;
import com.mogo.eagle.core.data.enums.EventTypeEnumNew;
import com.mogo.eagle.core.data.enums.WarningDirectionEnum;
import com.mogo.eagle.core.data.map.MogoLocation;
import com.mogo.eagle.core.data.map.entity.V2XMessageEntity;
import com.mogo.eagle.core.data.msgbox.MsgBoxBean;
import com.mogo.eagle.core.data.msgbox.MsgBoxType;
import com.mogo.eagle.core.data.msgbox.V2XMsg;
import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener;
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.msgbox.CallerMsgBoxManager;
import com.mogo.eagle.function.biz.v2x.v2n.scenario.impl.AbsV2XScenario;
import com.mogo.eagle.function.biz.v2x.v2n.scenario.view.IV2XMarker;
import com.mogo.eagle.core.data.v2x.V2XWarningTarget;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
import java.math.BigDecimal;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
/**
* @author liujing
* @description 车路云—场景预警-V1.0 前车/行人/摩托车/盲区碰撞预警
* @since: 2021/3/24
*/
public class V2XFrontWarningScenario extends AbsV2XScenario implements IMoGoChassisLocationGCJ02Listener, IMoGoWarningStatusListener {
private static final String TAG = "V2XWarningMarker";
private static final V2XWarningMarker sV2XWarningMarker = new V2XWarningMarker();
private V2XWarningTarget mMarkerEntity;
private WarningDirectionEnum mDirection;
public V2XFrontWarningScenario() {
//setV2XMarker(sV2XWarningMarker);
}
@Override
public void init(@Nullable V2XMessageEntity v2XMessageEntity) {
CallerLogger.INSTANCE.d(M_V2X + TAG, "----- init -----:\n" + (v2XMessageEntity == null ? "null" : v2XMessageEntity.toString()));
try {
setV2XMessageEntity(v2XMessageEntity);
if (v2XMessageEntity != null && v2XMessageEntity.getContent() instanceof V2XWarningTarget) {
mMarkerEntity = (V2XWarningTarget) v2XMessageEntity.getContent();
show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void show() {
CallerLogger.INSTANCE.d(M_V2X + TAG, "----- show --- 1 --:\n" + (mMarkerEntity == null ? "null" : mMarkerEntity.toString()));
if (mMarkerEntity != null) {
CallerLogger.INSTANCE.d(M_V2X + TAG, "----- show --- 2 --:\n" + mMarkerEntity);
String v2xType = getV2XTypeForFrontWarning(mMarkerEntity);
V2XMessageEntity entity = getV2XMessageEntity();
if (!v2xType.equals("0")) {
if (getAlertContentForFrontWarning(mMarkerEntity).toString() == null
|| getAlertContentForFrontWarning(mMarkerEntity).toString().isEmpty()
|| mMarkerEntity.getTts() == null || mMarkerEntity.getTts().isEmpty()) {
Log.d("MsgBox-FrontWarScenario", "alertContent或ttsContent为空!");
}
CallerMsgBoxManager.INSTANCE.saveMsgBox(
new MsgBoxBean(
MsgBoxType.V2X,
new V2XMsg(v2xType + "",
getAlertContentForFrontWarning(mMarkerEntity).toString(),
mMarkerEntity.getTts())
)
);
CallerHmiManager.INSTANCE.warningV2X(v2xType + "",
getAlertContentForFrontWarning(mMarkerEntity), mMarkerEntity.getTts(),
this,getDirection(),
TimeUnit.SECONDS.toMillis(5));
}
}
}
private String getV2XTypeForFrontWarning(V2XWarningTarget entity) {
switch (entity.getType()) {
case 1:
case 11:
entity.setTts("注意行人");
return EventTypeEnumNew.TYPE_USECASE_ID_VRUCW_PERSON.getPoiType();
case 2:
entity.setTts("注意自行车");
case 4:
entity.setTts("注意摩托车");
return EventTypeEnumNew.TYPE_USECASE_ID_VRUCW_MOTOR_VEHICLES.getPoiType();
}
return "0";
}
private CharSequence getAlertContentForFrontWarning(V2XWarningTarget entity) {
double dis = entity.getDistance();
//距离四舍五入保留整数
BigDecimal bg = new BigDecimal(dis);
double disBig = bg.setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue();
String distance = String.format(Locale.getDefault(), "%.0f", disBig) + "";
String content = entity.getWarningContent();
SpannableStringBuilder ssb = new SpannableStringBuilder(content + distance);
ssb.setSpan(new ForegroundColorSpan(Color.parseColor("#FF3036")), content.length(), ssb.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
return ssb;
}
@Override
public void drawPOI() {
IV2XMarker marker = getV2XMarker();
if (marker != null && mMarkerEntity != null) {
marker.drawPOI(mMarkerEntity);
CallerLogger.INSTANCE.d(M_V2X + TAG, "drawPOI");
}
}
@Override
public void clearPOI() {
CallerLogger.INSTANCE.d(M_V2X + TAG, "----- clearPOI -----");
}
@Override
public void onChassisLocationGCJ02(@Nullable MogoLocation gnssInfo) {
sV2XWarningMarker.onCarLocationChanged2(gnssInfo);
}
private WarningDirectionEnum getDirection(){
WarningDirectionEnum warningDirectionEnum = WarningDirectionEnum.ALERT_WARNING_ALL;
switch (mMarkerEntity.getDirection()) {
case 0:
warningDirectionEnum = WarningDirectionEnum.ALERT_WARNING_NON;
break;
case 1:
warningDirectionEnum = WarningDirectionEnum.ALERT_WARNING_TOP;
break;
case 2:
warningDirectionEnum = WarningDirectionEnum.ALERT_WARNING_BOTTOM;
break;
case 3:
warningDirectionEnum = WarningDirectionEnum.ALERT_WARNING_LEFT;
break;
case 4:
warningDirectionEnum = WarningDirectionEnum.ALERT_WARNING_RIGHT;
break;
}
mDirection = warningDirectionEnum;
return warningDirectionEnum;
}
@Override
public void onShow() {
//预警蒙层
drawPOI();
}
@Override
public void onDismiss() {
if (mDirection != null) {
CallerHmiManager.INSTANCE.dismissWarning(mDirection);
}
// clearPOI();
}
}

View File

@@ -0,0 +1,446 @@
package com.mogo.eagle.function.biz.v2x.v2n.scenario.scene.warning;
import static com.mogo.eagle.core.data.constants.DataTypes.TYPE_MARKER_CLOUD_STOP_LINE_DATA;
import static com.mogo.eagle.core.data.constants.DataTypes.TYPE_MARKER_CLOUD_WARN_DATA;
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_V2X;
import com.mogo.cloud.commons.utils.CoordinateUtils;
import com.mogo.commons.AbsMogoApplication;
import com.mogo.commons.module.status.MogoStatusManager;
import com.mogo.commons.utils.Trigonometric;
import com.mogo.eagle.core.data.map.MogoLatLng;
import com.mogo.eagle.core.data.map.MogoLocation;
import com.mogo.eagle.core.data.v2x.DrawLineInfo;
import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationWGS84ListenerManager;
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager;
import com.mogo.eagle.function.biz.v2x.v2n.bridge.BridgeApi;
import com.mogo.eagle.function.biz.v2x.v2n.manager.IMoGoPersonWarnPolylineManager;
import com.mogo.eagle.function.biz.v2x.v2n.manager.IMoGoStopPolylineManager;
import com.mogo.eagle.function.biz.v2x.v2n.manager.IMoGoWarnPolylineManager;
import com.mogo.eagle.function.biz.v2x.v2n.scenario.view.IV2XMarker;
import com.mogo.eagle.core.data.v2x.V2XLocation;
import com.mogo.eagle.core.data.v2x.V2XWarningTarget;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
import com.mogo.eagle.core.utilcode.mogo.thread.WorkThreadHandler;
import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
import com.mogo.map.marker.IMogoMarkerManager;
import com.mogo.map.overlay.IMogoPolyline;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/**
* @author liujing
* @description 前方预警marker打点 绘制安全线和预警线 衡阳交付-取消划线需求,只渲染识别物红色模型移动过程,代码保留
* @since: 2021/3/30
*/
public class V2XWarningMarker implements IV2XMarker {
private static final String TAG = "V2XWarningMarker";
private static final String WARNING_ARROWS = "WARNING_ARROWS";
private V2XWarningTarget mCloundWarningInfo;
private boolean isSelfLineClear = true;//绘制线是否已被清除
private final List fillPoints = new ArrayList();//停止线经纬度合集
private boolean isFirstLocation = false;
private MogoLatLng carLocation = new MogoLatLng(
CallerChassisLocationWGS84ListenerManager.INSTANCE.getChassisLocationWGS84().getLatitude(),
CallerChassisLocationWGS84ListenerManager.INSTANCE.getChassisLocationWGS84().getLongitude()
);
/*
* 自车前方的点,在停止线上--通过自车位置与距离停止线之间的距离计算
* */
private MogoLatLng middleLocationInStopLine = new MogoLatLng(0, 0);
private static long showTime = 6000;
private double bearing;
private boolean hasStopLines = false;
@Override
public void drawPOI(Object entity) {
try {
CallerLogger.INSTANCE.d(M_V2X + TAG, "===drawPOI");
mCloundWarningInfo = (V2XWarningTarget) entity;
drawLineWithEntity();
} catch (Exception e) {
CallerLogger.INSTANCE.d(M_V2X + TAG, e.toString());
}
}
public void drawLineWithEntity() {
showTime = mCloundWarningInfo.getShowTime() > 0 ? mCloundWarningInfo.getShowTime() * 1000 : 6000;
fillPointOnStopLine();
MogoLocation location = BridgeApi.INSTANCE.getLocation().get();
if (location == null) {
return;
}
bearing = location.getHeading();
if (mCloundWarningInfo != null && mCloundWarningInfo.getStopLines() != null) {
hasStopLines = mCloundWarningInfo.getStopLines().size() > 0;
}
isSelfLineClear = false;
isFirstLocation = false;
if (fillPoints != null && fillPoints.size() > 0) {
//存在停止线的情况 自车与停止线之间绘制蓝色安全线 停止线向前50m绘制红色预警线
middleLocationInStopLine = getMiddleLocationInStopLine();
//停止线前方画线
WorkThreadHandler.getInstance().postDelayed(() -> {
if (carLocation.lat != 0 && carLocation.lon != 0) {
//在自车与停止线直线绘制蓝色预警线
//衡阳交付-取消划线需求,只渲染识别物红色模型移动过程
//drawSelfCarLine(carLocation.lon, carLocation.lat, bearing);
} else {
}
//二轮车和行人的渲染和移动
IMogoMarkerManager marker = CallerMapUIServiceManager.INSTANCE.getMarkerManager(AbsMogoApplication.getApp());
if (marker != null) {
marker.removeMarkers(TYPE_MARKER_CLOUD_WARN_DATA);
}
/* 衡阳交付-取消划线需求,只渲染识别物红色模型移动过程
//获取停止线前方50m坐标点
MogoLatLng warningLocation = Trigonometric.getNewLocation(middleLocationInStopLine,
50, angleForCarMoveDirection());
//停止线向前方50m绘制红色预警线
drawRedWarningLineFrontOfStopLine(mCloundWarningInfo, middleLocationInStopLine,
warningLocation);
*/
Objects.requireNonNull(CallerMapUIServiceManager.INSTANCE.getMarkerService()).renderWarningMoveMarker(mCloundWarningInfo.getLon(), mCloundWarningInfo.getLat(), mCloundWarningInfo.getType(), mCloundWarningInfo.getCollisionLat(), mCloundWarningInfo.getCollisionLon(), mCloundWarningInfo.getAngle(), mCloundWarningInfo.getShowTime());
//添加停止线marker
//衡阳交付-取消划线需求,只渲染识别物红色模型移动过程
//handleStopLine();
}, 0);
CallerLogger.INSTANCE.d(M_V2X + TAG, "显示时间为++" + showTime + "识别物类型:" +
String.valueOf(mCloundWarningInfo.getType()));
} else { //无停止线
CallerLogger.INSTANCE.d(M_V2X + TAG, "无停止线");
WorkThreadHandler.getInstance().postDelayed(() -> {
/* 衡阳交付-取消划线需求,只渲染识别物红色模型移动过程
CallerLogger.INSTANCE.d(M_V2X + TAG, "无停止线" + mCloundWarningInfo.toString());
//绘制识别物与交汇点连线,并且更新连线数据
drawOtherObjectLine(mCloundWarningInfo);
//二轮车和行人的渲染和移动
V2XServiceManager.getMarkerManager().removeMarkers(TYPE_MARKER_CLOUD_WARN_DATA);
if (carLocation.lat != 0 && carLocation.lon != 0) {
drawSelfCarLine(carLocation.lon, carLocation.lat, bearing);
} else {
CallerLogger.INSTANCE.d(M_V2X + TAG, "数据为空carLocation == null");
}
*/
Objects.requireNonNull(CallerMapUIServiceManager.INSTANCE.getMarkerService()).renderWarningMoveMarker(mCloundWarningInfo.getLon()
, mCloundWarningInfo.getLat()
, mCloundWarningInfo.getType()
, mCloundWarningInfo.getCollisionLat()
, mCloundWarningInfo.getCollisionLon()
, mCloundWarningInfo.getAngle()
, mCloundWarningInfo.getShowTime());
}, 0);
}
clearAllLine();
}
/*
*
* */
public double angleForCarMoveDirection() {
MogoLatLng startLatLng = new MogoLatLng(carLocation.lat, carLocation.lon);
MogoLatLng endLatLng = new MogoLatLng(middleLocationInStopLine.lat, middleLocationInStopLine.lon);
double angle = Trigonometric.getAngle(startLatLng.lon, startLatLng.lat, endLatLng.lon, endLatLng.lat);
CallerLogger.INSTANCE.d(M_V2X + TAG, "angle==" + String.valueOf(angle));
return angle;
}
/*绘制停止线前方50m的红色预警线
* startLatLng: 划线起点=停止线上的坐标点
* mogoLatLng: 停止线前方50m坐标点
* */
private void drawRedWarningLineFrontOfStopLine(V2XWarningTarget info, MogoLatLng
startLatLng, MogoLatLng mogoLatLng) {
if (info != null) {
double angle = Trigonometric.getAngle(startLatLng.lon, startLatLng.lat, mogoLatLng.lon, mogoLatLng.lat);
CallerLogger.INSTANCE.d(M_V2X + TAG, "angle==drawRedWarningLineFrontOfStopLine:" + String.valueOf(angle));
IMoGoStopPolylineManager stopPolyLineMnager = BridgeApi.INSTANCE.v2xStopPolyline();
if (stopPolyLineMnager != null) {
IMogoPolyline polyLine = stopPolyLineMnager.getMogoStopPolyline();
MogoLatLng endLatlng = new MogoLatLng(mogoLatLng.lat, mogoLatLng.lon);
MogoLatLng addMiddleLoc = Trigonometric.getNewLocation(startLatLng.lon, startLatLng.lat, 25, angle);
if (polyLine != null) {
CallerLogger.INSTANCE.d(M_V2X + TAG, "drawStopLine polyLine != null");
polyLine.setPoints(Arrays.asList(startLatLng, addMiddleLoc, endLatlng));
polyLine.setTransparency(0.5f);
} else {
DrawLineInfo lineInfo = new DrawLineInfo();
List locations = new ArrayList();
locations.add(startLatLng);
locations.add(addMiddleLoc);
locations.add(endLatlng);
lineInfo.setLocations(locations);
lineInfo.setHeading(info.getHeading());
CallerLogger.INSTANCE.d(TAG, "drawStopLine width = " + info.getRoadwidth());
lineInfo.setWidth(info.getRoadwidth() * 14 + 5);
stopPolyLineMnager.drawStopPolyline(BridgeApi.INSTANCE.context(), lineInfo);
}
CallerLogger.INSTANCE.d(M_V2X + TAG, "停止线前方50m区域的三个坐标点是:" + startLatLng.lon + "," + startLatLng.lat +
"中间点坐标:" + addMiddleLoc.lon + "," + addMiddleLoc.lat
+ "终点" + endLatlng.lon + "," + endLatlng.lat);
}
} else {
clearAllLine();
}
}
public void clearAllLine() {
UiThreadHandler.postDelayed(() -> {
CallerLogger.INSTANCE.d(M_V2X + TAG, "清除所有预警线的时间是:" + String.valueOf(showTime));
//清除识别物到碰撞点预警线
IMoGoPersonWarnPolylineManager personStopPolyLineManager = BridgeApi.INSTANCE.v2xPersonWarnPolyline();
if (personStopPolyLineManager != null) {
personStopPolyLineManager.clearLine();
}
//清除车前方第一条预警线
IMoGoWarnPolylineManager warnPolyLineManager = BridgeApi.INSTANCE.v2xWarnPolyline();
if (warnPolyLineManager != null) {
warnPolyLineManager.clearLine();
}
//清除停止线
IMoGoStopPolylineManager stopPolyLineManager = BridgeApi.INSTANCE.v2xStopPolyline();
if (stopPolyLineManager != null) {
stopPolyLineManager.clearLine();
}
IMogoMarkerManager marker = CallerMapUIServiceManager.INSTANCE.getMarkerManager(AbsMogoApplication.getApp());
if (marker != null) {
//清除小箭头
marker.removeMarkers(WARNING_ARROWS);
//清除停止线
marker.removeMarkers(TYPE_MARKER_CLOUD_STOP_LINE_DATA);
}
isSelfLineClear = true;
}, showTime);
}
/**
* 补点后的停止线经纬度合集
*/
public void fillPointOnStopLine() {
try {
fillPoints.clear();
List stopLines = mCloundWarningInfo.getStopLines();
if (stopLines != null && stopLines.size() > 1) {
V2XLocation x = mCloundWarningInfo.getStopLines().get(0);
V2XLocation y = mCloundWarningInfo.getStopLines().get(1);
//两点间的距离
float distance = CoordinateUtils.calculateLineDistance(x.getLon(), x.getLat(), y.getLon(), y.getLat());
float average = distance / 3;
//两点间的角度
double angle = Trigonometric.getAngle(x.getLon(), x.getLat(), y.getLon(), y.getLat());
//根据距离和角度获取下个点的经纬度
fillPoints.add(x);
for (int i = 1; i < 3; i++) {
MogoLatLng newLocation = Trigonometric.getNewLocation(x.getLon(), x.getLat(), average * i, angle);
fillPoints.add(newLocation);
}
fillPoints.add(y);
} else {
CallerLogger.INSTANCE.d(M_V2X + TAG, "停止线数据不存在");
}
} catch (Exception e) {
CallerLogger.INSTANCE.e(M_V2X + TAG, "exception : " + e);
e.printStackTrace();
}
}
/*
* 停止线绘制
* */
private void handleStopLine() {
try {
if (mCloundWarningInfo != null) {
IMogoMarkerManager marker = CallerMapUIServiceManager.INSTANCE.getMarkerManager(AbsMogoApplication.getApp());
if (marker != null) {
marker.removeMarkers(TYPE_MARKER_CLOUD_STOP_LINE_DATA);
}
for (int i = 0; i < fillPoints.size(); i++) {
V2XWarningTarget entity = new V2XWarningTarget();
MogoLatLng latLng = (MogoLatLng) fillPoints.get(i);
entity.setLat(latLng.lat);
entity.setLon(latLng.lon);
entity.setHeading(mCloundWarningInfo.getHeading());
Objects.requireNonNull(CallerMapUIServiceManager.INSTANCE.getMarkerService()).renderStopLineMarker(entity.getLon(), entity.getLat());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private MogoLatLng getMogoLat(MogoLatLng latlng) {
MogoLatLng newLocation = Trigonometric.getNewLocation(latlng.lon, latlng.lat, mCloundWarningInfo.getStopLineDistance(),
mCloundWarningInfo.getAngle());
return newLocation;
}
/*
* 自车前方的点,落点在停止线上--通过自车位置与距离停止线之间的距离计算
* */
private MogoLatLng getMiddleLocationInStopLine() {
if (carLocation.lat == 0 || carLocation.lon == 0) {
CallerLogger.INSTANCE.d(M_V2X + TAG, "获取不到车的位置");
}
MogoLatLng newLocation = new MogoLatLng(0, 0);
if (mCloundWarningInfo != null && mCloundWarningInfo.getStopLines() != null && mCloundWarningInfo.getStopLines().size() > 1) {
V2XLocation x = mCloundWarningInfo.getStopLines().get(0);
V2XLocation y = mCloundWarningInfo.getStopLines().get(1);
float distance = CoordinateUtils.calculateLineDistance(x.getLon(), x.getLat(), y.getLat(), y.getLat());
double angle = Trigonometric.getAngle(x.getLat(), x.getLat(), y.getLon(), y.getLat());
newLocation = Trigonometric.getNewLocation(x.getLon(), x.getLat(), distance * 0.5, angle);
} else {
CallerLogger.INSTANCE.d(M_V2X + TAG, "停止线返回坐标点数量不正确" + mCloundWarningInfo.getStopLines().size());
}
return newLocation;
}
/**
* 存在停止线时自车与停止线之间为蓝色预警
* 不存在停止线,自车与预碰撞点之间为红色预警
* lon 自车经度
* lat 自车纬度
*/
public void drawSelfCarLine(double lon, double lat, float bearing) {
CallerLogger.INSTANCE.d(M_V2X + TAG, "drawSelfCarLine");
if (!isSelfLineClear) {
if (mCloundWarningInfo != null) {
IMoGoWarnPolylineManager warnPolyLineManager = BridgeApi.INSTANCE.v2xWarnPolyline();
if (warnPolyLineManager == null) {
return;
}
IMogoPolyline mogoPolyline = warnPolyLineManager.getMogoWarnPolyline();
MogoLatLng startLatlng = new MogoLatLng(0, 0);
MogoLatLng endLatlng = new MogoLatLng(0, 0);
MogoLatLng addMiddleLoc = new MogoLatLng(0, 0);
if (!isFirstLocation) {
carLocation = getMogoLat(new MogoLatLng(lat, lon));
isFirstLocation = true;
}
//绘制线的终点(在停止线上或者预碰撞点上)
endLatlng = new MogoLatLng(hasStopLines ?
middleLocationInStopLine.lat : mCloundWarningInfo.getCollisionLat(), hasStopLines ?
middleLocationInStopLine.lon : mCloundWarningInfo.getCollisionLon());
startLatlng = new MogoLatLng(lat, lon);
float distance = CoordinateUtils.calculateLineDistance(startLatlng.lon, startLatlng.lat, endLatlng.lon, endLatlng.lat);
//扩展点为了渐变色添加
addMiddleLoc = Trigonometric.getNewLocation(startLatlng.getLon(), startLatlng.getLat(), distance / 2,
Trigonometric.getAngle(startLatlng.lon, startLatlng.lat, endLatlng.lon, endLatlng.lat));
CallerLogger.INSTANCE.d(M_V2X + TAG, "angle==扩展点为了渐变色添加:" +
String.valueOf(Trigonometric.getAngle(startLatlng.lon, startLatlng.lat, endLatlng.lon, endLatlng.lat)));
if (mogoPolyline != null) {
mogoPolyline.setPoints(Arrays.asList(startLatlng, addMiddleLoc, endLatlng));
mogoPolyline.setTransparency(0.5f);
} else {
DrawLineInfo info = new DrawLineInfo(); // 对象
List locations = new ArrayList();
locations.add(startLatlng);
locations.add(addMiddleLoc);
locations.add(endLatlng);
info.setLocations(locations);
info.setHeading(bearing);
info.setWidth(mCloundWarningInfo.getRoadwidth() * 14 + 5);
if (mCloundWarningInfo.getStopLines() != null) {
info.setHasStopLines(mCloundWarningInfo.getStopLines().size() > 0);
}
warnPolyLineManager.drawWarnPolyline(BridgeApi.INSTANCE.context(), info);
CallerLogger.INSTANCE.d(M_V2X + TAG, "自车前方第一条线" + "起点:" + startLatlng + "中间点:" + addMiddleLoc + "终点:" + endLatlng);
}
CallerLogger.INSTANCE.d(M_V2X + TAG, "自车为起点绘制 自车;" + startLatlng.lon + "," + startLatlng.lat +
"中间扩展点" + addMiddleLoc.lon + "," + addMiddleLoc.lat + "终点:" + endLatlng.lon + "," + endLatlng.lat);
} else {
clearAllLine();
}
}
}
/**
* 侧方目标物与预碰撞点连线,并且更新数据 TODO 需要实时给行人当前位置
*/
private void drawOtherObjectLine(V2XWarningTarget info) {
if (info != null) {
CallerLogger.INSTANCE.d(M_V2X + TAG, "info != null");
IMoGoPersonWarnPolylineManager personWarnPolylineManager = BridgeApi.INSTANCE.v2xPersonWarnPolyline();
if (personWarnPolylineManager == null) {
return;
}
IMogoPolyline polyLine = personWarnPolylineManager.getMogoPersonWarnPolyline();
MogoLatLng startLatlng = new MogoLatLng(info.getLat(), info.getLon());//识别物坐标
MogoLatLng endLatlng = new MogoLatLng(info.getCollisionLat(), info.getCollisionLon());//预碰撞点坐标
float distance = CoordinateUtils.calculateLineDistance(startLatlng.lon, startLatlng.lat, endLatlng.lon, endLatlng.lat);//识别物到碰撞点之间的距离
MogoLatLng addMiddleLoc = Trigonometric.getNewLocation(startLatlng.getLon(), startLatlng.getLat(), distance / 2,
Trigonometric.getAngle(startLatlng.lon, startLatlng.lat, endLatlng.lon, endLatlng.lat));//补点
if (polyLine != null) {
CallerLogger.INSTANCE.d(M_V2X + TAG, "目标物与碰撞点连线 != null");
polyLine.setPoints(Arrays.asList(startLatlng, addMiddleLoc, endLatlng));
polyLine.setTransparency(0.5f);
} else {
//识别物到预碰撞点之间的箭头
addArrows(startLatlng, endLatlng);
DrawLineInfo lineInfo = new DrawLineInfo();
List locations = new ArrayList();
locations.add(startLatlng);
locations.add(addMiddleLoc);
locations.add(endLatlng);
lineInfo.setLocations(locations);
lineInfo.setHeading(info.getHeading());
lineInfo.setWidth(info.getRoadwidth() * 14 + 5);
personWarnPolylineManager.drawPersonWarnPolyline(BridgeApi.INSTANCE.context(), lineInfo);
CallerLogger.INSTANCE.d(M_V2X + TAG, "目标物与预碰撞点画线点为" + "起点:" + startLatlng + "中间点:" + addMiddleLoc + "终点:" + endLatlng);
}
} else {
CallerLogger.INSTANCE.e(M_V2X + TAG, "info == null");
clearAllLine();
}
}
//侧面目标物与碰撞点之间添加多个小箭头
private void addArrows(MogoLatLng startLatLng, MogoLatLng endLatLng) {
float distance = CoordinateUtils.calculateLineDistance(
startLatLng.lon, startLatLng.lat, endLatLng.lon, endLatLng.lat);
double rotate = Trigonometric.getAngle(startLatLng.lon, startLatLng.lat, endLatLng.lon, endLatLng.lat);
CallerLogger.INSTANCE.d(M_V2X + TAG, "添加小箭头--目标物与预碰撞点之间的距离是" + String.valueOf(distance));
if (distance > 5) {
int count = (int) (distance / 5);
for (int i = 0; i < count; i++) {
MogoLatLng newLo = Trigonometric.getNewLocation(
startLatLng.getLon(), startLatLng.getLat(), 5 * (i + 1), Trigonometric.getAngle(startLatLng.lon, startLatLng.lat, endLatLng.lon, endLatLng.lat));
Objects.requireNonNull(CallerMapUIServiceManager.INSTANCE.getMarkerService()).drawerArrowsMarkerWithLocation(newLo, WARNING_ARROWS, 10, new Double(rotate).intValue());
CallerLogger.INSTANCE.d(M_V2X + TAG, "小箭头位置" + newLo);
}
}
}
//线随车动
public void onCarLocationChanged2(MogoLocation latLng) {
carLocation = new MogoLatLng(latLng.getLatitude(), latLng.getLongitude());
if (MogoStatusManager.getInstance().isVrMode() && !isSelfLineClear) {
if (mCloundWarningInfo != null) {
V2XLocation v2XLocation = new V2XLocation();
v2XLocation.setLat(latLng.getLatitude());
v2XLocation.setLon(latLng.getLongitude());
mCloundWarningInfo.setCarLocation(v2XLocation);
}
//衡阳交付-取消划线需求,只渲染识别物红色模型移动过程
//drawSelfCarLine(latLng.getLongitude(), latLng.getLatitude(), latLng.getBearing());
}
CallerLogger.INSTANCE.d(M_V2X + TAG, "车辆行驶轨迹" + latLng.getLongitude() + "," + latLng.getLatitude());
}
}

View File

@@ -0,0 +1,13 @@
package com.mogo.eagle.function.biz.v2x.v2n.scenario.view;
/**
* author : donghongyu
* e-mail : 1358506549@qq.com
* date : 2020/5/15 4:13 PM
* desc : V2X安全驾驶场景接口
* version: 1.0
*/
public interface IV2XMarker<T> {
void drawPOI(T entity);
}

View File

@@ -0,0 +1,14 @@
package com.mogo.eagle.function.biz.v2x.v2n.test
class TestConsts {
companion object {
/**
* V2X 测试控制面板广播Action
*/
@JvmField
val BROADCAST_TEST_PANEL_CONTROL_TYPE_EXTRA_KEY = "sceneType"
}
}

View File

@@ -0,0 +1,189 @@
package com.mogo.eagle.function.biz.v2x.v2n.test;
import static com.mogo.eagle.core.data.map.entity.V2XMessageEntity.V2XTypeEnum.ALERT_ROAD_WARNING;
import com.mogo.eagle.core.data.map.MogoLatLng;
import com.mogo.eagle.core.data.map.entity.MarkerLocation;
import com.mogo.eagle.core.data.map.entity.V2XMessageEntity;
import com.mogo.eagle.core.data.map.entity.V2XRoadEventEntity;
import com.mogo.eagle.core.data.map.entity.V2XWarningEntity;
import com.mogo.eagle.core.function.v2x.R;
import com.mogo.eagle.core.data.v2x.V2XOptimalRouteDataRes;
import com.mogo.eagle.core.network.utils.GsonUtil;
import com.mogo.eagle.core.utilcode.util.Utils;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.List;
/**
* author : donghongyu
* e-mail : 1358506549@qq.com
* date : 2020-01-0918:20
* desc : 生成测试数据
* version: 1.0
*/
public class TestOnLineCarUtils {
/**
* 模拟道路事件测试数据
*/
public static V2XMessageEntity<V2XRoadEventEntity> getV2XScenarioAIRoadEventData() {
V2XRoadEventEntity entity = new V2XRoadEventEntity();
entity.setLocation(new MarkerLocation());
entity.setShowEventButton(false);
entity.setPoiType("100061");
entity.setExpireTime(20000);
V2XMessageEntity<V2XRoadEventEntity> body = new V2XMessageEntity<>();
body.setContent(entity);
body.setType(ALERT_ROAD_WARNING);
return body;
}
/**
* 模拟道路事件UGC测试数据
*/
public static V2XMessageEntity<V2XRoadEventEntity> getV2XScenarioRoadEventUGCData() {
try {
InputStream inputStream = Utils.getApp()
.getResources()
.openRawResource(R.raw.scenario_road_event_data);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int len = -1;
byte[] buffer = new byte[1024];
while ((len = inputStream.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
inputStream.close();
// 加载数据源
V2XRoadEventEntity v2xRoadEventEntity = GsonUtil.objectFromJson(baos.toString(), V2XRoadEventEntity.class);
V2XMessageEntity<V2XRoadEventEntity> v2xMessageEntity = new V2XMessageEntity<>();
// 控制类型
v2xMessageEntity.setType(V2XMessageEntity.V2XTypeEnum.ALERT_EVENT_UGC_WARNING);
// 设置数据
v2xMessageEntity.setContent(v2xRoadEventEntity);
return v2xMessageEntity;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 测试数据
*/
public static V2XMessageEntity getV2XScenarioPushFrontWarningEventData(String adasResult) {
try {
int id = R.raw.scenario_warning_event_data_right;
switch (adasResult) {
case "left":
id = R.raw.scenario_warning_event_data_left;
break;
case "pedestrians":
id = R.raw.scenario_warning_event_data_pedestrians;
break;
default:
}
InputStream inputStream = Utils.getApp()
.getResources()
.openRawResource(id);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int len = -1;
byte[] buffer = new byte[1024];
while ((len = inputStream.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
inputStream.close();
// 加载数据源
V2XWarningEntity warningEntity = GsonUtil.objectFromJson(baos.toString(), V2XWarningEntity.class);
V2XMessageEntity messageEntity = new V2XMessageEntity();
messageEntity.setType(V2XMessageEntity.V2XTypeEnum.ALERT_THE_FRONT_WEAKNESS);
messageEntity.setContent(warningEntity);
return messageEntity;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 模拟最优路线推送
*/
public static V2XMessageEntity<V2XOptimalRouteDataRes> getV2XOptimalRoute() {
try {
InputStream inputStream = Utils.getApp()
.getResources()
.openRawResource(R.raw.test_data_v2x_zuiyouluxian);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int len = -1;
byte[] buffer = new byte[1024];
while ((len = inputStream.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
inputStream.close();
// 加载数据源
V2XOptimalRouteDataRes v2xRoadEventEntity = GsonUtil.objectFromJson(baos.toString(), V2XOptimalRouteDataRes.class);
V2XMessageEntity<V2XOptimalRouteDataRes> v2xMessageEntity = new V2XMessageEntity<>();
// 控制类型
v2xMessageEntity.setType(V2XMessageEntity.V2XTypeEnum.ALERT_PUSH_VR_SHOW);
// 设置数据
v2xMessageEntity.setContent(v2xRoadEventEntity);
return v2xMessageEntity;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 自车求助测试数据
*/
public static V2XMessageEntity<Boolean> getV2XScenarioCarForHelpEventData() {
try {
V2XMessageEntity<Boolean> v2xMessageEntity = new V2XMessageEntity<>();
// 控制类型
v2xMessageEntity.setType(V2XMessageEntity.V2XTypeEnum.ALERT_CAR_FOR_HELP);
// 设置数据
v2xMessageEntity.setContent(true);
return v2xMessageEntity;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 返回绘制线路测试数据
*
* @return
*/
public static List<MogoLatLng> getTestCoordinates() {
try {
InputStream inputStream = Utils.getApp()
.getResources()
.openRawResource(R.raw.test_coordinates);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int len = -1;
byte[] buffer = new byte[1024];
while ((len = inputStream.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
inputStream.close();
// 加载数据源
return GsonUtil.arrayFromJson(baos.toString(), MogoLatLng.class);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}

View File

@@ -0,0 +1,90 @@
package com.mogo.eagle.function.biz.v2x.v2n.test;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.mogo.eagle.core.data.map.MogoLatLng;
import com.mogo.eagle.core.data.map.entity.V2XMessageEntity;
import com.mogo.eagle.core.data.map.entity.V2XRoadEventEntity;
import com.mogo.eagle.core.data.v2x.V2XOptimalRouteDataRes;
import com.mogo.eagle.function.biz.v2x.v2n.consts.V2XConst;
import java.util.List;
/**
* V2X 测试面板广播接收,目的是可以通过广播调用起来面板
*
* @author donghongyu
*/
public class TestV2XReceiver extends BroadcastReceiver {
private static final String TAG = "TestV2XReceiver";
private Context mContext;
@Override
public void onReceive(Context context, Intent intent) {
try {
this.mContext = context;
int sceneType = intent.getIntExtra(TestConsts.BROADCAST_TEST_PANEL_CONTROL_TYPE_EXTRA_KEY, 0);
// 分发场景
dispatchSceneTest(sceneType);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 分发处理场景
*
* @param sceneType 场景类型
*/
private void dispatchSceneTest(int sceneType) {
if (sceneType == 1) {// 触发AI道路施工事件
V2XMessageEntity<V2XRoadEventEntity> v2XMessageEntity =
TestOnLineCarUtils.getV2XScenarioAIRoadEventData();
Intent intent = new Intent(V2XConst.BROADCAST_SCENE_HANDLER_ACTION);
intent.putExtra(V2XConst.BROADCAST_SCENE_EXTRA_KEY, v2XMessageEntity);
LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
} else if (sceneType == 10) {//触发事件UGC
V2XMessageEntity<V2XRoadEventEntity> v2XMessageEntity =
TestOnLineCarUtils.getV2XScenarioRoadEventUGCData();
Intent intent = new Intent(V2XConst.BROADCAST_SCENE_HANDLER_ACTION);
intent.putExtra(V2XConst.BROADCAST_SCENE_EXTRA_KEY, v2XMessageEntity);
LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
} else if (sceneType == 12) {//车路云场景预警-右侧
V2XMessageEntity messageEntity = TestOnLineCarUtils.getV2XScenarioPushFrontWarningEventData("right");
Intent intent = new Intent(V2XConst.BROADCAST_SCENE_HANDLER_ACTION);
intent.putExtra(V2XConst.BROADCAST_SCENE_EXTRA_KEY, messageEntity);
LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
} else if (sceneType == 13) {//车路云场景预警-左侧
V2XMessageEntity messageEntity = TestOnLineCarUtils.getV2XScenarioPushFrontWarningEventData("left");
Intent intent = new Intent(V2XConst.BROADCAST_SCENE_HANDLER_ACTION);
intent.putExtra(V2XConst.BROADCAST_SCENE_EXTRA_KEY, messageEntity);
LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
} else if (sceneType == 14) {//行人预警,行人路线预测 车路云预警-前方行人
V2XMessageEntity messageEntity = TestOnLineCarUtils.getV2XScenarioPushFrontWarningEventData("pedestrians");
Intent intent = new Intent(V2XConst.BROADCAST_SCENE_HANDLER_ACTION);
intent.putExtra(V2XConst.BROADCAST_SCENE_EXTRA_KEY, messageEntity);
LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
} else if (sceneType == 17) {//最优路线推荐
V2XMessageEntity<V2XOptimalRouteDataRes> v2XMessageEntity =
TestOnLineCarUtils.getV2XOptimalRoute();
Intent intent = new Intent(V2XConst.BROADCAST_SCENE_HANDLER_ACTION);
intent.putExtra(V2XConst.BROADCAST_SCENE_EXTRA_KEY, v2XMessageEntity);
LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
} else if (sceneType == 20) {// 小地图绘制线
List<MogoLatLng> coordinates = TestOnLineCarUtils.getTestCoordinates();
// CallerSmpManager.drawablePolyline(coordinates);
} else if (sceneType == 21) {// 小地图清除绘制线
// CallerSmpManager.clearPolyline();
}
}
}

View File

@@ -0,0 +1,52 @@
package com.mogo.eagle.function.biz.v2x.v2n.utils
import kotlin.math.asin
import kotlin.math.cos
import kotlin.math.sin
import kotlin.math.sqrt
internal class DistanceUtils {
companion object {
/**
* @param lon1
* @param lat1
* @param lon2
* @param lat2
* @return 两坐标的距离 单位M
*/
fun calculateLineDistance(lon1: Double, lat1: Double, lon2: Double, lat2: Double): Float {
return try {
var var2 = lon1
var var4 = lat1
var var6 = lon2
var var8 = lat2
var2 *= 0.01745329251994329
var4 *= 0.01745329251994329
var6 *= 0.01745329251994329
var8 *= 0.01745329251994329
val var10 = sin(var2)
val var12 = sin(var4)
val var14 = cos(var2)
val var16 = cos(var4)
val var18 = sin(var6)
val var20 = sin(var8)
val var22 = cos(var6)
val var24 = cos(var8)
val var28 = DoubleArray(3)
val var29 = DoubleArray(3)
var28[0] = var16 * var14
var28[1] = var16 * var10
var28[2] = var12
var29[0] = var24 * var22
var29[1] = var24 * var18
var29[2] = var20
(asin(sqrt((var28[0] - var29[0]) * (var28[0] - var29[0]) + (var28[1] - var29[1]) * (var28[1] - var29[1]) + (var28[2] - var29[2]) * (var28[2] - var29[2])) / 2.0) * 1.27420015798544E7).toFloat()
} catch (var26: Throwable) {
var26.printStackTrace()
0.0f
}
}
}
}

View File

@@ -0,0 +1,95 @@
package com.mogo.eagle.function.biz.v2x.v2n.utils
import androidx.core.util.Pair
import com.mogo.eagle.core.data.enums.EventTypeEnumNew.Companion.isRoadEvent
import com.mogo.eagle.core.data.map.entity.MarkerExploreWay
import com.mogo.eagle.core.data.map.entity.MarkerLocation
import com.mogo.eagle.core.data.map.entity.V2XRoadEventEntity
import com.mogo.eagle.core.data.v2x.V2XMarkerCardResult
import com.mogo.eagle.core.data.v2x.V2XRoadXData
import com.mogo.eagle.function.biz.v2x.v2n.scenario.scene.airoad.AiRoadMarker
import com.mogo.eagle.core.utilcode.util.CoordinateTransform
import mogo.telematics.pad.MessagePad
import roadwork.Road
fun Road.RW_PB.toRoadMarker(): V2XMarkerCardResult =
V2XMarkerCardResult().also { l1 ->
val centerX = this.roadwork?.center?.point?.lon ?: 0.0
val centerY = this.roadwork?.center?.point?.lat ?: 0.0
val id = "${centerX}_${centerY}"
l1.exploreWay = ArrayList<MarkerExploreWay>().also { l2 ->
l2.add(MarkerExploreWay().also { l3 ->
l3.poiType = this.roadwork?.poiType?.toString()
l3.setGenerateTime(this.roadwork?.detectTime ?: 0L)
l3.location = MarkerLocation().also { l4 ->
val p = CoordinateTransform.WGS84ToGCJ02(this.roadwork?.center?.point?.lon ?: 0.0, this.roadwork?.center?.point?.lat ?: 0.0)
l4.lon = p[0]
l4.lat = p[1]
l4.angle = this.roadwork?.center?.road?.bearing?.toDouble() ?: 0.0
}
l3.infoId = id
l3.gpsLocation = Pair(this.roadwork?.center?.point?.lon ?: 0.0, this.roadwork?.center?.point?.lat ?: 0.0)
l3.polygon = this.roadwork?.polygonList?.takeIf { it.isNotEmpty() }?.map { Pair(it.lon, it.lat) }
})
}
AiRoadMarker.aiMakers[id]?.receive()
}
fun V2XRoadXData.toRoadMarker(): V2XMarkerCardResult =
V2XMarkerCardResult().also { l1 ->
l1.exploreWay = ArrayList<MarkerExploreWay>().also { l2 ->
l2.add(MarkerExploreWay().also { l3 ->
l3.poiType = this.poiType
l3.setGenerateTime(this.detectTime ?: 0L)
l3.location = MarkerLocation().also { l4 ->
val p = CoordinateTransform.WGS84ToGCJ02(this.center?.lon ?: 0.0, this.center?.lat ?: 0.0)
l4.lon = p[0]
l4.lat = p[1]
l4.angle = this.centerRoad?.bearing ?: 0.0
}
l3.infoId = this.index
l3.gpsLocation = Pair(this.center?.lon ?: 0.0, this.center?.lat ?: 0.0)
l3.polygon = this.polygon?.takeIf { it.isNotEmpty() }?.map { Pair(it.lon, it.lat) }
})
}
AiRoadMarker.aiMakers[this.index]?.receive()
}
fun MessagePad.TrackedObject.toRoadMarker(poiType: String): V2XMarkerCardResult =
V2XMarkerCardResult().also { l1 ->
val id = "${this.longitude}_${this.latitude}"
l1.exploreWay = ArrayList<MarkerExploreWay>().also { l2 ->
l2.add(MarkerExploreWay().also { l3 ->
l3.poiType = poiType
l3.setGenerateTime(0L)
l3.location = MarkerLocation().also { l4 ->
val p = CoordinateTransform.WGS84ToGCJ02(this.longitude, this.latitude)
l4.lon = p[0]
l4.lat = p[1]
l4.angle = this.heading
}
l3.infoId = id
l3.gpsLocation = Pair(this.longitude, this.latitude)
l3.polygon = this.polygonList?.takeIf { it.isNotEmpty() }?.map { Pair(it.longitude, it.latitude) }
})
}
AiRoadMarker.aiMakers[id]?.receive()
}
fun V2XMarkerCardResult.toV2XRoadEventEntity(): V2XRoadEventEntity =
V2XRoadEventEntity().also { l1 ->
val exploreWayList: List<MarkerExploreWay>? = this.exploreWay
if (!exploreWayList.isNullOrEmpty() && exploreWayList.isNotEmpty()) {
for (markerExploreWay in exploreWayList) {
if (isRoadEvent(markerExploreWay.poiType)) {
val markerLocation = markerExploreWay.location
l1.location = markerLocation
l1.poiType = markerExploreWay.poiType
l1.noveltyInfo = markerExploreWay
l1.expireTime = 20000
}
}
}
}

View File

@@ -0,0 +1,38 @@
package com.mogo.eagle.function.biz.v2x.v2n.utils
import android.content.Context
import android.graphics.Rect
import com.mogo.eagle.core.data.map.MogoLatLng
import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationWGS84ListenerManager
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager
import com.mogo.eagle.core.utilcode.util.WindowUtils
class MapUtils {
companion object {
@JvmStatic
fun zoomMap(latLng: MogoLatLng?, context: Context) {
try {
if (latLng == null) {
return
}
val mBoundRect = Rect()
mBoundRect.bottom = WindowUtils.dip2px(context, 100f)
mBoundRect.top = WindowUtils.dip2px(context, 370f)
mBoundRect.left = WindowUtils.dip2px(context, 575f)
mBoundRect.right = WindowUtils.dip2px(context, 100f)
// 当前车辆位置
val carLocation = MogoLatLng(
CallerChassisLocationWGS84ListenerManager.getChassisLocationWGS84().latitude,
CallerChassisLocationWGS84ListenerManager.getChassisLocationWGS84().longitude
)
// 调整自适应的地图镜头
CallerMapUIServiceManager.getMapUIController()
?.showBounds("MapUtils", carLocation, listOf(latLng), mBoundRect, true)
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}

View File

@@ -0,0 +1,70 @@
package com.mogo.eagle.function.biz.v2x.v2n.view
import android.content.Context
import android.graphics.Bitmap
import android.view.LayoutInflater
import androidx.constraintlayout.widget.ConstraintLayout
import com.mogo.eagle.core.data.enums.EventTypeEnumNew
import com.mogo.eagle.core.data.map.entity.V2XRoadEventEntity
import com.mogo.eagle.core.function.biz.R
import com.mogo.eagle.core.utilcode.util.ViewUtils
import kotlinx.android.synthetic.main.view_marker_event_car.view.*
/**
* author : donghongyu
* e-mail : 1358506549@qq.com
* date : 2020-01-0619:55
* desc :
* 3、道路事件
* 2.18 演示 :驾驶模式中地图展示“拥堵“、“施工”;
* ADAS模式下还包含 原有的拥堵、交通检查、封路事件)
* version: 1.0
*/
class V2XMarkerRoadEventView(context: Context, alarmInfo: V2XRoadEventEntity) :
ConstraintLayout(context) {
companion object{
const val TAG = "V2XMarkerRoadEventView"
}
init {
initView(context, alarmInfo)
}
fun initView(context: Context, alarmInfo: V2XRoadEventEntity) {
if (alarmInfo.poiType == EventTypeEnumNew.ALERT_FRONT_CAR.poiType ||
alarmInfo.poiType == EventTypeEnumNew.ALERT_CAR_TROUBLE_WARNING.poiType
) {
LayoutInflater.from(context)
.inflate(R.layout.view_marker_event_car, this)
} else {
LayoutInflater.from(context)
.inflate(R.layout.view_marker_event_road, this)
}
updateIcon(alarmInfo)
}
/**
* @see EventTypeEnumNew
*/
private fun updateIcon(alarmInfo: V2XRoadEventEntity) {
// 道路施工、积水、路面结冰、浓雾、事故、拥堵
val iconResId = EventTypeEnumNew.getUpdateIconRes(alarmInfo.poiType)
if (iconResId != 0) {
ivCar.setImageResource(iconResId)
}
}
/**
* 背景
*/
fun setBackground(imageRes: Int): V2XMarkerRoadEventView {
ivBg.setImageResource(imageRes)
return this
}
fun getView(): Bitmap {
return ViewUtils.fromView(this)
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Some files were not shown because too many files have changed in this diff Show More