[6.5.0][道路事件] 修正施工占道提示逻辑
This commit is contained in:
@@ -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<Lane>, total: List<Lane>): kotlin.Pair<Int, String> {
|
||||
if (occupy.size == total.size) {
|
||||
return kotlin.Pair(Int.MIN_VALUE, "更换路线")
|
||||
}
|
||||
val map = HashMap<Int, String>()
|
||||
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 -> {
|
||||
|
||||
@@ -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<Double, Double, Float>, point: Triple<Double, Double, Float> ,polygon: List<Pair<Double, Double>>): 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<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
|
||||
fun computeBestLane(laneId: Int, occupy: List<Lane>, total: List<Lane>): Pair<Int, String> {
|
||||
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<Int, String>()
|
||||
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, "更换路线")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user