From 72647f150f46307cd30baf21c32743b2e76f16b1 Mon Sep 17 00:00:00 2001 From: xuxinchao Date: Fri, 9 May 2025 17:11:01 +0800 Subject: [PATCH] =?UTF-8?q?[8.0.0]=E8=BD=A6=E9=BE=99=E4=BA=8B=E4=BB=B6?= =?UTF-8?q?=E8=BF=9BMogoMind?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../unmanned/passenger/ui/aiview/AiView.kt | 5 + .../passenger/ui/aiview/NDEViewModel.kt | 83 ++++++ .../ui/aiview/adapter/AIMessageAdapter.kt | 2 + .../ui/aiview/adapter/AIMessageViewHolder.kt | 22 ++ .../ui/aiview/adapter/AINDERoadAdapter.kt | 237 ++++++++++++++++++ .../ui/aiview/bean/AssistantMessage.kt | 15 ++ .../src/main/res/layout/item_ai_nde_event.xml | 63 +++++ .../src/main/res/layout/item_ai_nde_road.xml | 43 ++++ 8 files changed, 470 insertions(+) create mode 100644 OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/aiview/NDEViewModel.kt create mode 100644 OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/aiview/adapter/AINDERoadAdapter.kt create mode 100644 OCH/taxi/unmanned-passenger/src/main/res/layout/item_ai_nde_event.xml create mode 100644 core/function-impl/mogo-core-function-hmi/src/main/res/layout/item_ai_nde_road.xml diff --git a/OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/aiview/AiView.kt b/OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/aiview/AiView.kt index 1087c5a359..4e2ca32a06 100644 --- a/OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/aiview/AiView.kt +++ b/OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/aiview/AiView.kt @@ -51,6 +51,7 @@ class AiView @JvmOverloads constructor( private var roadV2NEventModel:RoadV2NEventViewModel ?= null private var roadCrossRoamModel:RoadCrossRoamViewModel ?= null private var automaticExplorationModel:AutomaticExplorationViewModel ?= null + private var ndeViewModel: NDEViewModel ?= null private var aiAnimator: BigFrameAnimatorContainer?=null private var aiAnimatorBg: BigFrameAnimatorContainer?=null @@ -240,6 +241,10 @@ class AiView @JvmOverloads constructor( ViewModelProvider(it)[AutomaticExplorationViewModel::class.java] } automaticExplorationModel?.init() + ndeViewModel = findViewTreeViewModelStoreOwner()?.let{ + ViewModelProvider(it)[NDEViewModel::class.java] + } + ndeViewModel?.init() } private fun startListInfo(){ diff --git a/OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/aiview/NDEViewModel.kt b/OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/aiview/NDEViewModel.kt new file mode 100644 index 0000000000..66c3fc90a0 --- /dev/null +++ b/OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/aiview/NDEViewModel.kt @@ -0,0 +1,83 @@ +package com.mogo.och.unmanned.passenger.ui.aiview + +import androidx.lifecycle.ViewModel +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotIdentifyListener +import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotIdentifyListenerManager +import com.mogo.och.unmanned.passenger.ui.aiview.bean.AIMessage +import mogo.telematics.pad.MessagePad.TrackedObject + +class NDEViewModel: ViewModel(), IMoGoAutopilotIdentifyListener { + + companion object{ + private const val TAG = "NDEViewModel" + } + + private var lastMap2 = HashMap() + private var lastTime = 0L + + fun init(){ + CallerAutopilotIdentifyListenerManager.addListener(TAG, this) + } + + override fun onAutopilotIdentifyDataUpdate(trafficData: List?){ + super.onAutopilotIdentifyDataUpdate(trafficData) + handleCheLong(trafficData) + } + + private fun handleCheLong(trafficData: List?) { + var hasCheLong = false + var isNewData = false + val roadMsgList = ArrayList() + val curMap = HashMap() + if (lastTime > 0 && System.currentTimeMillis() - lastTime > 60000) { + lastMap2.clear()// 清除上次车龙事件的缓存 + } + var lastLocStr: String? = "" + trafficData?.forEach { obj -> + if (obj.type == 707) {// 当前方向所有车道 + if (obj.polygonCount > 1) {// 当次数据有车龙事件 + lastLocStr = lastMap2[obj.laneNum] + // 1. 上次无车龙但此次有车龙,认为是新车龙事件 + // 2. 两次都有车龙,则判断车龙的长度是否相同 + if (lastLocStr == null || lastLocStr == "0" || lastLocStr != "${obj.polygonList[0]}-${obj.polygonList[obj.polygonCount - 1]}") { + isNewData = true + } + hasCheLong = true + + // key: 车道号,value: 非0代表有车龙且首、尾两个点可计算车龙长度 + curMap[obj.laneNum] = + "${obj.polygonList[0]}-${obj.polygonList[obj.polygonCount - 1]}" + } else {// 当次没有车龙 + if (lastMap2[obj.laneNum] != null && lastMap2[obj.laneNum] != "0") {// 3. 上次有车龙,这次无车龙 + isNewData = true + } + // key: 车道号,value: 0代表无车龙 + curMap[obj.laneNum] = "0" + } + // 保存所有车道信息 + roadMsgList.add( + AIMessage.RoadMsg( + obj.arrowType, + laneNum = obj.laneNum, + isRecommend = obj.suggestedLanes, + isCheLong = obj.polygonCount > 1 + ) + ) + } + } + if (isNewData) { + // 清除上次车道信息 + lastMap2.clear() + if (hasCheLong) { + // 缓存当次车龙事件所有车道信息 + lastMap2.putAll(curMap) + lastTime = System.currentTimeMillis() + + val sortedList = roadMsgList.sortedWith(compareByDescending { it.laneNum }) + val ndeEvent = AIMessage.NDEData(System.currentTimeMillis().toString(),"路口车龙","前方路口有车龙",sortedList) + AIMessageManager.post(ndeEvent) + } + } + } + +} \ No newline at end of file diff --git a/OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/aiview/adapter/AIMessageAdapter.kt b/OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/aiview/adapter/AIMessageAdapter.kt index bf20535f64..665e2f7b04 100644 --- a/OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/aiview/adapter/AIMessageAdapter.kt +++ b/OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/aiview/adapter/AIMessageAdapter.kt @@ -25,6 +25,7 @@ class AIMessageAdapter : ListAdapter(MessageDiffCa AIMessage.TYPE_ROAD_CROSS -> RoadCrossRoamViewHolder(inflater.inflate(R.layout.item_ai_road_cross_roam,parent,false)) AIMessage.TYPE_AUTOMATIC_EXPLORATION -> AutomaticExplorationViewHolder(inflater.inflate(R.layout.item_ai_automatic_exploration,parent,false)) AIMessage.TYPE_EVALUATE -> EvaluateViewViewHolder(inflater.inflate(R.layout.taxi_p_evaluate,parent,false)) + AIMessage.TYPE_NDE -> NDEViewHolder(inflater.inflate(R.layout.item_ai_nde_event,parent,false)) else -> throw IllegalArgumentException("Invalid view type") } } @@ -42,6 +43,7 @@ class AIMessageAdapter : ListAdapter(MessageDiffCa is AIMessage.RoadCrossRoam -> AIMessage.TYPE_ROAD_CROSS is AIMessage.AutomaticExploration -> AIMessage.TYPE_AUTOMATIC_EXPLORATION is AIMessage.EvaluateData -> AIMessage.TYPE_EVALUATE + is AIMessage.NDEData -> AIMessage.TYPE_NDE else -> AIMessage.TYPE_EVENT } } diff --git a/OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/aiview/adapter/AIMessageViewHolder.kt b/OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/aiview/adapter/AIMessageViewHolder.kt index a4576e846b..99f87adb19 100644 --- a/OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/aiview/adapter/AIMessageViewHolder.kt +++ b/OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/aiview/adapter/AIMessageViewHolder.kt @@ -23,6 +23,7 @@ import com.mogo.commons.voice.AIAssist import com.mogo.eagle.core.data.notice.AutoExplorationEntity import com.mogo.eagle.core.data.v2x.RoadV2NEventType import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationWGS84ListenerManager +import com.mogo.eagle.core.function.hmi.ui.msgbox.adapter.PassengerNDERoadAdapter import com.mogo.eagle.core.function.hmi.ui.notice.exploration.AutomaticExplorationAdapter import com.mogo.eagle.core.function.hmi.ui.v2n.RoadV2NEventLivePlayView import com.mogo.eagle.core.function.view.MapRoamView @@ -412,6 +413,27 @@ class EvaluateViewViewHolder(binding: View) : MessageViewHolder(binding) { } } +class NDEViewHolder(binding: View) : MessageViewHolder(binding){ + + private var tvNdeTitle: TextView = binding.findViewById(R.id.tvNdeTitle) + private var tvNdeContent: TextView = binding.findViewById(R.id.tvNdeContent) + private var rvNdeList: RecyclerView = binding.findViewById(R.id.rvNdeList) + + override fun bind(item: AIMessage, onItemClickListener: OnItemClickListener?) { + if(item is AIMessage.NDEData){ + tvNdeTitle.text = item.title + tvNdeContent.text = item.desc + val linearLayoutManager = LinearLayoutManager(itemView.context) + linearLayoutManager.orientation = LinearLayoutManager.HORIZONTAL + val ndeRoadAdapter = AINDERoadAdapter(itemView.context) + rvNdeList.adapter = ndeRoadAdapter + rvNdeList.layoutManager = linearLayoutManager + ndeRoadAdapter.setData(item.roadList) + } + } + +} + private class NoScrollLayoutManager(context: Context?) : LinearLayoutManager(context) { override fun canScrollVertically(): Boolean { return false diff --git a/OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/aiview/adapter/AINDERoadAdapter.kt b/OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/aiview/adapter/AINDERoadAdapter.kt new file mode 100644 index 0000000000..0d2ec97ca1 --- /dev/null +++ b/OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/aiview/adapter/AINDERoadAdapter.kt @@ -0,0 +1,237 @@ +package com.mogo.och.unmanned.passenger.ui.aiview.adapter + +import android.content.Context +import android.util.TypedValue +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.RecyclerView +import com.mogo.och.unmanned.passenger.ui.aiview.bean.AIMessage +import com.mogo.och.unmanned.taxi.passenger.R + +class AINDERoadAdapter(private val context: Context): RecyclerView.Adapter() { + + private var roadList: List?= null + + fun setData(list: List){ + roadList = list + notifyDataSetChanged() + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AIRoadHolder { + val view = LayoutInflater.from(parent.context) + .inflate(R.layout.item_ai_nde_road, parent, false) + return AIRoadHolder(view) + } + + override fun onBindViewHolder(holder: AIRoadHolder, position: Int) { + roadList?.let{ + val roadMsg = it[position] + if(it.size < 3){ + //设置item宽度为最大宽度180dp + val params = ConstraintLayout.LayoutParams( + TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 180f, + context.resources.displayMetrics).toInt(), + ConstraintLayout.LayoutParams.WRAP_CONTENT) + holder.clRoadLayout.layoutParams = params + }else if(it.size == 3){ + //设置item宽度为最大宽度180dp + val params = ConstraintLayout.LayoutParams( + TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 120f, + context.resources.displayMetrics).toInt(), + ConstraintLayout.LayoutParams.WRAP_CONTENT) + holder.clRoadLayout.layoutParams = params + }else if(it.size == 4){ + //设置item宽度为最大宽度180dp + val params = ConstraintLayout.LayoutParams( + TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100f, + context.resources.displayMetrics).toInt(), + ConstraintLayout.LayoutParams.WRAP_CONTENT) + holder.clRoadLayout.layoutParams = params + }else{ + val params = ConstraintLayout.LayoutParams( + TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 90f, + context.resources.displayMetrics).toInt(), + ConstraintLayout.LayoutParams.WRAP_CONTENT) + holder.clRoadLayout.layoutParams = params + } + when(roadMsg.arrowType){ + //直行 + 201->{ + holder.ivRoadType.setImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.icon_road_forward + )) + } + //直行或左转 + 202->{ + holder.ivRoadType.setImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.icon_road_forward_or_turn_left + )) + } + //直行或右转 + 203->{ + holder.ivRoadType.setImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.icon_road_forward_or_turn_right + )) + } + //直行或掉头 + 204->{ + holder.ivRoadType.setImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.icon_road_forward_or_reverse + )) + } + //左转 + 205->{ + holder.ivRoadType.setImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.icon_road_turn_left + )) + } + //左转或掉头 + 206->{ + holder.ivRoadType.setImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.icon_road_turn_left_or_reverse + )) + } + //左弯或向左合流 + 207->{ + holder.ivRoadType.setImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.icon_road_turn_or_merge_left + )) + } + //右转 + 208->{ + holder.ivRoadType.setImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.icon_road_turn_right + )) + } + //右转或向右合流 + 209->{ + holder.ivRoadType.setImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.icon_road_turn_or_merge_right + )) + } + //左右转弯 + 210->{ + holder.ivRoadType.setImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.icon_road_turn_left_or_right + )) + } + //掉头 + 211->{ + holder.ivRoadType.setImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.icon_road_reverse + )) + } + //禁止左转 + 212->{ + holder.ivRoadType.setImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.icon_road_prohibit_turn_left + )) + } + //禁止右转 + 213->{ + holder.ivRoadType.setImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.icon_road_prohibit_turn_right + )) + } + //禁止掉头 + 214->{ + holder.ivRoadType.setImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.icon_road_prohibit_reverse + )) + } + //直行或左转或右转 + 215->{ + holder.ivRoadType.setImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.icon_road_forward_turn_left_right + )) + } + //直行或掉头或左转 + 216->{ + holder.ivRoadType.setImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.icon_road_forward_turn_left_reverse + )) + } + //右转或掉头 + 217->{ + holder.ivRoadType.setImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.icon_road_turn_right_or_reverse + )) + } + //禁止右转或向右合流 + 218->{ + holder.ivRoadType.setImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.icon_road_prohibit_turn_or_merge_right + )) + } + } + //是否是推荐车道 + if(roadMsg.isRecommend){ + holder.tvRoadStatus.text = context.getString(R.string.nde_road_recommend) + holder.tvRoadStatus.setTextColor(context.getColor(R.color.msg_nde_road_recommend)) + holder.clRoadLayout.background = ContextCompat.getDrawable( + context, + R.drawable.bg_nde_road_recommend + ) + } + //是否有车龙,代表拥堵、行驶缓慢 + if(roadMsg.isCheLong){ + holder.tvRoadStatus.text = context.getString(R.string.nde_road_slow) + holder.tvRoadStatus.setTextColor(context.getColor(R.color.msg_nde_road_slow)) + } + if(position == it.lastIndex){ + holder.viewDivider.visibility = View.INVISIBLE + } + } + } + + override fun getItemCount() = roadList?.size ?: 0 + + class AIRoadHolder(itemView: View) : RecyclerView.ViewHolder(itemView){ + var clRoadLayout: ConstraintLayout = itemView.findViewById(R.id.clRoadLayout) + var ivRoadType: ImageView = itemView.findViewById(R.id.ivRoadType) + var tvRoadStatus: TextView = itemView.findViewById(R.id.tvRoadStatus) + var viewDivider: View = itemView.findViewById(R.id.viewDivider) + } + +} \ No newline at end of file diff --git a/OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/aiview/bean/AssistantMessage.kt b/OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/aiview/bean/AssistantMessage.kt index e46dac59fe..d6d00d5861 100644 --- a/OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/aiview/bean/AssistantMessage.kt +++ b/OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/aiview/bean/AssistantMessage.kt @@ -26,6 +26,7 @@ sealed class AIMessage( const val TYPE_ROAD_CROSS = 8 const val TYPE_AUTOMATIC_EXPLORATION = 9 const val TYPE_EVALUATE = 10 + const val TYPE_NDE = 11 } data class Scan( @@ -167,4 +168,18 @@ sealed class AIMessage( var isFirst:Boolean = true ): AIMessage(id,title) + data class NDEData( + override val id: String, + override val title: String, + var desc: String, + var roadList: List + ):AIMessage(id,title) + + data class RoadMsg( + var arrowType: Int, // 车道类型,如直行201(详情参考文件:message_pad.proto) + var laneNum: Int,// 车道号 + var isRecommend: Boolean,// 是否是推荐车道 + var isCheLong: Boolean// 是否有车龙,代表拥堵、行驶缓慢 + ) + } \ No newline at end of file diff --git a/OCH/taxi/unmanned-passenger/src/main/res/layout/item_ai_nde_event.xml b/OCH/taxi/unmanned-passenger/src/main/res/layout/item_ai_nde_event.xml new file mode 100644 index 0000000000..12b5324bb9 --- /dev/null +++ b/OCH/taxi/unmanned-passenger/src/main/res/layout/item_ai_nde_event.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/layout/item_ai_nde_road.xml b/core/function-impl/mogo-core-function-hmi/src/main/res/layout/item_ai_nde_road.xml new file mode 100644 index 0000000000..9232a72486 --- /dev/null +++ b/core/function-impl/mogo-core-function-hmi/src/main/res/layout/item_ai_nde_road.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + \ No newline at end of file