diff --git a/core/function-impl/mogo-core-function-biz/src/main/java/com/mogo/eagle/function/biz/v2x/v2n/pnc/V2NIdentifyDrawer.kt b/core/function-impl/mogo-core-function-biz/src/main/java/com/mogo/eagle/function/biz/v2x/v2n/pnc/V2NIdentifyDrawer.kt index 146c4d6bb3..73a8883432 100644 --- a/core/function-impl/mogo-core-function-biz/src/main/java/com/mogo/eagle/function/biz/v2x/v2n/pnc/V2NIdentifyDrawer.kt +++ b/core/function-impl/mogo-core-function-biz/src/main/java/com/mogo/eagle/function/biz/v2x/v2n/pnc/V2NIdentifyDrawer.kt @@ -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, end: kotlin.Pair): 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) } } diff --git a/core/function-impl/mogo-core-function-biz/src/main/java/com/mogo/eagle/function/biz/v2x/v2n/utils/V2NUtils.kt b/core/function-impl/mogo-core-function-biz/src/main/java/com/mogo/eagle/function/biz/v2x/v2n/utils/V2NUtils.kt index e233531b36..2e52ad28ec 100644 --- a/core/function-impl/mogo-core-function-biz/src/main/java/com/mogo/eagle/function/biz/v2x/v2n/utils/V2NUtils.kt +++ b/core/function-impl/mogo-core-function-biz/src/main/java/com/mogo/eagle/function/biz/v2x/v2n/utils/V2NUtils.kt @@ -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, val occupy: List) + + + fun generateIntermediatePoints(head: Pair, tail: Pair, interval: Double): List> { + 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 = 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) } + } } \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiProvider.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiProvider.kt index cda2a7f5bf..6a9985c591 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiProvider.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiProvider.kt @@ -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() } + 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() + } } \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/greenwave/GreenWaveView.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/greenwave/GreenWaveView.kt index 0744769176..77d3c1dd99 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/greenwave/GreenWaveView.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/greenwave/GreenWaveView.kt @@ -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 diff --git a/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/enums/EventTypeEnumNew.kt b/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/enums/EventTypeEnumNew.kt index a6d812c06a..ecd8c64586 100644 --- a/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/enums/EventTypeEnumNew.kt +++ b/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/enums/EventTypeEnumNew.kt @@ -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(), "未知/错误/异常", diff --git a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/hmi/warning/IMoGoHmiProvider.kt b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/hmi/warning/IMoGoHmiProvider.kt index fc5e2a7874..54840daaa6 100644 --- a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/hmi/warning/IMoGoHmiProvider.kt +++ b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/hmi/warning/IMoGoHmiProvider.kt @@ -217,4 +217,14 @@ interface IMoGoHmiProvider :IProvider{ * 通知小智形象要变化了 */ fun notifyXiaoZhiStatusChanged(event: Event, state: State) + + /** + * 展示绿波通行弹窗 + */ + fun showGreenWave(min: Int, max: Int, cross: Int) + + /** + * 隐藏绿波通弹窗 + */ + fun dismissGreenWave() } \ No newline at end of file diff --git a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/hmi/CallerHmiManager.kt b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/hmi/CallerHmiManager.kt index 7270a55fda..9e2d5a04af 100644 --- a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/hmi/CallerHmiManager.kt +++ b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/hmi/CallerHmiManager.kt @@ -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() + } } \ No newline at end of file diff --git a/libraries/mogo-map-api/src/main/java/com/mogo/map/IMogoData.kt b/libraries/mogo-map-api/src/main/java/com/mogo/map/IMogoData.kt index 3e73cc5ec2..0a5de66661 100644 --- a/libraries/mogo-map-api/src/main/java/com/mogo/map/IMogoData.kt +++ b/libraries/mogo-map-api/src/main/java/com/mogo/map/IMogoData.kt @@ -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): List -} \ No newline at end of file + + /** + * 获取路口数据 + */ + fun getCrossRoad(lon: Double, lat: Double, angle: Double): CrossRoad? +} diff --git a/libraries/mogo-map-api/src/main/java/com/mogo/map/entities/CrossRoad.kt b/libraries/mogo-map-api/src/main/java/com/mogo/map/entities/CrossRoad.kt new file mode 100644 index 0000000000..61d44ce785 --- /dev/null +++ b/libraries/mogo-map-api/src/main/java/com/mogo/map/entities/CrossRoad.kt @@ -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 +) diff --git a/libraries/mogo-map/src/main/java/com/mogo/map/MapDataWrapper.kt b/libraries/mogo-map/src/main/java/com/mogo/map/MapDataWrapper.kt index c6bd7e2ac9..e319ec8514 100644 --- a/libraries/mogo-map/src/main/java/com/mogo/map/MapDataWrapper.kt +++ b/libraries/mogo-map/src/main/java/com/mogo/map/MapDataWrapper.kt @@ -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() + MapDataApi.getCrossRoad(lon, lat, angle.toFloat(), object : IResult { + + 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() + } } \ No newline at end of file