From 850fa814bc7fa144b6ca0d6add0c3360d542b1e3 Mon Sep 17 00:00:00 2001 From: renwj Date: Fri, 23 Sep 2022 19:57:58 +0800 Subject: [PATCH] =?UTF-8?q?[V2X][Road]=E6=96=BD=E5=B7=A5=E5=8D=A0=E9=81=93?= =?UTF-8?q?=E4=BA=8B=E4=BB=B6=E8=A7=A6=E5=8F=91=E5=90=8E=EF=BC=8C=E6=A0=87?= =?UTF-8?q?=E8=AE=B0=E9=81=93=E8=B7=AF=E9=A2=9C=E8=89=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../function/v2x/events/V2XEventManager.kt | 7 +- .../scenario/scene/airoad/AiRoadMarker.kt | 324 ++++++++++++++++++ .../scene/road/V2XRoadEventMarker.java | 28 -- gradle.properties | 2 +- .../src/main/java/com/mogo/map/IMogoMap.java | 13 +- .../java/com/mogo/map/center/CenterLine.kt | 13 + .../main/java/com/mogo/map/AMapWrapper.java | 25 ++ .../common/utils/DrivingDirectionUtils.java | 2 +- 8 files changed, 382 insertions(+), 32 deletions(-) create mode 100644 core/function-impl/mogo-core-function-v2x/src/main/java/com/mogo/eagle/core/function/v2x/events/scenario/scene/airoad/AiRoadMarker.kt create mode 100644 libraries/mogo-map-api/src/main/java/com/mogo/map/center/CenterLine.kt diff --git a/core/function-impl/mogo-core-function-v2x/src/main/java/com/mogo/eagle/core/function/v2x/events/V2XEventManager.kt b/core/function-impl/mogo-core-function-v2x/src/main/java/com/mogo/eagle/core/function/v2x/events/V2XEventManager.kt index 7d436e2693..743505cf51 100644 --- a/core/function-impl/mogo-core-function-v2x/src/main/java/com/mogo/eagle/core/function/v2x/events/V2XEventManager.kt +++ b/core/function-impl/mogo-core-function-v2x/src/main/java/com/mogo/eagle/core/function/v2x/events/V2XEventManager.kt @@ -45,6 +45,8 @@ import com.mogo.eagle.core.function.v2x.events.network.V2XRefreshCallback import com.mogo.eagle.core.function.v2x.events.observer.V2XOptimalRouteObserver import com.mogo.eagle.core.function.v2x.events.receiver.SceneBroadcastReceiver import com.mogo.eagle.core.function.v2x.events.scenario.impl.V2XScenarioManager +import com.mogo.eagle.core.function.v2x.events.scenario.scene.airoad.* +import com.mogo.eagle.core.function.v2x.events.scenario.scene.airoad.AiRoadMarker.Marker import com.mogo.eagle.core.function.v2x.events.utils.* import com.mogo.eagle.core.function.v2x.events.voice.V2XVoiceManager import com.mogo.eagle.core.network.utils.GsonUtil @@ -62,7 +64,6 @@ import com.mogo.module.common.drawer.TrafficMarkerDrawer import com.mogo.module.common.entity.* import com.mogo.module.common.entity.V2XMessageEntity.V2XTypeEnum import com.mogo.module.common.enums.EventTypeEnum -import com.mogo.module.common.enums.EventTypeEnum.FOURS_BLOCK_UP import com.mogo.module.common.enums.EventTypeHelper import com.mogo.service.statusmanager.IMogoStatusChangedListener import com.mogo.service.statusmanager.StatusDescriptor @@ -108,6 +109,7 @@ object V2XEventManager : IMoGoMapLocationListener, IMoGoTokenCallback, IV2XCallb BridgeApi.init(context) if (hasInit.compareAndSet(false, true)) { if (!V2XManager.hasInit()) { + AiRoadMarker.init(context) V2XManager.init(V2XConfig.Builder().also { it.aiCloudConfig(MoGoAiCloudClientConfig.getInstance()) it.context(context) @@ -483,6 +485,9 @@ object V2XEventManager : IMoGoMapLocationListener, IMoGoTokenCallback, IV2XCallb val p = CoordinateUtils.transformWgsToGcj(this.roadwork?.center?.point?.lat ?: 0.0, this.roadwork?.center?.point?.lon ?: 0.0) l4.lon = p[0] l4.lat = p[1] + AiRoadMarker.enqueue(Marker(this.roadwork?.center?.point?.lat ?: 0.0, this.roadwork?.center?.point?.lon ?: 0.0, this.roadwork?.polygonList?.takeIf { it.isNotEmpty() }?.map { d -> + android.util.Pair(d.lon, d.lat) + })) l4.angle = this.roadwork?.center?.road?.bearing?.toDouble() ?: 0.0 } }) diff --git a/core/function-impl/mogo-core-function-v2x/src/main/java/com/mogo/eagle/core/function/v2x/events/scenario/scene/airoad/AiRoadMarker.kt b/core/function-impl/mogo-core-function-v2x/src/main/java/com/mogo/eagle/core/function/v2x/events/scenario/scene/airoad/AiRoadMarker.kt new file mode 100644 index 0000000000..411ab19fa7 --- /dev/null +++ b/core/function-impl/mogo-core-function-v2x/src/main/java/com/mogo/eagle/core/function/v2x/events/scenario/scene/airoad/AiRoadMarker.kt @@ -0,0 +1,324 @@ +package com.mogo.eagle.core.function.v2x.events.scenario.scene.airoad + +import android.content.* +import android.graphics.* +import android.util.* +import androidx.lifecycle.* +import androidx.lifecycle.Lifecycle.Event +import androidx.lifecycle.Lifecycle.Event.ON_CREATE +import androidx.lifecycle.Lifecycle.Event.ON_DESTROY +import com.mogo.cloud.commons.utils.* +import com.mogo.eagle.core.data.map.* +import com.mogo.eagle.core.data.map.MapRoadInfo.StopLine +import com.mogo.eagle.core.function.api.map.listener.* +import com.mogo.eagle.core.function.call.map.* +import com.mogo.eagle.core.function.call.map.CallerMapRoadListenerManager.OnRoadListener +import com.mogo.eagle.core.utilcode.kotlin.* +import com.mogo.eagle.core.utilcode.mogo.logger.* +import com.mogo.map.* +import com.mogo.map.overlay.* +import com.mogo.module.common.utils.* +import io.netty.util.internal.* +import java.util.* +import java.util.concurrent.* +import java.util.concurrent.atomic.* + +/** + * Ai云道路施工事件,道路颜色标记类 + */ +object AiRoadMarker { + + private const val TAG = "AiRoadMarker" + + private val queue by lazy { LinkedBlockingQueue() } + + private val pool by lazy { Executors.newFixedThreadPool(2) } + + private val marker by lazy { AtomicReference() } + + private val curStopLine by lazy { AtomicReference() } + + private val lastStopLine by lazy { AtomicReference() } + + private val carLocation by lazy { AtomicReference>() } + + private val overlayManager by lazy { MogoOverlayManager.getInstance() } + + private val redLine by lazy { AtomicReference() } + + private val redLineColors = arrayListOf(Color.parseColor("#002ABAD9"), Color.parseColor("#FF7A30")) + +// private val blueLine by lazy { AtomicReference() } +// +// private val blueLineColors = arrayListOf(Color.parseColor("#002ABAD9"), Color.parseColor("#30A3FF")) + + private val markerCache = ConcurrentSet() + + private val redLineOptions by lazy { + MogoPolylineOptions().apply { + zIndex(40000f) + setGps(true) + width(30f) + useGradient(true) + colorValues(redLineColors) + } + } + +// private val blueLineOptions by lazy { +// MogoPolylineOptions().apply { +// zIndex(30000f) +// setGps(true) +// width(40f) +// useGradient(true) +// colorValues(blueLineColors) +// } +// } + + fun init(ctx: Context) { + ctx.lifeCycleOwner.lifecycle.addObserver(object : LifecycleEventObserver { + override fun onStateChanged(source: LifecycleOwner, event: Event) { + if (event == ON_CREATE) { + onCreate() + } + if (event == ON_DESTROY) { + onDestroy() + } + } + }) + + pool.execute { + var interrupted = false + Logger.d(TAG, "--- consumer --- 0 ---") + while (!interrupted) { + try { + Logger.d(TAG, "--- consumer --- 1 ---") + val top = queue.take() ?: continue + Logger.d(TAG, "--- consumer --- 2 ---") + val location = carLocation.get() ?: continue + val isFrontOfCar = isFrontOfCar(top.poi_lon, top.poi_lat, location.first, location.second, location.third) + val isSameRoad = isSameRoad(top.poi_lon, top.poi_lat, location.first, location.second, location.third) + Logger.d(TAG, "--- consumer --- 3 ---isFrontOfCar: $isFrontOfCar, isSameRoad: $isSameRoad") + if (isFrontOfCar && isSameRoad) { + marker.set(top) + marker(top) + } else { + markerCache.remove(top) + } + interrupted = Thread.currentThread().isInterrupted + } catch (e: InterruptedException) { + e.printStackTrace() + break + } + } + } + } + + private fun isSameRoad(x1: Double, y1: Double, x2: Double, y2: Double, angle: Double): Boolean { + val c1 = MogoMap.getInstance().mogoMap.getCenterLineRangeInfo(x1, y1, angle.toFloat(), 10f) + val c2 = MogoMap.getInstance().mogoMap.getCenterLineRangeInfo(x2, y2, angle.toFloat(), 10f) + Logger.d(TAG, "isSameRoad--: $c1 ==> $c2") + return c1 != null && c2 != null && c1.road_id.isNotEmpty() && c1.road_id == c2.road_id + } + + private val onRoadListener = object : OnRoadListener { + private var roadId = "" + private var hasCrossRoad = false + + override fun onRoadIdInfo(roadId: String) { + Logger.d(TAG, "--- onRoadInfo --- roadId: $roadId") + val oldRoadId = this.roadId + if (oldRoadId != roadId) { + if (hasCrossRoad) { + hasCrossRoad = false + lastStopLine.set(curStopLine.get()) + } + } + this.roadId = roadId + } + override fun onStopLineInfo(info: StopLine) { + Logger.d(TAG, "--- onStopLineInfo --- info: $info") + curStopLine.set(info) + if (!hasCrossRoad) { + hasCrossRoad = true + } + } + } + + private val onLocationListener = object : IMoGoMapLocationListener { + + + override fun onLocationChanged(location: MogoLocation?, from: Int) { + if (location == null) { + return + } + try { + val loc = CoordinateUtils.transformGcj02toWgs84(location.latitude, location.longitude) + Logger.d(TAG, "x:${loc[0]}, y:${loc[1]}, angle: ${location.bearing}") + carLocation.set(Triple(loc[0], loc[1], location.bearing.toDouble())) + val marker = marker.get() ?: return + val isOutOfRange = isOutOfRange(marker.poi_lon, marker.poi_lat, carLocation.get().first, carLocation.get().second, carLocation.get().third) + Logger.d(TAG, "--- onLocationChanged: isOutOfRange: $isOutOfRange") + if (isOutOfRange) { + unMarker(marker) + } + } catch (t: Throwable) { + Logger.e(TAG, "error: ${t.message}") + } + } + } +// +// private fun drawBlueLine(points: List>, location: MogoLocation) { +// val line = blueLine.get() +// blueLineOptions.points(points.filter { +// DrivingDirectionUtils.getDegreeOfCar2Poi2(location.longitude, location.latitude, it.first, it.second, location.bearing.toDouble()) < 90L +// }.map { +// MogoLatLng(it.second, it.first) +// }) +// if (line == null || line.isDestroyed) { +// overlayManager.addPolyline(blueLineOptions) +// } else { +// line.setOption(blueLineOptions) +// } +// } + + private fun onCreate() { + CallerMapRoadListenerManager.registerRoadListener(TAG, onRoadListener) + CallerMapLocationListenerManager.addListener(TAG, onLocationListener) + } + + private fun onDestroy() { + CallerMapRoadListenerManager.unRegisterRoadListener(TAG) + CallerMapLocationListenerManager.removeListener(TAG) + pool.shutdownNow() + } + + + fun enqueue(marker: Marker) { + Logger.d(TAG, "--- enqueue --- 1 ---") + if (markerCache.contains(marker)) { + Logger.d(TAG, "--- enqueue --- cache hit ---") + return + } + Logger.d(TAG, "--- enqueue --- 2 ---") + markerCache += marker + pool.execute { + Logger.d(TAG, "--- enqueue --- 3 ---${Thread.currentThread().name}::${Thread.currentThread().id}") + queue.put(marker) + } + } + + private fun marker(marker: Marker) { + Logger.d(TAG, "--- marker --- 1 ---") + val location = carLocation.get() ?: return + Logger.d(TAG, "--- marker --- 2 ---") + removeRedLine() + //施工中心点前方的自车行驶方向上300米距离 + val l1 = MogoMap.getInstance().mogoMap.getCenterLineRangeInfo(marker.poi_lon, marker.poi_lat, location.third.toFloat(), 300f) + //施工中心点后方的自车行驶方向上300米距离 + Logger.d(TAG, "--- marker --- 3 --- l1: $l1") + val l2 = MogoMap.getInstance().mogoMap.getCenterLineRangeInfo(marker.poi_lon, marker.poi_lat, location.third.toFloat(), -300f) + Logger.d(TAG, "--- marker --- 4 --- l2: $l2") + val points = LinkedList() + if (l2 != null && l2.points.isNotEmpty()) { + points.addAll(l2.points.map { + MogoLatLng(it.second, it.first) + }) + } + val centerX= marker.poi_lon + val centerY = marker.poi_lat + Logger.d(TAG, "--- marker --- 5 --- marker: $marker") + val farthestPoint = marker.polygon?.let { + var find: Pair = Pair(centerX, centerY) + var min = Long.MAX_VALUE + for (p in it) { + val angle = DrivingDirectionUtils.getDegreeOfCar2Poi2(centerX, centerY, p.first, p.second, location.third) + if (angle < min) { + min = angle + find = p + } + } + MogoLatLng(find.second, find.second) + } ?: MogoLatLng(centerY, centerX) + marker.farthestPoint = Pair(farthestPoint.lon, farthestPoint.lat) + Logger.d(TAG, "--- marker --- 6 --- marker: $marker") + if (l1 != null && l1.points.isNotEmpty()) { + for (l in l1.points) { + if (DrivingDirectionUtils.getDegreeOfCar2Poi2(farthestPoint.lon, farthestPoint.lat, l.first, l.second, location.third) < 90L) { + points.add(l.let { MogoLatLng(it.second, it.first) }) + } + } + } + var line = redLine.get() + redLineOptions.points(points) + Logger.d(TAG, "--- marker --- 7 --- points: ${points.size}") + if (line == null || line.isDestroyed) { + val l = overlayManager.addPolyline(redLineOptions) + this.redLine.set(l) + line = l + } else { + line.setOption(redLineOptions) + } + if (!line.isVisible) { + line.isVisible = true + } + } + + private fun removeRedLine() { + val old = redLine.get() + Logger.d(TAG, "--- removeRedLine --- 1 ---") + if (old != null) { + Logger.d(TAG, "--- removeRedLine --- 2 ---") + redLine.set(null) + old.isVisible = false + old.remove() + } + } + +// private fun removeBlueLine() { +// val old = blueLine.get() +// Logger.d(TAG, "--- removeBlueLine --- 1 ---") +// if (old != null) { +// Logger.d(TAG, "--- removeBlueLine --- 2 ---") +// blueLine.set(null) +// old.isVisible = false +// old.remove() +// } +// } + + private fun unMarker(marker: Marker) { + markerCache -= marker + removeRedLine() + } + + private fun isOutOfRange(markerLon: Double, markerLat: Double, carLon: Double, carLat: Double, carAngle: Double): Boolean { + return !isFrontOfCar(markerLon, markerLat, carLon, carLat, carAngle) + } + + private fun isFrontOfCar(markerLon: Double, markerLat: Double, carLon: Double, carLat: Double, carAngle: Double): Boolean { + val degree = DrivingDirectionUtils.getDegreeOfCar2Poi2(carLon, carLat, markerLon, markerLat, carAngle) + return degree < 90 + } + + data class Marker( + val poi_lat: Double, + val poi_lon: Double, + val polygon: List>?, + var farthestPoint: Pair? = null + ) { + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + other as Marker + if (poi_lat != other.poi_lat) return false + if (poi_lon != other.poi_lon) return false + return true + } + + override fun hashCode(): Int { + var result = poi_lat.hashCode() + result = 31 * result + poi_lon.hashCode() + return result + } + } +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-v2x/src/main/java/com/mogo/eagle/core/function/v2x/events/scenario/scene/road/V2XRoadEventMarker.java b/core/function-impl/mogo-core-function-v2x/src/main/java/com/mogo/eagle/core/function/v2x/events/scenario/scene/road/V2XRoadEventMarker.java index b2ea3362a4..e389c02ea2 100644 --- a/core/function-impl/mogo-core-function-v2x/src/main/java/com/mogo/eagle/core/function/v2x/events/scenario/scene/road/V2XRoadEventMarker.java +++ b/core/function-impl/mogo-core-function-v2x/src/main/java/com/mogo/eagle/core/function/v2x/events/scenario/scene/road/V2XRoadEventMarker.java @@ -91,34 +91,6 @@ public class V2XRoadEventMarker implements IV2XMarker { t.printStackTrace(); } } - -// if (polygons.size() > 1) { -// if (overlayManager == null) { -// overlayManager = MogoOverlayManager.getInstance(); -// } -// MogoPolylineOptions options = new MogoPolylineOptions(); -// List colors = new ArrayList<>(); -// colors.add(Color.argb(204, 237, 172, 21)); -// colors.add(Color.argb(0, 255, 255, 255)); -// options.colorValues(colors); -// List points = new ArrayList<>(); -// for (int i = 0; i < polygons.size(); i++) { -// Pair p = polygons.get(i); -// points.add(new MogoLatLng(p.second, p.first)); -// } -// if (points.size() > 2) { -// points.add(points.get(0)); -// } -// options.points(points); -// options.useGradient(true); -// options.useFacade(true); -// options.setGps(false); -// options.width(5f); -// options.zIndex(75000f); -// options.maxIndex(800000f); -// polyline = overlayManager.addPolyline(options); -// polyline.setVisible(true); -// } } } } diff --git a/gradle.properties b/gradle.properties index e160b93985..5fddde6d6b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -85,7 +85,7 @@ MOGO_LOCATION_VERSION=1.4.3.26 MOGO_TELEMATIC_VERSION=1.4.3.26 ######## MogoAiCloudSDK Version ######## # 自研地图 -MAP_SDK_VERSION=2.4.2.3 +MAP_SDK_VERSION=2.5.1.9 MAP_SDK_OPERATION_VERSION=1.1.2.4 # websocket WEBSOCKET_VERSION=1.1.7 diff --git a/libraries/mogo-map-api/src/main/java/com/mogo/map/IMogoMap.java b/libraries/mogo-map-api/src/main/java/com/mogo/map/IMogoMap.java index 435d2a5fe7..e549b410a1 100644 --- a/libraries/mogo-map-api/src/main/java/com/mogo/map/IMogoMap.java +++ b/libraries/mogo-map-api/src/main/java/com/mogo/map/IMogoMap.java @@ -1,5 +1,6 @@ package com.mogo.map; +import com.mogo.map.center.CenterLine; import com.mogo.map.marker.IMogoMarker; import com.mogo.map.marker.MogoMarkerOptions; import com.mogo.map.overlay.IMogoPolyline; @@ -170,8 +171,18 @@ public interface IMogoMap { IMogoPolyline addPolyline( MogoPolylineOptions options ); /** - * 获取地图版本号 + * 获取地图版本 * @return */ String getMapVersion(); + + /** + * 获取行驶方向一定长度的中心线 + * @param lon 经度 + * @param lat 纬度 + * @param angle 航向角 + * @param distance 获取车道中心线的长度,> 0: 行驶方向前方距离, <0 行驶方向后方距离 + * @return 中心线相关数据 + */ + CenterLine getCenterLineRangeInfo(double lon, double lat, float angle, float distance); } diff --git a/libraries/mogo-map-api/src/main/java/com/mogo/map/center/CenterLine.kt b/libraries/mogo-map-api/src/main/java/com/mogo/map/center/CenterLine.kt new file mode 100644 index 0000000000..d17ed547ab --- /dev/null +++ b/libraries/mogo-map-api/src/main/java/com/mogo/map/center/CenterLine.kt @@ -0,0 +1,13 @@ +package com.mogo.map.center + +import android.util.Pair + +data class CenterLine( + + var id: String = "", //id + var tile_id: String = "", //瓦片id + var road_id: String = "", //道路id + var lane_id: String = "", //车道id + var points: List> = emptyList(), + var angle: Double = 0.0 +) diff --git a/libraries/mogo-map/src/main/java/com/mogo/map/AMapWrapper.java b/libraries/mogo-map/src/main/java/com/mogo/map/AMapWrapper.java index 135de98e90..6c490ccaa7 100644 --- a/libraries/mogo-map/src/main/java/com/mogo/map/AMapWrapper.java +++ b/libraries/mogo-map/src/main/java/com/mogo/map/AMapWrapper.java @@ -3,9 +3,12 @@ package com.mogo.map; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Point; +import android.util.Log; +import android.util.Pair; import com.mogo.eagle.core.data.config.FunctionBuildConfig; import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; +import com.mogo.map.center.CenterLine; import com.mogo.map.marker.AMapInfoWindowAdapter; import com.mogo.map.marker.AMapMarkerWrapper; import com.mogo.map.marker.IMogoMarker; @@ -33,6 +36,7 @@ import com.zhidaoauto.map.sdk.open.view.MapAutoView; import com.zhidaoauto.map.sdk.open.view.MapAutoViewHelper; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -319,6 +323,27 @@ public class AMapWrapper implements IMogoMap { return singlePointRoadInfo != null ? singlePointRoadInfo.getLaneWidth() : 0; } + @Override + public CenterLine getCenterLineRangeInfo(double lon, double lat, float angle, float distance) { + com.zhidaoauto.map.sdk.open.road.CenterLine info = MapDataApi.INSTANCE.getCenterLineRangeInfo(lon, lat, angle, distance); + CenterLine ret = null; + if (info != null) { + ret = new CenterLine(info.id, info.tile_id, info.road_id, info.lane_id, convert(info.points), info.angle == null ? 0f : info.angle); + } + return ret; + } + + private List> convert(List points) { + if (points == null || points.isEmpty()) { + return Collections.emptyList(); + } + List> ret = new ArrayList<>(points.size()); + for (LonLatPoint p : points) { + ret.add(Pair.create(p.longitude, p.latitude)); + } + return ret; + } + private Context getContext() { return mMapView.getContext(); } diff --git a/modules/mogo-module-common/src/main/java/com/mogo/module/common/utils/DrivingDirectionUtils.java b/modules/mogo-module-common/src/main/java/com/mogo/module/common/utils/DrivingDirectionUtils.java index 0adacdbbc7..bf5d562033 100644 --- a/modules/mogo-module-common/src/main/java/com/mogo/module/common/utils/DrivingDirectionUtils.java +++ b/modules/mogo-module-common/src/main/java/com/mogo/module/common/utils/DrivingDirectionUtils.java @@ -26,7 +26,7 @@ public class DrivingDirectionUtils { return Math.sqrt(Math.pow(x1 - x2, 2.0) + Math.pow(y1 - y2, 2.0)); } - private static double getAngle(double sx, double sy, double x1, double y1, double x2, double y2) { + public static double getAngle(double sx, double sy, double x1, double y1, double x2, double y2) { x1 = x1 - sx; y1 = y1 - sy; x2 = x2 - sx;