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 07fb94a401..de2d62a20f 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 @@ -25,6 +25,7 @@ import com.mogo.eagle.core.function.call.autopilot.CallerV2XListenerManager.V2NC import com.mogo.eagle.core.function.call.autopilot.CallerV2nNioEventListenerManager import com.mogo.eagle.core.function.call.hmi.CallerHmiManager import com.mogo.eagle.core.function.call.hmi.CallerRoadV2NEventWindowListenerManager +import com.mogo.eagle.core.function.call.map.CallerMapRoadListenerManager 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 @@ -34,6 +35,7 @@ import com.mogo.eagle.core.utilcode.util.CoordinateTransform import com.mogo.eagle.core.utilcode.util.CoordinateUtils import com.mogo.eagle.core.utilcode.util.DrivingDirectionUtils import com.mogo.eagle.core.utilcode.util.GsonUtils +import com.mogo.eagle.core.utilcode.util.ThreadUtils import com.mogo.eagle.function.biz.v2x.V2XBizTrace import com.mogo.eagle.function.biz.v2x.v2n.pnc.beans.Extras import com.mogo.eagle.function.biz.v2x.v2n.scenario.scene.airoad.AiRoadMarker @@ -44,6 +46,10 @@ import com.mogo.eagle.function.biz.v2x.v2n.utils.IEventDismissListener import com.mogo.eagle.function.biz.v2x.v2n.utils.V2NUtils import com.mogo.eagle.function.biz.v2x.v2n.utils.V2XEventAnalyticsManager import com.mogo.map.entities.Lane +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.asCoroutineDispatcher +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch import mogo.telematics.pad.MessagePad import mogo.telematics.pad.MessagePad.Header import mogo.telematics.pad.MessagePad.TrackedObject @@ -66,6 +72,8 @@ internal object V2NIdentifyDrawer: IEventDismissListener { private const val MSG_WHAT_DRAW_GREEN_WAVE = 0x1014 // 绿波通行 private const val MSG_WHAT_DRAW_PEOPLE_CROSS = 0x1015 // 行人横穿 + private val scope by lazy { CoroutineScope(ThreadUtils.getCpuPool().asCoroutineDispatcher()) } + private val callback = Handler.Callback { msg -> if (msg.what == MSG_WHAT_DRAW_SHIGONE || msg.what == MSG_WHAT_DRAW_SHIGU) { val events = msg.obj as? List<*> @@ -108,90 +116,97 @@ internal object V2NIdentifyDrawer: IEventDismissListener { Log.d("V2NIdentifyDrawer", "---callback --- id: $id ---") AiRoadMarker.aiMakers.getOrPut(id) { AiRoadMarker().apply { - val poiType = getPoiType(itx.type).poiType - val polygon = itx.polygonList.map { Pair.create(it.longitude, it.latitude) } - marker(Marker(id, - poiType, - itx.longitude, - itx.latitude, - itx.heading, - polygon, - null, - V2XRoadEventEntity().also { e -> - e.poiType = poiType - e.location = MarkerLocation().also { l -> - val p = CoordinateTransform.WGS84ToGCJ02( - itx.longitude, - itx.latitude - ) - l.lon = p[0] - l.lat = p[1] - l.angle = itx.heading - } - e.noveltyInfo = MarkerExploreWay().also { - it.poiType = poiType - it.location = e.location - it.polygon = polygon - } - }, isUseGps = true), true, isDrawRoadLine(poiType) - ) + scope.launch { + Log.d("V2NIdentifyDrawer", "--- 判断是否在路口 ---") + while (CallerMapRoadListenerManager.isInRoadCross()) { + delay(2000) + } + Log.d("V2NIdentifyDrawer", "--- 不在路口了 ---") + val poiType = getPoiType(itx.type).poiType + val polygon = itx.polygonList.map { Pair.create(it.longitude, it.latitude) } + marker(Marker(id, + poiType, + itx.longitude, + itx.latitude, + itx.heading, + polygon, + null, + V2XRoadEventEntity().also { e -> + e.poiType = poiType + e.location = MarkerLocation().also { l -> + val p = CoordinateTransform.WGS84ToGCJ02( + itx.longitude, + itx.latitude + ) + l.lon = p[0] + l.lat = p[1] + l.angle = itx.heading + } + e.noveltyInfo = MarkerExploreWay().also { + it.poiType = poiType + it.location = e.location + it.polygon = polygon + } + }, isUseGps = true), true, isDrawRoadLine(poiType) + ) - val distance = CoordinateUtils.calculateLineDistance( - itx.longitude, - itx.latitude, - car.longitude, - car.latitude - ) - val alertContent = getAlertContent(poiType, distance.toDouble()) - val ttsContent = getTtsContent(poiType, distance.toDouble()) - V2XBizTrace.onAck(TAG, "绘制poi事件:$poiType") - saveMsgBox( - MsgBoxBean( - V2X, - V2XMsg( - poiType, - alertContent, - ttsContent, - CommunicationType.V2N.name + val distance = CoordinateUtils.calculateLineDistance( + itx.longitude, + itx.latitude, + car.longitude, + car.latitude + ) + val alertContent = getAlertContent(poiType, distance.toDouble()) + val ttsContent = getTtsContent(poiType, distance.toDouble()) + V2XBizTrace.onAck(TAG, "绘制poi事件:$poiType") + saveMsgBox( + MsgBoxBean( + V2X, + V2XMsg( + poiType, + alertContent, + ttsContent, + CommunicationType.V2N.name + ) ) ) - ) - 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) { - val isDriver = AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode) - val total = decision.total - val occupy = decision.occupy - val laneId = decision.laneId - val sb = StringBuilder() - if (laneId != null) { - val isOccupy = occupy.find { it.id == laneId } != null - if (isOccupy) { - if (isDriver) { - val bestLane = computeBestLane(laneId, occupy, total) - sb.append("发现前方${distance.toInt()}米${ if (poiType == EventTypeEnumNew.TYPE_SOCKET_ROAD_SHIGONG.poiType) "车道施工" else "车道事故" }@@, 蘑菇建议您尽快${bestLane.second}") + 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) { + val isDriver = AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode) + val total = decision.total + val occupy = decision.occupy + val laneId = decision.laneId + val sb = StringBuilder() + if (laneId != null) { + val isOccupy = occupy.find { it.id == laneId } != null + if (isOccupy) { + if (isDriver) { + val bestLane = V2NUtils.computeBestLane(laneId, occupy, total) + sb.append("发现前方${distance.toInt()}米${ if (poiType == EventTypeEnumNew.TYPE_SOCKET_ROAD_SHIGONG.poiType) "车道施工" else "车道事故" }@@, 蘑菇建议您尽快${bestLane.second}") + } else { + sb.append("发现前方${distance.toInt()}米${ if (poiType == EventTypeEnumNew.TYPE_SOCKET_ROAD_SHIGONG.poiType) "车道施工" else "车道事故" }@@, 蘑菇时刻为您守护") + } } else { - sb.append("发现前方${distance.toInt()}米${ if (poiType == EventTypeEnumNew.TYPE_SOCKET_ROAD_SHIGONG.poiType) "车道施工" else "车道事故" }@@, 蘑菇时刻为您守护") - } - } else { - if (isDriver) { - sb.append("发现前方${distance.toInt()}米${ if (poiType == EventTypeEnumNew.TYPE_SOCKET_ROAD_SHIGONG.poiType) "车道施工" else "车道事故" }@@, 蘑菇提醒您小心${ if (computeDirection(laneId, occupy) > 0) "右侧" else "左侧" }行人及来车") - } else { - sb.append("发现前方${distance.toInt()}米${ if (poiType == EventTypeEnumNew.TYPE_SOCKET_ROAD_SHIGONG.poiType) "车道施工" else "车道事故" }@@, 蘑菇时刻为您守护") + if (isDriver) { + sb.append("发现前方${distance.toInt()}米${ if (poiType == EventTypeEnumNew.TYPE_SOCKET_ROAD_SHIGONG.poiType) "车道施工" else "车道事故" }@@, 蘑菇提醒您小心${ if (computeDirection(laneId, occupy) > 0) "右侧" else "左侧" }行人及来车") + } else { + sb.append("发现前方${distance.toInt()}米${ if (poiType == EventTypeEnumNew.TYPE_SOCKET_ROAD_SHIGONG.poiType) "车道施工" else "车道事故" }@@, 蘑菇时刻为您守护") + } } } + val ss = sb.toString() + val content = ss.substring(0, ss.indexOf("@@")) + val tts = ss.replace("@@", "") + CallerRoadV2NEventWindowListenerManager.showLiveVideo(id, System.currentTimeMillis(), EventTypeEnumNew.getUpdateIconRes(poiType), content, isDriver, tts, itx.cameraIp, itx.longitude, itx.latitude) } - val ss = sb.toString() - val content = ss.substring(0, ss.indexOf("@@")) - val tts = ss.replace("@@", "") - CallerRoadV2NEventWindowListenerManager.showLiveVideo(id, System.currentTimeMillis(), EventTypeEnumNew.getUpdateIconRes(poiType), content, isDriver, tts, itx.cameraIp, itx.longitude, itx.latitude) } + //消息埋点 + V2XEventAnalyticsManager.triggerV2XEvent( + poiType, alertContent, ttsContent, + DataSourceType.AICLOUD, CommunicationType.V2N + ) } - //消息埋点 - V2XEventAnalyticsManager.triggerV2XEvent( - poiType, alertContent, ttsContent, - DataSourceType.AICLOUD, CommunicationType.V2N - ) } }.receive() } @@ -365,46 +380,6 @@ internal object V2NIdentifyDrawer: IEventDismissListener { } } - private fun computeBestLane(laneId: Int, occupy: List, total: List): kotlin.Pair { - if (occupy.size == total.size) { - return kotlin.Pair(Int.MIN_VALUE, "更换路线") - } - val map = HashMap() - if (total.size % 2 == 0) { - val half = total.size / 2 - for (i in 0 until half) { - val left = total[i] - val right = total[half + i] - map[left.id] = "驶入左${i + 1}车道" - map[right.id] = "驶入右${i + 1}车道" - } - } else { - val middle = total.size / 2 - map[total[middle].id] = "驶入中间车道" - for (i in 0 until middle) { - val left = total[i] - val right = total[middle + i + 1] - map[left.id] = "驶入左${i + 1}车道" - map[right.id] = "驶入右${i + 1}车道" - } - } - val ids = occupy.map { it.id } - val freeLanes = total.filter { itx -> !ids.contains(itx.id) } - if (freeLanes.isNotEmpty()) { - var best = Int.MIN_VALUE - var delta = Int.MAX_VALUE - for (lane in freeLanes) { - val abs = abs(lane.id - laneId) - if (abs < delta && lane.id != laneId) { - best = lane.id - delta = abs - } - } - return kotlin.Pair(best, map[best] ?: "更换路线") - } - return kotlin.Pair(Int.MIN_VALUE, "更换路线") - } - private fun getTtsContent(poiType: String, distance: Double): String { return when (poiType) { EventTypeEnumNew.TYPE_SOCKET_ROAD_SHIGONG.poiType -> { 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 af239a5731..19f8bf376a 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,11 +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.geom.LineString.MINIMUM_VALID_SIZE import org.locationtech.jts.geom.Polygon -import org.locationtech.jts.linearref.LengthIndexedLine import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit.SECONDS +import kotlin.math.abs object V2NUtils { @@ -22,7 +22,7 @@ object V2NUtils { fun computeOccupyLanesInfo(car: Triple, point: Triple ,polygon: List>): Decision? { val roadInfo = MapDataWrapper.getRoadInfo(point.first, point.second, point.third) Log.d(TAG, "road_info:$roadInfo") - val lanes = MapDataWrapper.getLaneInfo(roadInfo.tileId, roadInfo.roadId) + val lanes = MapDataWrapper.getLaneInfo(roadInfo.tileId, roadInfo.roadId).sortedByDescending { it.id } Log.d(TAG, "lanes: ${lanes.joinToString(",") { itx -> itx.points.joinToString(",") { "${it.first}, ${it.second}" } } }") if (lanes.isEmpty()) { return null @@ -54,30 +54,57 @@ object V2NUtils { centerLine = it latch.countDown() } - latch.await() - return Decision(centerLine?.lane_id?.toInt() , lanes, occupy) + return try { + if (latch.await(3, SECONDS)) { + Decision(centerLine?.lane_id?.toInt() , lanes, occupy) + } else { + Decision(null, lanes, occupy) + } + } catch (t: Throwable) { + t.printStackTrace() + return Decision(null, lanes, occupy) + } } 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 + fun computeBestLane(laneId: Int, occupy: List, total: List): Pair { + if (occupy.size == total.size) { + return Pair(Int.MIN_VALUE, "更换路线") } - if (result[result.size - 1].distance(end) > 0.0001) { - result.add(end) + val map = HashMap() + if (total.size % 2 == 0) { + val half = total.size / 2 + for (i in 0 until half) { + val left = total[i] + val right = total[half + i] + map[left.id] = "驶入左${i + 1}车道" + map[right.id] = "驶入右${i + 1}车道" + } + } else { + val middle = total.size / 2 + map[total[middle].id] = "驶入中间车道" + for (i in 0 until middle) { + val left = total[i] + val right = total[middle + i + 1] + map[left.id] = "驶入左${i + 1}车道" + map[right.id] = "驶入右${i + 1}车道" + } } - return result.map { Pair(it.x, it.y) } + val ids = occupy.map { it.id } + val freeLanes = total.filter { itx -> !ids.contains(itx.id) } + if (freeLanes.isNotEmpty()) { + var best = Int.MIN_VALUE + var delta = Int.MAX_VALUE + for (lane in freeLanes) { + val abs = abs(lane.id - laneId) + if (abs < delta && lane.id != laneId) { + best = lane.id + delta = abs + } + } + return Pair(best, map[best] ?: "更换路线") + } + return Pair(Int.MIN_VALUE, "更换路线") } } \ No newline at end of file diff --git a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/map/CallerMapRoadListenerManager.kt b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/map/CallerMapRoadListenerManager.kt index 51e35953ad..90ef5abbfb 100644 --- a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/map/CallerMapRoadListenerManager.kt +++ b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/map/CallerMapRoadListenerManager.kt @@ -95,6 +95,10 @@ object CallerMapRoadListenerManager : CallerBase() { } + fun isInRoadCross(): Boolean { + return mCross == 0 + } + fun invokeRoadCrossClick() { M_LISTENERS.forEach { entry -> entry.value.onRoadCrossClick()