[6.5.0][道路事件] 绿波通行业务逻辑

This commit is contained in:
renwj
2024-07-03 19:50:49 +08:00
parent fd087758c9
commit de4d758930
10 changed files with 190 additions and 31 deletions

View File

@@ -3,8 +3,10 @@ package com.mogo.eagle.function.biz.v2x.v2n.pnc
import android.os.Handler
import android.os.HandlerThread
import android.os.Message
import android.text.TextUtils
import android.util.Log
import androidx.core.util.Pair
import com.mogo.commons.voice.AIAssist
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.data.enums.CommunicationType
import com.mogo.eagle.core.data.enums.DataSourceType
@@ -33,6 +35,7 @@ import com.mogo.eagle.core.function.call.map.CallerVisualAngleManager
import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxManager.saveMsgBox
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.util.AppStateManager
import com.mogo.eagle.core.utilcode.util.CoordinateTransform
import com.mogo.eagle.core.utilcode.util.CoordinateUtils
import com.mogo.eagle.core.utilcode.util.DrivingDirectionUtils
@@ -41,14 +44,17 @@ import com.mogo.eagle.function.biz.v2x.v2n.scenario.scene.airoad.AiRoadMarker
import com.mogo.eagle.function.biz.v2x.v2n.scenario.scene.airoad.AiRoadMarker.Marker
import com.mogo.eagle.function.biz.v2x.v2n.utils.V2NUtils
import com.mogo.eagle.function.biz.v2x.v2n.utils.V2XEventAnalyticsManager
import com.mogo.map.MapDataWrapper
import com.mogo.map.entities.Lane
import mogo.telematics.pad.MessagePad
import mogo.telematics.pad.MessagePad.Header
import mogo.telematics.pad.MessagePad.TrackedObject
import mogo.telematics.pad.MessagePad.V2nCrossSpeed
import mogo.v2x.MogoV2X
import mogo.v2x.MogoV2X.RSI_PB
import mogo.v2x.MogoV2X.RTEData_PB
import java.util.concurrent.TimeUnit.SECONDS
import kotlin.math.abs
/**
* V2N上车相关事件绘制
@@ -60,6 +66,7 @@ internal object V2NIdentifyDrawer {
private const val MSG_WHAT_DRAW_SHIGONE = 0x1010 // 道路施工
private const val MSG_WHAT_DRAW_SHIGU = 0x1011 // 交通事故
private const val MSG_WHAT_DRAW_YONGDU = 0x1012 // 交通拥堵
private const val MSG_WHAT_DRAW_GREEN_WAVE = 0x1013 // 绿波通行
private val callback = Handler.Callback { msg ->
if (msg.what == MSG_WHAT_DRAW_SHIGONE || msg.what == MSG_WHAT_DRAW_SHIGU) {
@@ -150,33 +157,6 @@ internal object V2NIdentifyDrawer {
)
)
)
// CallerHmiManager.warningV2X(
// poiType,
// alertContent,
// ttsContent,
// object : IMoGoWarningStatusListener {
// override fun onShow() {
// super.onShow()
// runCatching { CallerHmiManager.notifyXiaoZhiStatusChanged(V2N(EventTypeEnumNew.getEnumType(poiType)), State.START) }
// CallerVisualAngleManager.changeAngle(
// RoadEvent(
// itx.longitude,
// itx.latitude,
// itx.angle
// )
// )
// }
//
// override fun onDismiss() {
// super.onDismiss()
// runCatching { CallerHmiManager.notifyXiaoZhiStatusChanged(V2N(EventTypeEnumNew.getEnumType(poiType)), State.STOP) }
// CallerVisualAngleManager.changeAngle(Default())
// }
// },
// ALERT_WARNING_TOP,
// 10000,
// false
// )
if (polygon.isNotEmpty()) {
val decision = V2NUtils.computeOccupyLanesInfo(Triple(car.longitude, car.latitude, car.heading.toFloat()), Triple(itx.longitude, itx.latitude, itx.heading.toFloat()), polygon.map { kotlin.Pair(it.first, it.second) })
if (decision != null) {
@@ -321,6 +301,41 @@ internal object V2NIdentifyDrawer {
}.receive()
}
}
if (msg.what == MSG_WHAT_DRAW_GREEN_WAVE) {
val data = msg.obj as? V2nCrossSpeed ?: return@Callback true
val destX = data.lng
val destY = data.lat
val id = "${destX}_${destY}"
AiRoadMarker.aiMakers.getOrPut(id) {
AiRoadMarker().apply {
try {
val location = CallerChassisLocationWGS84ListenerManager.getChassisLocationWGS84()
val current = abs(location.gnssSpeed) * 3.6f.toInt()
val min = abs(data.speedStraightMin * 3.6f).toInt()
val max = abs(data.speedStraightMax * 3.6f).toInt()
marker(Marker(id, EventTypeEnumNew.TYPE_SOCKET_ROAD_GREE_WAVE.poiType, destX, destY, 0.0, null, null, null), drawMarker = false, false)
if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)) {
AppStateManager.currentActivity()?.let {
val speakText = StringBuilder("保持当前车速即可通过路口,好丝滑!")
if (current < min) {
speakText.setLength(0)
speakText.append("蘑菇推荐您提升车速至${min}千米每小小, 当前车速${current}千米每小时")
}
if (current > max) {
speakText.setLength(0)
speakText.append("蘑菇推荐您降低车速至${max}千米每小时, 当前车速${current}千米每小时")
}
AIAssist.getInstance(it).speakTTSVoice(speakText.toString())
}
}
CallerHmiManager.showGreenWave(min, max, computeCrossCountBetween(Triple(location.longitude, location.latitude, location.heading), kotlin.Pair(destX, destY)))
} finally {
receive()
}
}
}
}
true
}
@@ -390,6 +405,21 @@ internal object V2NIdentifyDrawer {
}
}
private fun computeCrossCountBetween(start: kotlin.Triple<Double, Double, Double>, end: kotlin.Pair<Double, Double>): Int {
val points = V2NUtils.generateIntermediatePoints(kotlin.Pair(start.first, start.second), end, 10.0 * 1e-7)
var crossId = MapDataWrapper.getCrossRoad(start.first, start.second, start.third)?.cross_id_end
val angle = start.third
var count = 1
for (p in points) {
val crossRoad = MapDataWrapper.getCrossRoad(p.first, p.second, angle)
if (crossRoad != null && !TextUtils.isEmpty(crossRoad.cross_id) && !TextUtils.equals(crossId, crossRoad.cross_id)) {
count++
crossId = crossRoad.cross_id
}
}
return count
}
private fun getAlertContent(poiType: String, distance: Double): String {
return when (poiType) {
EventTypeEnumNew.TYPE_SOCKET_ROAD_SHIGONG.poiType -> {
@@ -474,23 +504,36 @@ internal object V2NIdentifyDrawer {
}
}
private fun drawGreenWave(crossSpeed: V2nCrossSpeed) {
Log.d("V2NIdentifyDrawer", "---drawGreenWave---: $crossSpeed, [${FunctionBuildConfig.v2nMainSwitch}, ${FunctionBuildConfig.isNewV2NData}]")
if (V2NCarTypeCheck.verifyCarType() && FunctionBuildConfig.v2nMainSwitch && FunctionBuildConfig.isNewV2NData) {
handler.removeMessages(MSG_WHAT_DRAW_GREEN_WAVE)
handler.sendMessage(Message.obtain(handler, MSG_WHAT_DRAW_GREEN_WAVE, crossSpeed))
}
}
private val nioEventListener = object : IMoGoV2nNioEventListener {
override fun onV2nNioCongestionEvent(congestion: MessagePad.V2nCongestion) {
super.onV2nNioCongestionEvent(congestion)
V2XBizTrace.onAck(congestion, "onV2nNioCongestionEvent", true)
}
override fun onV2nNioCrossoverEvent(event: MessagePad.Event) {
super.onV2nNioCrossoverEvent(event)
V2XBizTrace.onAck(event,"onV2nNioCrossoverEvent", true)
//TODO renwj
}
override fun onV2nNioGreenWavePassageEvent(crossSpeed: MessagePad.V2nCrossSpeed) {
override fun onV2nNioGreenWavePassageEvent(crossSpeed: V2nCrossSpeed) {
super.onV2nNioGreenWavePassageEvent(crossSpeed)
V2XBizTrace.onAck(crossSpeed, "onV2nNioGreenWavePassageEvent", true)
drawGreenWave(crossSpeed)
}
override fun onV2nNioOtherRetrogradeEvent(event: MessagePad.Event) {
super.onV2nNioOtherRetrogradeEvent(event)
CallerLogger.i(TAG, "onV2nNioOtherRetrogradeEvent --> ${event.toString()}")
V2XBizTrace.onAck(event, "onV2nNioOtherRetrogradeEvent", true)
}
}

View File

@@ -7,8 +7,11 @@ import com.mogo.map.entities.Lane
import com.zhidaoauto.map.data.road.CenterLine
import org.locationtech.jts.geom.Coordinate
import org.locationtech.jts.geom.GeometryFactory
import org.locationtech.jts.geom.LineString
import org.locationtech.jts.linearref.LengthIndexedLine
import java.util.concurrent.CountDownLatch
object V2NUtils {
private const val TAG = "V2NUtils"
@@ -42,4 +45,25 @@ object V2NUtils {
}
data class Decision(val laneId: Int? = null,val total: List<Lane>, val occupy: List<Lane>)
fun generateIntermediatePoints(head: Pair<Double, Double>, tail: Pair<Double, Double>, interval: Double): List<Pair<Double, Double>> {
val geometryFactory = GeometryFactory()
val start = Coordinate(head.first, head.second)
val end = Coordinate(tail.first, tail.second)
val line: LineString = geometryFactory.createLineString(arrayOf(start, end))
val indexedLine = LengthIndexedLine(line)
val lineLength = indexedLine.endIndex
val result: MutableList<Coordinate> = ArrayList()
var i = 0.0
while (i <= lineLength) {
val p = indexedLine.extractPoint(i)
result.add(p)
i += interval
}
if (result[result.size - 1].distance(end) > 0.0001) {
result.add(end)
}
return result.map { Pair(it.x, it.y) }
}
}

View File

@@ -4,6 +4,7 @@ import android.content.Context
import android.text.TextUtils
import android.view.Gravity
import android.view.ViewGroup
import android.view.WindowManager
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.lifecycle.lifecycleScope
import com.alibaba.android.arouter.facade.annotation.Route
@@ -30,6 +31,7 @@ import com.mogo.eagle.core.function.call.hmi.CallerHmiViewControlListenerManager
import com.mogo.eagle.core.function.call.v2x.CallerTrafficLightListenerManager
import com.mogo.eagle.core.function.call.v2x.CallerTurnLightListenerManager
import com.mogo.eagle.core.function.hmi.ui.camera.RoadVideoDialog
import com.mogo.eagle.core.function.hmi.ui.greenwave.GreenWaveView
import com.mogo.eagle.core.function.hmi.ui.lookaround.M1LookAroundView
import com.mogo.eagle.core.function.hmi.ui.notice.DispatchDialogManager
import com.mogo.eagle.core.function.hmi.ui.notice.NoticeCheckDialog
@@ -83,6 +85,8 @@ class MoGoHmiProvider : IMoGoHmiProvider {
private val xiaozhi by lazy { XiaoZhiStateManager() }
private val greenWave by lazy { AtomicReference<MoGoPopWindow>() }
override fun init(context: Context?) {
this.context = context
@@ -403,4 +407,29 @@ class MoGoHmiProvider : IMoGoHmiProvider {
override fun notifyXiaoZhiStatusChanged(event: Event, state: State) {
xiaozhi.notify(event, state)
}
override fun showGreenWave(min: Int, max: Int, cross: Int) {
val activity = AppStateManager.currentActivity() ?: return
greenWave.get()?.hide()
val content = GreenWaveView(activity)
MoGoPopWindow.Builder()
.contentView(content)
.width(WindowManager.LayoutParams.WRAP_CONTENT)
.height(WindowManager.LayoutParams.WRAP_CONTENT)
.attachToActivity(activity)
.gravityInActivity(Gravity.END)
.onDismissed {
greenWave.set(null)
}
.onShowed {
content.bind(min, max, cross)
}
.build().also {
greenWave.set(it)
}.show()
}
override fun dismissGreenWave() {
greenWave.get()?.hide()
}
}

View File

@@ -1,7 +1,6 @@
package com.mogo.eagle.core.function.hmi.ui.greenwave
import android.content.Context
import android.os.Looper
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.MotionEvent

View File

@@ -1,5 +1,6 @@
package com.mogo.eagle.core.data.enums
import android.view.View
import com.mogo.eagle.core.data.R
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
@@ -518,6 +519,13 @@ enum class EventTypeEnumNew(
content = "前方%s米有车辆异常倒车/逆行,蘑菇提醒您注意观察小心通过",
tts = "前方%s米有车辆异常倒车/逆行,蘑菇提醒您注意观察小心通过"
),
TYPE_SOCKET_ROAD_GREE_WAVE(
"100063",
"绿波通行",
poiTypeSrcVr = View.NO_ID,
content = "保持当前车速即可通过路口,好丝滑!",
tts = "保持当前车速即可通过路口,好丝滑!"
),
TYPE_ERROR(
0.toString(),
"未知/错误/异常",

View File

@@ -217,4 +217,14 @@ interface IMoGoHmiProvider :IProvider{
* 通知小智形象要变化了
*/
fun notifyXiaoZhiStatusChanged(event: Event, state: State)
/**
* 展示绿波通行弹窗
*/
fun showGreenWave(min: Int, max: Int, cross: Int)
/**
* 隐藏绿波通弹窗
*/
fun dismissGreenWave()
}

View File

@@ -317,4 +317,18 @@ object CallerHmiManager {
fun notifyXiaoZhiStatusChanged(event: Event, state: State) {
hmiProviderApi?.notifyXiaoZhiStatusChanged(event, state)
}
/**
* 展示绿波通行弹窗
*/
fun showGreenWave(min: Int, max: Int, cross: Int) {
hmiProviderApi?.showGreenWave(min, max, cross)
}
/**
* 隐藏绿波通行弹窗
*/
fun dismissGreenWave() {
hmiProviderApi?.dismissGreenWave()
}
}

View File

@@ -2,6 +2,7 @@ package com.mogo.map
import com.mogo.eagle.core.data.map.MogoLocation
import com.mogo.map.entities.BusStation
import com.mogo.map.entities.CrossRoad
import com.mogo.map.entities.Lane
import com.mogo.map.entities.RoadInfo
import com.zhidaoauto.map.data.point.LonLatPoint
@@ -121,4 +122,9 @@ interface IMogoData {
* 获取公交站点集合
*/
fun getBusStation(routeList: ArrayList<LonLatPoint>): List<BusStation>
}
/**
* 获取路口数据
*/
fun getCrossRoad(lon: Double, lat: Double, angle: Double): CrossRoad?
}

View File

@@ -0,0 +1,9 @@
package com.mogo.map.entities
data class CrossRoad(
val status: Int, // 0: 不在路口 1: 在路口
val tile_id: String, // 起始路口瓦片id或者当前路口的瓦片id
val cross_id: String, // 起始路口id或当前路口id
val tile_id_end: String, //
val cross_id_end: String
)

View File

@@ -6,11 +6,13 @@ import com.mogo.eagle.core.utilcode.mogo.logger.Logger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_MAP
import com.mogo.map.MogoData.Companion.mogoMapData
import com.mogo.map.entities.BusStation
import com.mogo.map.entities.CrossRoad
import com.mogo.map.entities.Lane
import com.mogo.map.location.GDLocationClient.Companion.gdLocationClient
import com.mogo.map.utils.HDMapUtils.getHDCityCode
import com.zhidaoauto.map.data.point.LonLatPoint
import com.zhidaoauto.map.data.road.CenterLine
import com.zhidaoauto.map.data.road.RoadCross
import com.zhidaoauto.map.data.road.RoadNameInfo
import com.zhidaoauto.map.data.road.RoadRectInfos
import com.zhidaoauto.map.data.road.RoutePath
@@ -21,6 +23,7 @@ import com.zhidaoauto.map.sdk.open.abs.OnHdDataDownByCityListener
import com.zhidaoauto.map.sdk.open.data.CityInfo
import com.zhidaoauto.map.sdk.open.data.MapDataApi
import java.util.concurrent.CountDownLatch
import java.util.concurrent.atomic.AtomicReference
/**
* 地图数据工具,涉及到数据调用可能会有耗时建议IO操作
@@ -303,4 +306,18 @@ object MapDataWrapper : IMogoData {
latch.await()
return resultList
}
override fun getCrossRoad(lon: Double, lat: Double, angle: Double): CrossRoad? {
val latch = CountDownLatch(1)
val temp = AtomicReference<CrossRoad>()
MapDataApi.getCrossRoad(lon, lat, angle.toFloat(), object : IResult<RoadCross> {
override fun result(code: Int, result: RoadCross?) {
temp.set(CrossRoad(result?.status ?: 0, result?.tile_id ?: "", result?.cross_id ?: "", result?.tile_id_end ?: "", result?.cross_id_end ?: ""))
latch.countDown()
}
})
latch.await()
return temp.get()
}
}