[6.5.0] feat: 通过公交站点计算逻辑实现;
This commit is contained in:
@@ -1,20 +1,32 @@
|
||||
package com.mogo.eagle.function.biz.v2x.busstation
|
||||
|
||||
import android.util.Pair
|
||||
import android.os.Handler
|
||||
import android.os.HandlerThread
|
||||
import com.mogo.commons.debug.DebugConfig
|
||||
import com.mogo.eagle.core.data.config.FunctionBuildConfig
|
||||
import com.mogo.eagle.core.data.enums.EventTypeEnumNew
|
||||
import com.mogo.eagle.core.data.map.MogoLocation
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationWGS84Listener
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationWGS84ListenerManager
|
||||
import com.mogo.eagle.core.function.call.hmi.CallerRoadV2NEventWindowListenerManager
|
||||
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager
|
||||
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.Logger
|
||||
import com.mogo.eagle.core.utilcode.util.CoordinateUtils
|
||||
import com.mogo.eagle.core.utilcode.util.DrivingDirectionUtils
|
||||
import com.mogo.map.MogoData
|
||||
import com.mogo.map.entities.BusStation
|
||||
import com.mogo.map.overlay.core.Level
|
||||
import com.mogo.map.overlay.point.Point
|
||||
import com.zhidaoauto.map.data.point.LonLatPoint
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.LinkedList
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import kotlin.math.sin
|
||||
|
||||
/**
|
||||
* 计算通过公交站点 管理类
|
||||
@@ -23,19 +35,154 @@ object BusStationEventManager : IMoGoChassisLocationWGS84Listener {
|
||||
|
||||
const val TAG = "BusStationEventManager"
|
||||
|
||||
private val mScope: CoroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
||||
private val isCalculateNearByStation = AtomicBoolean(false)
|
||||
private val farthestLocationList = ArrayList<LonLatPoint>()
|
||||
private val busStationListNearBy = LinkedHashMap<String, BusStation>()
|
||||
private val mCoroutineScope: CoroutineScope =
|
||||
CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
||||
|
||||
// 距离当前车位置 X 米远的点集合(用来查询根据点查询roadId, 然后用roadId查询路上的公交站点)
|
||||
private val farthestLocationList = ArrayList<LonLatPoint>()
|
||||
|
||||
// 是否在计算附近的公交站点集合
|
||||
private val isCalculateNearByStation = AtomicBoolean(false)
|
||||
|
||||
// 查询出来的符合条件的公交站点集合
|
||||
private val busStationNearByQueue = LinkedList<List<BusStation>>()
|
||||
|
||||
// 需要提醒的公交站点
|
||||
private val busStationListNeedNotified = HashMap<String, BusStation>()
|
||||
|
||||
private val isDriverScreen by lazy {
|
||||
AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)
|
||||
}
|
||||
|
||||
private val checkDistanceRunnable = object : Runnable {
|
||||
override fun run() {
|
||||
try {
|
||||
synchronized(busStationNearByQueue) {
|
||||
if (busStationNearByQueue.isNotEmpty()) {
|
||||
val list = busStationNearByQueue.pollLast()
|
||||
val currentLocation =
|
||||
CallerChassisLocationWGS84ListenerManager.getChassisLocationWGS84()
|
||||
list.forEach {
|
||||
if (!busStationListNeedNotified.containsKey(it.getBusStationId())) {
|
||||
val distance = CoordinateUtils.calculateLineDistance(
|
||||
currentLocation.longitude,
|
||||
currentLocation.latitude,
|
||||
it.getBusStationPoint().longitude,
|
||||
it.getBusStationPoint().latitude,
|
||||
).toInt()
|
||||
val angle = DrivingDirectionUtils.getDegreeOfCar2Poi(
|
||||
currentLocation.longitude,
|
||||
currentLocation.latitude,
|
||||
it.getBusStationPoint().longitude,
|
||||
it.getBusStationPoint().latitude,
|
||||
currentLocation.heading.toInt()
|
||||
)
|
||||
if (distance <= 150 && angle < 90) {
|
||||
it.notifyDistance = distance
|
||||
busStationListNeedNotified[it.getBusStationId()] = it
|
||||
Logger.d(
|
||||
TAG, "addNeedNotifiedBusStation --> ${it.toString()}"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 对已经展示过的做移除 消散操作
|
||||
if (busStationListNeedNotified.isNotEmpty()) {
|
||||
val currentLocation =
|
||||
CallerChassisLocationWGS84ListenerManager.getChassisLocationWGS84()
|
||||
busStationListNeedNotified.values.forEach {
|
||||
val distance = CoordinateUtils.calculateLineDistance(
|
||||
currentLocation.longitude,
|
||||
currentLocation.latitude,
|
||||
it.getBusStationPoint().longitude,
|
||||
it.getBusStationPoint().latitude,
|
||||
).toInt()
|
||||
val angle = DrivingDirectionUtils.getDegreeOfCar2Poi(
|
||||
currentLocation.longitude,
|
||||
currentLocation.latitude,
|
||||
it.getBusStationPoint().longitude,
|
||||
it.getBusStationPoint().latitude,
|
||||
currentLocation.heading.toInt()
|
||||
)
|
||||
if (distance<=5 && angle >= 90) {
|
||||
CallerRoadV2NEventWindowListenerManager.dismiss(it.getBusStationId())
|
||||
busStationListNeedNotified.remove(it.getBusStationId())
|
||||
Logger.d(
|
||||
TAG,
|
||||
"removeNeedNotifiedBusStation --> ${it.toString()}"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 开始提醒
|
||||
if (busStationListNeedNotified.isNotEmpty()) {
|
||||
handler.removeCallbacks(notificationCheckRunnable)
|
||||
handler.post(notificationCheckRunnable)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
} finally {
|
||||
handler?.postDelayed(this, 1000L)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val notificationCheckRunnable = object : Runnable {
|
||||
override fun run() {
|
||||
if (busStationListNeedNotified.isNotEmpty()) {
|
||||
val list = busStationListNeedNotified.values.toList()
|
||||
.filter { it.notifyTime <= 0 && it.notifyDistance > 0 }
|
||||
.sortedBy { it.notifyDistance }
|
||||
if (list.isNotEmpty()) {
|
||||
list.first().also {
|
||||
//TODO 调整调用方式
|
||||
it.notifyTime = System.currentTimeMillis()
|
||||
CallerRoadV2NEventWindowListenerManager.show(
|
||||
it.getBusStationId(),
|
||||
it.notifyTime,
|
||||
EventTypeEnumNew.getUpdateIconRes(""),
|
||||
"前方${it.notifyDistance}米有公交站,蘑菇提醒您小心右侧行人及来车",
|
||||
isDriverScreen,
|
||||
"192.168.1.1",
|
||||
0.0, 0.0
|
||||
)
|
||||
Logger.d(
|
||||
TAG,
|
||||
"showBusStationNotification --> ${it.toString()}"
|
||||
)
|
||||
}
|
||||
if (list.size >= 2) {
|
||||
handler.postDelayed(this, 4000L)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private val handler by lazy {
|
||||
val thread = HandlerThread("road_v2n_bus_station_calculate")
|
||||
thread.start()
|
||||
Handler(thread.looper)
|
||||
}
|
||||
|
||||
fun init() {
|
||||
CallerChassisLocationWGS84ListenerManager.addListener(TAG, 1, this)
|
||||
handler?.post(checkDistanceRunnable)
|
||||
}
|
||||
|
||||
fun unInit() {
|
||||
CallerChassisLocationWGS84ListenerManager.removeListener(TAG)
|
||||
mScope?.cancel()
|
||||
mCoroutineScope?.cancel()
|
||||
busStationNearByQueue?.clear()
|
||||
busStationListNeedNotified?.clear()
|
||||
handler?.removeCallbacks(checkDistanceRunnable)
|
||||
handler?.removeCallbacks(notificationCheckRunnable)
|
||||
handler?.looper?.quit()
|
||||
}
|
||||
|
||||
override fun onChassisLocationWGS84(gnssInfo: MogoLocation) {
|
||||
@@ -52,16 +199,14 @@ object BusStationEventManager : IMoGoChassisLocationWGS84Listener {
|
||||
* @param metersPreSegment 每段多少米
|
||||
*/
|
||||
private fun calculateNearByStation(
|
||||
gnssInfo: MogoLocation,
|
||||
segmentSum: Int,
|
||||
metersPreSegment: Int
|
||||
gnssInfo: MogoLocation, segmentSum: Int, metersPreSegment: Int
|
||||
) {
|
||||
mScope.launch {
|
||||
mCoroutineScope.launch {
|
||||
farthestLocationList.clear()
|
||||
val heading = gnssInfo.heading
|
||||
//每10米一个点,获取150米范围内的坐标点
|
||||
//每metersPreSegment 米一个点,获取 segmentSum * metersPreSegment 米范围内的坐标点
|
||||
for (index in 1..segmentSum) {
|
||||
val newPoint = calculateNewPoint(
|
||||
val newPoint = DrivingDirectionUtils.calculateNewPoint(
|
||||
gnssInfo.longitude,
|
||||
gnssInfo.latitude,
|
||||
heading,
|
||||
@@ -70,37 +215,54 @@ object BusStationEventManager : IMoGoChassisLocationWGS84Listener {
|
||||
newPoint?.also {
|
||||
farthestLocationList.add(LonLatPoint(it.first, it.second))
|
||||
}
|
||||
if (DebugConfig.isDebug()) {
|
||||
farthestLocationList.last().also {
|
||||
showHDMarker(it.longitude, it.latitude)
|
||||
}
|
||||
}
|
||||
}
|
||||
MogoData.mogoMapData.get()?.also { iMogoData ->
|
||||
val busStationList = iMogoData.getBusStation(farthestLocationList)
|
||||
val filteredBusStationList = busStationList.filter {
|
||||
it.busStationPoints.isNotEmpty() &&
|
||||
DrivingDirectionUtils.getDegreeOfCar2Poi(
|
||||
gnssInfo.longitude,
|
||||
gnssInfo.latitude,
|
||||
it.getBusStationPoint().longitude,
|
||||
it.getBusStationPoint().latitude,
|
||||
gnssInfo.heading.toInt()
|
||||
) < 90 && CoordinateUtils.calculateLineDistance(
|
||||
gnssInfo.longitude,
|
||||
gnssInfo.latitude,
|
||||
it.getBusStationPoint().longitude,
|
||||
it.getBusStationPoint().latitude,
|
||||
) <= (segmentSum * metersPreSegment)
|
||||
}
|
||||
Logger.d(
|
||||
TAG,
|
||||
"calculateNearByStation --> 查询出附近公交站点 ${busStationList.size} 个"
|
||||
"calculateNearByStation --> 本次查询出:${busStationList.size}个,本次符合条件:${filteredBusStationList.size}个,当前待提醒:${busStationListNeedNotified.size}个"
|
||||
)
|
||||
busStationList.forEach {
|
||||
busStationListNearBy[it.getBusStationId()] = it
|
||||
synchronized(busStationNearByQueue) {
|
||||
busStationNearByQueue.clear()
|
||||
busStationNearByQueue.add(busStationList)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据当前经纬度和方向,计算距离 distance 米处的坐标
|
||||
*/
|
||||
private fun calculateNewPoint(
|
||||
x: Double,
|
||||
y: Double,
|
||||
angle: Double,
|
||||
distance: Double
|
||||
): Pair<Double, Double>? {
|
||||
if (distance == 0.0) {
|
||||
return null
|
||||
}
|
||||
val radian = Math.toRadians(angle)
|
||||
val radianCandle = Math.toRadians(angle)
|
||||
val nX = x + distance * sin(radian) / 100000.0
|
||||
val nY = y + distance * sin(radianCandle) / 100000.0
|
||||
return Pair.create(nX, nY)
|
||||
private fun showHDMarker(lon: Double, lat: Double) {
|
||||
val builder = Point.Options.Builder(
|
||||
"TYPE_MARKER_BUS_STATION", Level.MAP_MARKER
|
||||
).setId(UUID.randomUUID().toString()).anchor(0.2f, 0.2f)
|
||||
.set3DMode(true)
|
||||
.isUseGps(true)
|
||||
.controlAngle(true)
|
||||
.icon3DRes(EventTypeEnumNew.getMarker3DRes(EventTypeEnumNew.TYPE_SOCKET_ROAD_SHIGONG.poiType))
|
||||
.longitude(lon)
|
||||
.latitude(lat)
|
||||
val overlayManager = CallerMapUIServiceManager.getOverlayManager()
|
||||
overlayManager?.removeAllPointsInOwner("TYPE_MARKER_BUS_STATION")
|
||||
overlayManager?.showOrUpdatePoint(builder.build())
|
||||
}
|
||||
|
||||
}
|
||||
@@ -33,7 +33,6 @@ import kotlinx.android.synthetic.main.hmi_view_road_v2n_event_window.view.tvV2XT
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import me.jessyan.autosize.utils.AutoSizeUtils
|
||||
import java.util.UUID
|
||||
|
||||
/**
|
||||
* 路侧V2N事件通用弹框
|
||||
@@ -248,32 +247,6 @@ class RoadV2NEventWindowView @JvmOverloads constructor(
|
||||
super.onAttachedToWindow()
|
||||
CallerRoadV2NEventWindowListenerManager.addListener(TAG, this)
|
||||
initView()
|
||||
//TODO
|
||||
val eventId = UUID.randomUUID().toString()
|
||||
CallerRoadV2NEventWindowListenerManager.show(
|
||||
eventId,
|
||||
System.currentTimeMillis(),
|
||||
R.drawable.v2x_icon_shigong_zhandao,
|
||||
"前方 200米 道路积水",
|
||||
true,
|
||||
"172.168.1.20",
|
||||
0.0,
|
||||
0.0
|
||||
)
|
||||
UiThreadHandler.postDelayed({
|
||||
CallerRoadV2NEventWindowListenerManager.dismiss(eventId)
|
||||
|
||||
val eventId1 = CallerRoadV2NEventWindowListenerManager.show(
|
||||
UUID.randomUUID().toString(),
|
||||
System.currentTimeMillis(),
|
||||
R.drawable.v2x_icon_jiaotongshigu_vr,
|
||||
"前方 300米 发生交通事故",
|
||||
true,
|
||||
"172.168.1.20",
|
||||
0.0,
|
||||
0.0
|
||||
)
|
||||
}, 20 * 1000L)
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
|
||||
Reference in New Issue
Block a user