Merge branch 'dev_minibus-d_230425_3.2.0' into code_opt_3.3.0

# Conflicts:
#	core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/config/CloudPoiManager.java
This commit is contained in:
donghongyu
2023-06-05 16:15:36 +08:00
31 changed files with 368 additions and 491 deletions

View File

@@ -49,7 +49,7 @@ class V2XMarkerRoadEventView(context: Context, alarmInfo: V2XRoadEventEntity) :
* @see EventTypeEnumNew
*/
private fun updateIcon(alarmInfo: V2XRoadEventEntity) {
// 道路施工、积水、路面结冰、浓雾、事故、拥堵
// 道路施工、积水、路面结冰、事故、拥堵
val iconResId = EventTypeEnumNew.getUpdateIconRes(alarmInfo.poiType)
if (iconResId != 0) {
ivCar.setImageResource(iconResId)

View File

@@ -2,18 +2,17 @@ package com.mogo.eagle.core.function.hmi.ui.widget
import android.app.Application
import android.content.Context
import android.os.Handler
import android.util.AttributeSet
import android.view.LayoutInflater
import com.mogo.cloud.live.manager.LiveStreamManagerImpl
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
import com.mogo.cloud.trafficlive.api.ITrafficCarLiveCallBack
import com.mogo.cloud.trafficlive.api.MoGoAiCloudTrafficLive
import com.mogo.eagle.core.function.call.telematic.CallerTelematicManager
import com.mogo.eagle.core.function.hmi.R
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.Logger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.mogo.eagle.core.widget.RoundConstraintLayout
import kotlinx.android.synthetic.main.view_driver_monitor.view.ivNormal
import kotlinx.android.synthetic.main.view_driver_monitor.view.liveProgressBar
@@ -27,37 +26,19 @@ class DriverMonitorView :
RoundConstraintLayout {
companion object {
private val TAG = "DriverMonitorView"
private var isLived = false
// TODO SOP演示功能代码乘客端查看当前车辆上的司机位置监控请求的是分体机提供的直播信息这里采用的是硬编码因为云平台的操作就是这样没有接口供查询对应关系
private var sopShowDriverMap = HashMap<String, String>()
}
private val mHandler = Handler()
private val mRunnable = object : Runnable {
override fun run() {
// Do something here
Logger.d(
"${SceneConstant.M_HMI}$TAG",
"检查司机直播……isLived=$isLived 当前车上的司机端SN=${sopShowDriverMap[CallerTelematicManager.getServerToken()]}"
)
CallerLogger.d(
"${SceneConstant.M_HMI}$TAG",
"检查司机直播……isLived=$isLived 当前车上的司机端SN=${sopShowDriverMap[CallerTelematicManager.getServerToken()]}"
)
showLive()
// TODO SOP演示功能代码乘客端查看当前车辆上的司机位置监控请求的是分体机提供的直播信息这里采用的是硬编码因为云平台的操作就是这样没有接口供查询对应关系
private var sopShowDriverMap = HashMap<String, String>()
private var isLived = false
mHandler.postDelayed(this, 10000) // 1 second delay
}
}
// 调用直播传入的司机屏幕SN
private var currentDriverSN = ""
// 当前直播源的SN,TODO 如果要测试可以使用下面的SN
// private var currentDriverLiveSN = "F803EB2046PZD00164"
private var currentDriverLiveSN = ""
private val liveStreamManager by lazy {
LiveStreamManagerImpl.getInstance(
context.applicationContext as Application?,
MoGoAiCloudClientConfig.getInstance().sn,
false
)
}
var liveListener: LiveListener? = null
@@ -83,10 +64,11 @@ class DriverMonitorView :
textureViewDriverMonitor.isOpaque = false
liveStreamManager.setLivePushStatusChangeCallback { }
// TODO SOP演示需求只有乘客屏幕才会触发这个逻辑 begin
// TODO SOP演示需求只有乘客屏幕才会触发这个逻辑 ,车上必须配置了分体机作为直播源 begin
// http://wiki.zhidaohulian.com/pages/viewpage.action?pageId=111386656
// 测试数据
sopShowDriverMap["F803EB2046PZD00164"] = "F803EB2046PZD00164"//凤坤工位旁的分体机
sopShowDriverMap["X20202105189C2522114198E7B3"] = "F803EB2046PZD00164"//凤坤工位旁的分体机
sopShowDriverMap["X202022060289M7N8P"] = "F803EB2046PZD00188"//湘A01733D
// key=pad司机屏幕SNvalue=分体机SNvalue用来调用ZeGo直播服务查看直播@see MoGoAiCloudTrafficLive.viewDesignativeVehicleLive
sopShowDriverMap["20220524733SWT1"] = "F803EB2046PZD00190"//湘D01777D
@@ -98,61 +80,99 @@ class DriverMonitorView :
// TODO SOP演示需求只有乘客屏幕才会触发这个逻辑 END
// 点击重新连接直播
ivNormal.setOnClickListener {
showLive()
startLive()
}
mHandler.postDelayed(mRunnable, 1000) // 1 second delay
}
fun isSOPDriverSn(sn: String) :Boolean{
return sopShowDriverMap.containsKey(sn)
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
mHandler.removeCallbacks(mRunnable)
sopShowDriverMap[CallerTelematicManager.getServerToken()]?.let {
MoGoAiCloudTrafficLive.stopCarLive(it)
if (currentDriverLiveSN.isNotEmpty()) {
MoGoAiCloudTrafficLive.stopCarLive(currentDriverLiveSN)
}
}
fun showLive() {
if (!isLived) {
sopShowDriverMap[CallerTelematicManager.getServerToken()]?.let {
Logger.d(
"${SceneConstant.M_HMI}$TAG",
"检查司机直播……isLived=$isLived 当前车上的司机端SN=${sopShowDriverMap[CallerTelematicManager.getServerToken()]}"
)
CallerLogger.d(
"${SceneConstant.M_HMI}$TAG",
"检查司机直播……isLived=$isLived 当前车上的司机端SN=${sopShowDriverMap[CallerTelematicManager.getServerToken()]}"
)
/**
* 检查传入的司机端所在车辆是否配置了F车机作为直播源。ture-有false-没有
*/
fun isSOPDriverSn(snDriver: String): Boolean {
currentDriverSN = snDriver
// 查找传入的司机端所在车是否配置了F车机作为直播源
sopShowDriverMap[snDriver]?.let {
// 这里应对的是乘客端切换连接的司机端的情况,正常情况这里不会执行,一个车只有一个司机端
if (isLived && it != currentDriverLiveSN) {
stopLive()
}
currentDriverLiveSN = it
// 这里知只是了初始化下直播SDK防止直接调用观看直播时候还未登录问题
LiveStreamManagerImpl.getInstance(
context.applicationContext as Application?,
MoGoAiCloudClientConfig.getInstance().sn,
false
)
} ?: let {
// 如果没查到设置当前车辆为null并将之前的直播关闭
stopLive()
currentDriverLiveSN = ""
}
Logger.d(
"${SceneConstant.M_HMI}$TAG",
"当前车上的司机端SN=${currentDriverSN},直播分体机SN=${currentDriverLiveSN}"
)
CallerLogger.d(
"${SceneConstant.M_HMI}$TAG",
"当前车上的司机端SN=${currentDriverSN},直播分体机SN=${currentDriverLiveSN}"
)
return currentDriverLiveSN.isNotEmpty()
}
/**
* 打开,司机仓监控直播
*/
fun startLive() {
if (currentDriverLiveSN.isNotEmpty()) {
Logger.d(
"${SceneConstant.M_HMI}$TAG",
"检查司机直播……isLived=$isLived 当前车上的司机端SN=${currentDriverSN},直播分体机SN=${currentDriverLiveSN}"
)
CallerLogger.d(
"${SceneConstant.M_HMI}$TAG",
"检查司机直播……isLived=$isLived 当前车上的司机端SN=${currentDriverSN},直播分体机SN=${currentDriverLiveSN}"
)
if (!isLived) {
MoGoAiCloudTrafficLive.viewDesignativeVehicleLive(
it,
currentDriverLiveSN,
textureViewDriverMonitor,
carLiveCallBack
)
} ?: let {
//为空又怎么撸
if (CallerTelematicManager.getServerToken().isNotEmpty()) {
Logger.d(
"${SceneConstant.M_HMI}$TAG",
"检查司机直播……isLived=$isLived 当前车辆SN=${CallerTelematicManager.getServerToken()} 不支持直播"
)
CallerLogger.d(
"${SceneConstant.M_HMI}$TAG",
"检查司机直播……isLived=$isLived 当前车辆SN=${CallerTelematicManager.getServerToken()} 不支持直播"
)
// 乘客屏幕连接上了司机屏,但是司机屏不在直播范围内,进行隐藏操作。
liveListener?.onPlayError()
}
} else {
ToastUtils.showShort("正在直播中")
}
// TODO 测试用的
// MoGoAiCloudTrafficLive.viewDesignativeVehicleLive(
// "F803EB2046PZD00164",
// textureViewDriverMonitor,
// carLiveCallBack
// )
} else {
ToastUtils.showShort("当前车内没有直播源")
//为空又怎么撸
Logger.d(
"${SceneConstant.M_HMI}$TAG",
"检查司机直播……isLived=$isLived 当前车辆SN=${currentDriverSN} 不支持直播"
)
CallerLogger.d(
"${SceneConstant.M_HMI}$TAG",
"检查司机直播……isLived=$isLived 当前车辆SN=${currentDriverSN} 不支持直播"
)
// 乘客屏幕连接上了司机屏,但是司机屏不在直播范围内,进行隐藏操作。
liveListener?.onPlayError()
}
}
/**
* 关闭,司机仓监控直播
*/
fun stopLive() {
isLived = false
if (currentDriverLiveSN.isNotEmpty()) {
MoGoAiCloudTrafficLive.stopCarLive(currentDriverLiveSN)
}
}
@@ -170,20 +190,20 @@ class DriverMonitorView :
private val carLiveCallBack = object : ITrafficCarLiveCallBack {
override fun onLive(liveSn: String?) {
Logger.d("${SceneConstant.M_HMI}$TAG", "onLive:$liveSn")
Logger.i("${SceneConstant.M_HMI}$TAG", "onLive:$liveSn")
CallerLogger.d("${SceneConstant.M_HMI}$TAG", "onLive:$liveSn")
}
override fun onFirstFrame() {
Logger.d("${SceneConstant.M_HMI}$TAG", "onFirstFrame:isFirstPage")
Logger.i("${SceneConstant.M_HMI}$TAG", "onFirstFrame:isFirstPage")
CallerLogger.d("${SceneConstant.M_HMI}$TAG", "onFirstFrame:isFirstPage")
isLived = true
refreshView(isLived)
}
override fun onDisConnect() {
Logger.e("${SceneConstant.M_HMI}$TAG", "onDisConnect")
CallerLogger.e("${SceneConstant.M_HMI}$TAG", "onDisConnect")
Logger.w("${SceneConstant.M_HMI}$TAG", "onDisConnect")
CallerLogger.w("${SceneConstant.M_HMI}$TAG", "onDisConnect")
isLived = false
refreshView(isLived)
}
@@ -196,14 +216,16 @@ class DriverMonitorView :
}
override fun onPlaying() {
Logger.e("${SceneConstant.M_HMI}$TAG", "onPlaying……")
Logger.i("${SceneConstant.M_HMI}$TAG", "onPlaying……")
CallerLogger.i("${SceneConstant.M_HMI}$TAG", "onPlaying……")
isLived = true
refreshView(isLived)
}
override fun onPlaRequesting() {
Logger.e("${SceneConstant.M_HMI}$TAG", "onPlaRequesting……")
isLived = true
Logger.w("${SceneConstant.M_HMI}$TAG", "onPlaRequesting……")
CallerLogger.w("${SceneConstant.M_HMI}$TAG", "onPlaRequesting……")
isLived = false
refreshView(isLived)
}
}

View File

@@ -1,95 +0,0 @@
package com.mogo.eagle.core.function.hmi.ui.widget
import android.animation.Animator
import android.animation.Animator.AnimatorListener
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import androidx.constraintlayout.widget.ConstraintLayout
import com.mogo.eagle.core.data.enums.EventTypeEnumNew
import com.mogo.eagle.core.data.enums.WarningDirectionEnum
import com.mogo.eagle.core.function.api.hmi.warning.IV2XEventListener
import com.mogo.eagle.core.function.call.v2x.CallerV2XWarningListenerManager
import com.mogo.eagle.core.function.hmi.R
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import kotlinx.android.synthetic.main.view_v2x_warning_fog.view.*
class V2XFogEventView(context: Context, attrs: AttributeSet) :
ConstraintLayout(context, attrs), IV2XEventListener {
companion object {
private const val TAG = "V2XFogEventView"
}
private val animatorSet = AnimatorSet()
init {
LayoutInflater.from(context).inflate(R.layout.view_v2x_warning_fog, this, true)
val animator1 = ObjectAnimator.ofFloat(iv_wu1, "alpha", 0f, 1f, 0f)
val animator2 = ObjectAnimator.ofFloat(iv_wu1, "translationX", -500f, 100f, 300f)
val animator3 = ObjectAnimator.ofFloat(iv_wu1, "scaleX", 1f, 1.5f, 2f)
val animator4 = ObjectAnimator.ofFloat(iv_wu1, "scaleY", 1f, 1.5f, 2f)
val animator5 = ObjectAnimator.ofFloat(iv_wu2, "alpha", 0f, 1f, 0f)
val animator6 = ObjectAnimator.ofFloat(iv_wu2, "translationX", 500f, -100f, -300f)
val animator7 = ObjectAnimator.ofFloat(iv_wu2, "scaleX", 1f, 1.5f, 2f)
val animator8 = ObjectAnimator.ofFloat(iv_wu2, "scaleY", 1f, 1.5f, 2f)
animatorSet.playTogether(
animator1,
animator2,
animator3,
animator4,
animator5,
animator6,
animator7,
animator8
)
animatorSet.duration = 5000
animatorSet.addListener(object : AnimatorListener{
override fun onAnimationStart(animation: Animator?) {
visibility = View.VISIBLE
}
override fun onAnimationEnd(animation: Animator?) {
visibility = View.GONE
}
override fun onAnimationCancel(animation: Animator?) {
visibility = View.GONE
}
override fun onAnimationRepeat(animation: Animator?) {
}
})
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
CallerV2XWarningListenerManager.addListener(TAG, this)
}
override fun show(v2xType: String, direction: WarningDirectionEnum, time: Long) {
ThreadUtils.runOnUiThread {
if(v2xType == EventTypeEnumNew.FOURS_FOG.poiType){
if (animatorSet.isStarted) {
return@runOnUiThread
}
animatorSet.start()
}
}
}
override fun dismiss(direction: WarningDirectionEnum) {
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
CallerV2XWarningListenerManager.removeListener(TAG)
}
}

View File

@@ -1,55 +0,0 @@
package com.mogo.eagle.core.function.main;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.res.Resources;
import android.util.DisplayMetrics;
import android.view.View;
import com.mogo.eagle.core.function.hmi.R;
/**
* created by wujifei on 2021/3/30 14:05
* describe:
*/
public class DisplayEffectsHelper {
private volatile static DisplayEffectsHelper instance = null;
private AnimatorSet animatorSet;
public static DisplayEffectsHelper getInstance() {
if (instance == null) {
synchronized (DisplayEffectsHelper.class) {
if (instance == null) {
instance = new DisplayEffectsHelper();
}
}
}
return instance;
}
public void init(View rootView) {
View view1 = rootView.findViewById(R.id.iv_wu1);
View view2 = rootView.findViewById(R.id.iv_wu2);
ObjectAnimator animator1 = ObjectAnimator.ofFloat(view1, "alpha", 0f, 1f, 0f);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(view1, "translationX", -500, 100f, 300f);
ObjectAnimator animator3 = ObjectAnimator.ofFloat(view1, "scaleX", 1f, 1.5f, 2f);
ObjectAnimator animator4 = ObjectAnimator.ofFloat(view1, "scaleY", 1f, 1.5f, 2f);
ObjectAnimator animator5 = ObjectAnimator.ofFloat(view2, "alpha", 0f, 1f, 0f);
ObjectAnimator animator6 = ObjectAnimator.ofFloat(view2, "translationX", 500, -100f, -300f);
ObjectAnimator animator7 = ObjectAnimator.ofFloat(view2, "scaleX", 1f, 1.5f, 2f);
ObjectAnimator animator8 = ObjectAnimator.ofFloat(view2, "scaleY", 1f, 1.5f, 2f);
animatorSet = new AnimatorSet();
animatorSet.playTogether(animator1, animator2, animator3, animator4, animator5, animator6, animator7, animator8);
animatorSet.setDuration(5000);
}
public void display() {
animatorSet.start();
}
private float dp2px(float dp) {
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
return dp * metrics.density;
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 784 KiB

View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone">
<ImageView
android:id="@+id/iv_wu1"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:alpha="0"
android:src="@drawable/wu1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/iv_wu2"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:alpha="0"
android:src="@drawable/wu2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintRight_toRightOf="parent"
tools:ignore="ContentDescription" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -86,12 +86,33 @@ object MarkerDrawerManager {
}
}
fun updateRoutePoints(routePoints: List<MessagePad.Location>?, context: Context) {
/**
* 存储全局轨迹用于轮询计算车已走过的轨迹index
*/
fun updateGDRoutePoints(routePoints: List<LatLng>?) {
if (routePoints == null || routePoints.isEmpty()) return
val latLngModels = coordinateConverterWgsToGcjListCommon(context, routePoints)
planningPoints.clear()
planningPoints.addAll(latLngModels)
// float remainingSumLength = calculateRemainingSumLength(mRoutePoints);
synchronized(this) {
planningPoints.clear()
planningPoints.addAll(routePoints)
}
}
fun resetStatus() {
synchronized(this) {
planningPoints.clear()
}
lastArrivedIndex = -1
}
/**
* 转为高德定位对象
*/
fun change2GDPoints(routePoints: List<MessagePad.Location>?, context: Context): List<LatLng> {
return if (routePoints == null || routePoints.isEmpty()) {
emptyList()
} else {
coordinateConverterWgsToGcjListCommon(context, routePoints)
}
}
/**
@@ -100,6 +121,7 @@ object MarkerDrawerManager {
* @param realLat
* @return 返回已经到达点的index
*/
@Synchronized
private fun getCarLocationIndex(
routePoints: List<LatLng>,
newPoints: MutableList<LatLng>,
@@ -108,14 +130,24 @@ object MarkerDrawerManager {
heading: Double
): Int {
var currentIndex = 0 //记录疑似点
// 是否超过200KM
var isLongDistance = false
if (routePoints.isNotEmpty()) {
//基础点
val baseLatLng = routePoints[0]
newPoints.add(baseLatLng)
var baseDiffDis = CoordinateUtils.calculateLineDistance(
realLon, realLat, baseLatLng.longitude, baseLatLng.latitude
) // lon,lat, prelon, prelat
for (i in 1 until routePoints.size) {
if (baseDiffDis > 200000) {
isLongDistance = true
}
val size = routePoints.size
for (i in 1 until size) {
val latLng = routePoints[i]
// 深拷贝数据用于高德地图上轨迹线的绘制
newPoints.add(LatLng(latLng.latitude, latLng.longitude))
if (isLongDistance) continue
val diff = CoordinateUtils.calculateLineDistance(
realLon, realLat, latLng.longitude, latLng.latitude
)
@@ -135,14 +167,20 @@ object MarkerDrawerManager {
}
}
Log.d("MarkerDrawerManager", "当次计算已走过的点的索引为:$currentIndex,存储的上次索引为:$lastArrivedIndex")
if (currentIndex < lastArrivedIndex) {
currentIndex = lastArrivedIndex
} else {
lastArrivedIndex = currentIndex
if (!isLongDistance) {
// 过滤缓存的非当次轨迹的索引,并且出现车已走过索引跳跃过大时视为无效复用上一次计算结果
if (currentIndex < lastArrivedIndex || (lastArrivedIndex >= 0 && currentIndex - lastArrivedIndex >= 10)) {
if (lastArrivedIndex < size) {
currentIndex = lastArrivedIndex
}
} else {
lastArrivedIndex = currentIndex
}
if (size >= 2) {
newPoints.add(currentIndex + 1, LatLng(realLat, realLon))
return currentIndex + 1
}
}
newPoints.addAll(routePoints)
newPoints.add(currentIndex + 1, LatLng(realLat, realLon))
return currentIndex + 1
}
return 0
}

View File

@@ -15,10 +15,7 @@ import android.widget.TextView
import androidx.annotation.MainThread
import androidx.core.graphics.drawable.toBitmap
import ch.hsr.geohash.GeoHash
import com.amap.api.maps.AMap
import com.amap.api.maps.CameraUpdate
import com.amap.api.maps.CameraUpdateFactory
import com.amap.api.maps.TextureMapView
import com.amap.api.maps.*
import com.amap.api.maps.model.*
import com.mogo.eagle.core.data.map.Infrastructure
import com.mogo.eagle.core.data.map.MogoLocation
@@ -37,21 +34,18 @@ import com.mogo.eagle.core.function.map.R
import com.mogo.eagle.core.function.smp.MakerWithCount
import com.mogo.eagle.core.function.smp.MarkerDrawerManager
import com.mogo.eagle.core.function.smp.MarkerDrawerManager.callback
import com.mogo.eagle.core.function.smp.MarkerDrawerManager.change2GDPoints
import com.mogo.eagle.core.function.smp.MarkerDrawerManager.coordinateConverterWgsToGcj
import com.mogo.eagle.core.function.smp.MarkerDrawerManager.lastArrivedIndex
import com.mogo.eagle.core.function.smp.MarkerDrawerManager.lonLatHeading
import com.mogo.eagle.core.function.smp.MarkerDrawerManager.planningPoints
import com.mogo.eagle.core.function.smp.MarkerDrawerManager.startLoopCalCarLocation
import com.mogo.eagle.core.function.smp.MarkerDrawerManager.updateRoutePoints
import com.mogo.eagle.core.function.smp.MarkerDrawerManager.updateGDRoutePoints
import com.mogo.eagle.core.function.smp.V2XMarkerView
import com.mogo.eagle.core.utilcode.mogo.MapAssetStyleUtils
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
import com.zhidaoauto.map.sdk.open.tools.ThreadPoolUtils
import me.jessyan.autosize.utils.AutoSizeUtils
import mogo.telematics.pad.MessagePad
import mogo.v2x.MogoV2X
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import kotlin.math.pow
@@ -127,10 +121,16 @@ class OverMapView @JvmOverloads constructor(
@Volatile
private var isInit = false
@Volatile
private var isFirst = true
// 用来绘制轨迹线
private val singlePool by lazy {
Executors.newSingleThreadExecutor()
}
private var allPoints: List<LatLng>? = null
companion object {
const val TAG = "OverMapView"
}
@@ -334,8 +334,9 @@ class OverMapView @JvmOverloads constructor(
mStartMarker?.isVisible = false
mEndMarker?.isVisible = false
MarkerDrawerManager.stopLoopCalCarLocation()
planningPoints.clear()
lastArrivedIndex = -1
ThreadUtils.getIoPool().execute {
MarkerDrawerManager.resetStatus()
}
isInit = false
}
@@ -355,10 +356,7 @@ class OverMapView @JvmOverloads constructor(
resources.getDrawable(R.drawable.transparent_background, null)
.toBitmap(AutoSizeUtils.dp2px(context, 32f), AutoSizeUtils.dp2px(context, 230f))
)
CallerPlanningRottingListenerManager.addListener(TAG, this)
initAMapView(context)
// 注册定位监听
CallerChassisLocationGCJ02ListenerManager.addListener(TAG, this)
//设置全览模式
overLayerView?.setOnClickListener { displayCustomOverView() }
overLayerView?.let {
@@ -403,6 +401,9 @@ class OverMapView @JvmOverloads constructor(
override fun onAttachedToWindow() {
super.onAttachedToWindow()
CallerPlanningRottingListenerManager.addListener(TAG, this)
// 注册定位监听
CallerChassisLocationGCJ02ListenerManager.addListener(TAG, this)
CallerFuncBizListenerManager.addListener(TAG, object : IFuncBizProvider {
override fun onInfStructures(map: HashMap<String, ArrayList<Infrastructure>>?) {
geoHashInfMap = map
@@ -470,37 +471,50 @@ class OverMapView @JvmOverloads constructor(
Log.d(TAG, "全局路径规划轨迹为空")
return
}
Log.d(TAG, "全局路径规划轨迹下发")
isFirst = true
MarkerDrawerManager.resetStatus()
val list: List<MessagePad.Location> = locationList
// 转成高德坐标系并存储
updateRoutePoints(list, mContext!!)
val planningPointList: List<LatLng> = planningPoints
UiThreadHandler.post ({
displayCustomOverView()
drawStartAndEndMarker(planningPointList)
}, UiThreadHandler.MODE.QUEUE)
if (!isInit) {
callback = object : MarkerDrawerManager.Callback {
override fun onLocationChanged(planningPoints: List<LatLng>, locIndex: Int) {
// 每1s刷新一下轨迹线
UiThreadHandler.post ({
if (planningPoints.isNotEmpty()) {
drawPolyline(planningPoints, locIndex)
// 转成高德定位对象并存储
val planningPointList = change2GDPoints(list, mContext!!)
updateGDRoutePoints(planningPointList)
synchronized(this::class.java) {
if (!isInit) {
var timeStamp = 0L
callback = object : MarkerDrawerManager.Callback {
override fun onLocationChanged(points: List<LatLng>, locIndex: Int) {
if (points.isNotEmpty()) {
// 每1s刷新一下轨迹线
singlePool.execute {
if (isFirst) {
Log.d(TAG, "第一次!")
isFirst = false
allPoints = points
displayCustomOverView()
drawStartAndEndMarker(points)
}
timeStamp = System.currentTimeMillis()
drawPolyline(points, locIndex)
Log.d(TAG, "绘制轨迹线的时间为:${System.currentTimeMillis() - timeStamp}ms")
}
}
}, UiThreadHandler.MODE.QUEUE)
}
}
startLoopCalCarLocation()
isInit = true
}
startLoopCalCarLocation()
isInit = true
}
UiThreadHandler.post({
if (geoHashInfMap.isNullOrEmpty()) {
UiThreadHandler.postDelayed({
if (geoHashInfMap.isNullOrEmpty()) {
UiThreadHandler.postDelayed({
singlePool.execute {
drawInfrastructureMarkers(locationList)
}, 1000, UiThreadHandler.MODE.QUEUE)
} else {
}
}, 1000, UiThreadHandler.MODE.QUEUE)
} else {
singlePool.execute {
drawInfrastructureMarkers(locationList)
}
}, UiThreadHandler.MODE.QUEUE)
}
}
/**
@@ -662,33 +676,39 @@ class OverMapView @JvmOverloads constructor(
* 进入自定义全览模式
*/
fun displayCustomOverView() {
val linePointsLatLng = planningPoints
if (linePointsLatLng.size > 1 && mLocation != null) {
//圈定地图显示范围
//存放经纬度
val boundsBuilder = LatLngBounds.Builder()
for (i in linePointsLatLng.indices) {
boundsBuilder.include(linePointsLatLng[i])
singlePool.execute {
val linePointsLatLng = allPoints
if (linePointsLatLng != null && linePointsLatLng.size > 1 && mLocation != null) {
//圈定地图显示范围
//存放经纬度
val boundsBuilder = LatLngBounds.Builder()
for (i in linePointsLatLng.indices) {
boundsBuilder.include(linePointsLatLng[i])
}
val currentLatLng = LatLng(mLocation!!.latitude, mLocation!!.longitude)
boundsBuilder.include(currentLatLng)
val cameraPosition = CameraPosition.Builder().tilt(mTilt).build()
//第二个参数为四周留空宽度
if (mAMap != null) {
mAMap!!.moveCamera(
CameraUpdateFactory.newLatLngBoundsRect(
boundsBuilder.build(),
AutoSizeUtils.dp2px(context, leftPadding.toFloat()),
AutoSizeUtils.dp2px(context, rightPadding.toFloat()),
AutoSizeUtils.dp2px(context, topPadding.toFloat()),
AutoSizeUtils.dp2px(context, bottomPadding.toFloat())
)
)
mAMap!!.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition))
}
} else {
if (mCarMarker != null && mAMap != null) {
//设置希望展示的地图缩放级别
val cameraPosition = CameraPosition.Builder()
.target(mCarMarker!!.position).tilt(mTilt).zoom(zoomLevel.toFloat()).build()
mAMap!!.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition))
}
}
val currentLatLng = LatLng(mLocation!!.latitude, mLocation!!.longitude)
boundsBuilder.include(currentLatLng)
val cameraPosition = CameraPosition.Builder().tilt(mTilt).build()
//第二个参数为四周留空宽度
mAMap!!.moveCamera(
CameraUpdateFactory.newLatLngBoundsRect(
boundsBuilder.build(),
AutoSizeUtils.dp2px(context, leftPadding.toFloat()),
AutoSizeUtils.dp2px(context, rightPadding.toFloat()),
AutoSizeUtils.dp2px(context, topPadding.toFloat()),
AutoSizeUtils.dp2px(context, bottomPadding.toFloat())
)
)
mAMap!!.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition))
} else {
//设置希望展示的地图缩放级别
val cameraPosition = CameraPosition.Builder()
.target(mCarMarker!!.position).tilt(mTilt).zoom(zoomLevel.toFloat()).build()
mAMap!!.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition))
}
}
@@ -699,14 +719,16 @@ class OverMapView @JvmOverloads constructor(
*/
private fun drawCarMarker(location: MogoLocation?) {
if (location == null) return
if (mCarMarker != null) {
val currentLatLng = LatLng(location.latitude, location.longitude)
mCarMarker!!.rotateAngle = (360 - location.heading).toFloat()
mCarMarker!!.position = currentLatLng
mCarMarker!!.setToTop()
if (mCompassMarker != null) {
mCompassMarker!!.rotateAngle = (360 - location.heading).toFloat()
mCompassMarker!!.position = currentLatLng
singlePool.execute {
if (mCarMarker != null) {
val currentLatLng = LatLng(location.latitude, location.longitude)
mCarMarker!!.rotateAngle = (360 - location.heading).toFloat()
mCarMarker!!.position = currentLatLng
mCarMarker!!.setToTop()
if (mCompassMarker != null) {
mCompassMarker!!.rotateAngle = (360 - location.heading).toFloat()
mCompassMarker!!.position = currentLatLng
}
}
}
}
@@ -718,6 +740,7 @@ class OverMapView @JvmOverloads constructor(
mStartMarker?.isVisible = false
mEndMarker?.isVisible = false
if (coordinates.size > 2) {
Log.d(TAG, "绘制起终点")
// 设置开始结束Marker位置
val startLatLng = coordinates[0]
val endLatLng = coordinates[coordinates.size - 1]
@@ -725,6 +748,8 @@ class OverMapView @JvmOverloads constructor(
mEndMarker?.position = endLatLng
mStartMarker?.isVisible = true
mEndMarker?.isVisible = true
} else {
Log.d(TAG, "不绘制起终点")
}
}
@@ -734,8 +759,7 @@ class OverMapView @JvmOverloads constructor(
* @param coordinates
* @param locIndex
*/
@MainThread
fun drawPolyline(coordinates: List<LatLng>, locIndex: Int) {
private fun drawPolyline(coordinates: List<LatLng>, locIndex: Int) {
if (textureList.size > 0) {
textureList.clear()
}
@@ -759,6 +783,7 @@ class OverMapView @JvmOverloads constructor(
texIndexList.add(i - 1)
}
if (mAMap != null && coordinates.size > 2) {
// Log.d(TAG, "绘制时轨迹点数为:${coordinates.size},纹理数为:${textureList.size},车辆index为$locIndex")
//设置线段纹理
val polylineOptions = PolylineOptions()
polylineOptions.addAll(coordinates)
@@ -819,60 +844,69 @@ class OverMapView @JvmOverloads constructor(
* 站点轨迹集合被包含在地图显示范围内
*/
fun includeSitePointsAndUpdateCamera(coordinates: List<LatLng>?) {
val linePointsLatLng = planningPoints
val boundsBuilder = LatLngBounds.Builder()
var isOnlyCarLocation = true
singlePool.execute {
val linePointsLatLng = allPoints
val boundsBuilder = LatLngBounds.Builder()
var isOnlyCarLocation = true
if (linePointsLatLng.size > 1) {
// 圈定地图显示范围(自动驾驶轨迹)
for (i in linePointsLatLng.indices) {
boundsBuilder.include(linePointsLatLng[i])
if (linePointsLatLng != null && linePointsLatLng.size > 1) {
// 圈定地图显示范围(自动驾驶轨迹)
for (i in linePointsLatLng.indices) {
boundsBuilder.include(linePointsLatLng[i])
}
isOnlyCarLocation = false
}
isOnlyCarLocation = false
}
if (mLocation != null) {
// 自车坐标
boundsBuilder.include(LatLng(mLocation!!.latitude, mLocation!!.longitude))
}
coordinates?.let {
// 站点轨迹被包含在地图显示范围内
for (i in it.indices) {
boundsBuilder.include(it[i])
if (mLocation != null) {
// 自车坐标
boundsBuilder.include(LatLng(mLocation!!.latitude, mLocation!!.longitude))
}
isOnlyCarLocation = false
}
if (!isOnlyCarLocation) {
val cameraPosition = CameraPosition.Builder().tilt(mTilt).build()
//第二个参数为四周留空宽度
mAMap!!.moveCamera(
CameraUpdateFactory.newLatLngBoundsRect(
boundsBuilder.build(),
AutoSizeUtils.dp2px(context, leftPadding.toFloat()),
AutoSizeUtils.dp2px(context, rightPadding.toFloat()),
AutoSizeUtils.dp2px(context, topPadding.toFloat()),
AutoSizeUtils.dp2px(context, bottomPadding.toFloat())
)
)
mAMap!!.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition))
} else {
//设置希望展示的地图缩放级别
val cameraPosition = CameraPosition.Builder()
.target(mCarMarker!!.position).tilt(mTilt).zoom(zoomLevel.toFloat()).build()
mAMap!!.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition))
coordinates?.let {
// 站点轨迹被包含在地图显示范围内
for (i in it.indices) {
boundsBuilder.include(it[i])
}
isOnlyCarLocation = false
}
if (!isOnlyCarLocation) {
val cameraPosition = CameraPosition.Builder().tilt(mTilt).build()
//第二个参数为四周留空宽度
if (mAMap != null) {
mAMap!!.moveCamera(
CameraUpdateFactory.newLatLngBoundsRect(
boundsBuilder.build(),
AutoSizeUtils.dp2px(context, leftPadding.toFloat()),
AutoSizeUtils.dp2px(context, rightPadding.toFloat()),
AutoSizeUtils.dp2px(context, topPadding.toFloat()),
AutoSizeUtils.dp2px(context, bottomPadding.toFloat())
)
)
mAMap!!.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition))
}
} else {
//设置希望展示的地图缩放级别
if (mCarMarker != null && mAMap != null) {
val cameraPosition = CameraPosition.Builder()
.target(mCarMarker!!.position).tilt(mTilt).zoom(zoomLevel.toFloat()).build()
mAMap!!.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition))
}
}
}
}
override fun onChassisLocationGCJ02(gnssInfo: MogoLocation?) {
gnssInfo?.let {
mLocation = it
lonLatHeading = Triple(it.longitude, it.latitude, it.heading)
drawCarMarker(it)
if (isFirstLocation) {
displayCustomOverView()
isFirstLocation = false
// 在中国境内
if (CoordinateConverter.isAMapDataAvailable(it.latitude, it.longitude)) {
mLocation = it
lonLatHeading = Triple(it.longitude, it.latitude, it.heading)
drawCarMarker(it)
if (isFirstLocation) {
displayCustomOverView()
isFirstLocation = false
}
}
}
@@ -885,7 +919,7 @@ class OverMapView @JvmOverloads constructor(
*/
override fun onAutopilotRotting(globalPathResp: MessagePad.GlobalPathResp?) {
globalPathResp?.let {
singlePool.execute {
ThreadUtils.getIoPool().execute {
handlePlanningData(it.wayPointsList)
}
}