Merge branch 'dev_robotaxi-d_250117_6.10.0' into dev_robotaxi-d_241210_6.10.0_yyk

This commit is contained in:
yangyakun
2025-02-06 09:41:45 +08:00
23 changed files with 649 additions and 77 deletions

View File

@@ -205,7 +205,7 @@ class DevaToolsProvider : IDevaToolsProvider, IAppStateListener {
// apmEnvProvider.init(if(DebugConfig.isDebug()) "0" else "1", "${ DebugConfig.getNetMode() }", mDockerVersion ?: "")
BadCaseManager.init(mContext!!)
ColdStartManager.init(mContext!!)
// OTAUpgradeManager.init(mContext!!)
OTAUpgradeManager.init(mContext!!)
if (DebugConfig.isDebug()) {
SdtManager.init(mContext!!, true, DetectResultImpl())
}

View File

@@ -156,6 +156,10 @@ internal object BadCaseManager : LifecycleEventObserver, IMoGoAutopilotRecordLis
BadCaseConfig.setStartTime(currentDay)
//删除前一天的接管记录
CallerTakeOverManager.deleteAllRecord(context)
//遍历是否有非当日的文件并删除
RecordBitmapUtils.deleteExpiredFile(currentDay,"FrontCamera")
RecordBitmapUtils.deleteExpiredFile(currentDay,"RearCamera")
RecordBitmapUtils.deleteExpiredFile(currentDay,"MapScreen")
}
}
@@ -417,7 +421,6 @@ internal object BadCaseManager : LifecycleEventObserver, IMoGoAutopilotRecordLis
override fun onAutopilotRecordResult(recordPanel: RecordPanelOuterClass.RecordPanel) {
super.onAutopilotRecordResult(recordPanel)
CallerLogger.d("$M_DEVA$TAG", "recordKey=${recordPanel.key},stat=${recordPanel.stat},type=${recordPanel.type}")
CallerLogger.i(TestTag,"onAutopilotRecordResult receive recordKey=${recordPanel.key},stat=${recordPanel.stat},type=${recordPanel.type},lineName=${BadCaseConfig.lineName}")
if(BadCaseConfig.notDisplayBagWindow){
//此时点击主动录包按钮,不能展示上报弹窗,需要在此处做主动录包弹窗中的一些逻辑
//开始录制
@@ -441,22 +444,18 @@ internal object BadCaseManager : LifecycleEventObserver, IMoGoAutopilotRecordLis
CallerLogger.i(TestTag,"onAutopilotRecordResult contains recordKey=${recordPanel.key},stat=${recordPanel.stat},type=${recordPanel.type},lineName=${BadCaseConfig.lineName}")
//目前type == 3包括接管被动录包和其他一些故障录包
if(recordPanel.type == 3){
CallerLogger.i(TestTag,"onAutopilotRecordResult 符合type=3 recordKey=${recordPanel.key},stat=${recordPanel.stat},type=${recordPanel.type},lineName=${BadCaseConfig.lineName}")
//录包成功
if(recordPanel.stat == 100 || recordPanel.stat == 101){
CallerLogger.i(TestTag,"onAutopilotRecordResult 录包成功 recordKey=${recordPanel.key},stat=${recordPanel.stat},type=${recordPanel.type},lineName=${BadCaseConfig.lineName}")
val activity = AppStateManager.currentActivity()
if (activity !is AppCompatActivity) {
return
}
CallerLogger.i(TestTag,"activity符合条件")
val geocodeSearch = GeocodeSearch(activity)
geocodeSearch.setOnGeocodeSearchListener(object: GeocodeSearch.OnGeocodeSearchListener {
override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult?, p1: Int) {
regeocodeResult?.regeocodeAddress?.formatAddress?.let {
address = it
}
CallerLogger.i(TestTag,"onRegeocodeSearched address=${address}")
val takeOverRecordInfo = TakeOverRecordInfo(System.currentTimeMillis(),
address,level1Id,level2Id,level3Id,
level1Name, level2Name, level3Name,
@@ -477,12 +476,12 @@ internal object BadCaseManager : LifecycleEventObserver, IMoGoAutopilotRecordLis
val q = RegeocodeQuery(latLon,200f,GeocodeSearch.AMAP)
geocodeSearch.getFromLocationAsyn(q)
takeOverBagId = recordPanel.key
// //触发域控前后120度摄像头截图和高精地图截图
// CallerAutoPilotControlManager.sendCaptureImgReqOnTakeOver(recordPanel.key)
// //高精地图屏幕截图
// CallerMapScreenListenerManager.addListener(TAG,this)
// //开启高精地图截图
// CallerMapUIServiceManager.getMapUIController()?.getMapScreenShot()
//触发域控前后120度摄像头截图和高精地图截图
CallerAutoPilotControlManager.sendCaptureImgReqOnTakeOver(recordPanel.key)
//高精地图屏幕截图
CallerMapScreenListenerManager.addListener(TAG,this)
//开启高精地图截图
CallerMapUIServiceManager.getMapUIController()?.getMapScreenShot()
}
}
}

View File

@@ -36,9 +36,11 @@ object RecordBitmapUtils {
/**
* 删除过期文件夹
* @param currentDay 要删除的文件日期
* @param deleteFile 要删除的文件目录
*/
fun deleteExpiredFile(currentDay: String){
val checkFileName = Environment.getExternalStorageDirectory().absolutePath + File.separator+ "MapScreen"
fun deleteExpiredFile(currentDay: String,deleteFile: String){
val checkFileName = Environment.getExternalStorageDirectory().absolutePath + File.separator+ deleteFile
val checkFileFolder = File(checkFileName)
if(checkFileFolder.exists()){
checkFileFolder.listFiles()?.forEach {dir->

View File

@@ -3,7 +3,9 @@ package com.zhjt.mogo_core_function_devatools.workorder
import android.annotation.SuppressLint
import android.app.Activity
import android.graphics.PixelFormat
import android.net.Uri
import android.os.Bundle
import android.os.Environment
import android.text.Editable
import android.text.TextWatcher
import android.util.DisplayMetrics
@@ -41,13 +43,15 @@ import com.mogo.eagle.core.utilcode.util.BarUtils
import com.mogo.eagle.core.utilcode.util.JsonParser
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.eagle.core.utilcode.util.TimeUtils
import com.mogo.eagle.core.utilcode.util.TimeUtils.getMdFormat
import com.mogo.eagle.core.utilcode.util.TimeUtils.millis2String
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.mogo.tts.base.SpeechUtils
import com.zhjt.mogo_core_function_devatools.R
import com.zhjt.mogo_core_function_devatools.badcase.consts.BadCaseConfig
import com.zhjt.mogo_core_function_devatools.workorder.adapter.OrderReasonAdapter
import kotlin.math.absoluteValue
import java.io.File
/**
* 接管原因编辑窗口
@@ -63,11 +67,7 @@ class TakeOverReasonWindow constructor(activity: Activity) : View.OnTouchListene
private var mWindowParams: WindowManager.LayoutParams? = null
private var mWindowManager: WindowManager? = null
private lateinit var mFloatLayout: View
private var mInViewX = 0f
private var mInViewY = 0f
private var mInScreenX = 0f
private var mInScreenY = 0f
private var takeOverSceneWindow: TakeOverSceneWindow ?= null
// 语音听写对象
private var mIat: SpeechRecognizer? = null
@@ -84,6 +84,9 @@ class TakeOverReasonWindow constructor(activity: Activity) : View.OnTouchListene
private lateinit var tvTakeOverReason: AppCompatTextView
private lateinit var etNoteInput: AppCompatEditText
private lateinit var ivNoteAudio: ImageView
private lateinit var ivFrontCamera: ImageView
private lateinit var ivRearCamera: ImageView
private lateinit var ivMapScreen: ImageView
private lateinit var tvTakeOverSave: TextView
private lateinit var tvTakeOverCancel: TextView
private lateinit var rvTakeOverList: RecyclerView
@@ -132,7 +135,7 @@ class TakeOverReasonWindow constructor(activity: Activity) : View.OnTouchListene
it.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
it.gravity = Gravity.START or Gravity.TOP
it.width = 902
it.height = 1530
it.height = 1535
it.alpha = 1.0f
}
}
@@ -143,6 +146,9 @@ class TakeOverReasonWindow constructor(activity: Activity) : View.OnTouchListene
tvTakeOverReason = mFloatLayout.findViewById(R.id.tvTakeOverReason)
etNoteInput = mFloatLayout.findViewById(R.id.etNoteInput)
ivNoteAudio = mFloatLayout.findViewById(R.id.ivNoteAudio)
ivFrontCamera = mFloatLayout.findViewById(R.id.ivFrontCamera)
ivRearCamera = mFloatLayout.findViewById(R.id.ivRearCamera)
ivMapScreen = mFloatLayout.findViewById(R.id.ivMapScreen)
tvTakeOverSave = mFloatLayout.findViewById(R.id.tvTakeOverSave)
tvTakeOverCancel = mFloatLayout.findViewById(R.id.tvTakeOverCancel)
rvTakeOverList = mFloatLayout.findViewById(R.id.rvTakeOverList)
@@ -316,6 +322,13 @@ class TakeOverReasonWindow constructor(activity: Activity) : View.OnTouchListene
}
}
private fun showSceneWindow(frontCameraUri: Uri,rearCameraUri: Uri,mapScreenUri: Uri,currentItem: Int){
if(takeOverSceneWindow == null){
takeOverSceneWindow = TakeOverSceneWindow(mActivity)
}
takeOverSceneWindow?.showFloatWindow(frontCameraUri,rearCameraUri,mapScreenUri,currentItem)
}
private fun setAudio(status: Boolean){
if(status){
//开始录音
@@ -417,25 +430,6 @@ class TakeOverReasonWindow constructor(activity: Activity) : View.OnTouchListene
@SuppressLint("ClickableViewAccessibility")
override fun onTouch(v: View?, motionEvent: MotionEvent?): Boolean {
// when (motionEvent?.action) {
// MotionEvent.ACTION_DOWN -> {
// // 获取相对View的坐标即以此View左上角为原点
// mInViewX = motionEvent.x
// mInViewY = motionEvent.y
// // 获取相对屏幕的坐标,即以屏幕左上角为原点
// mInScreenX = motionEvent.rawX
// mInScreenY = motionEvent.rawY
// }
// MotionEvent.ACTION_MOVE -> {
// // 更新浮动窗口位置参数
// mInScreenX = motionEvent.rawX
// mInScreenY = motionEvent.rawY
// mWindowParams!!.x = (mInScreenX - mInViewX).toInt()
// mWindowParams!!.y = (mInScreenY - mInViewY).toInt()
// // 手指移动的时候更新小悬浮窗的位置
// mWindowManager!!.updateViewLayout(mFloatLayout, mWindowParams)
// }
// }
return true
}
@@ -457,6 +451,40 @@ class TakeOverReasonWindow constructor(activity: Activity) : View.OnTouchListene
tvTakeOverTime.text = mActivity.resources.getString(R.string.take_over_time) +
millis2String(mTakeOverRecordInfo.faultStartTime, TimeUtils.getHourMinSecondFormat())
}
//展示前向摄像头
val frontCameraPath: String = ((Environment.getExternalStorageDirectory()
.absolutePath + File.separator) +
"FrontCamera" + File.separator + millis2String(System.currentTimeMillis(), getMdFormat())
+ File.separator + mTakeOverRecordInfo.bagId) + ".png"
val frontCameraUri = Uri.parse(frontCameraPath)
ivFrontCamera.setImageURI(frontCameraUri)
//展示后向摄像头
val rearCameraPath: String = ((Environment.getExternalStorageDirectory()
.absolutePath + File.separator) +
"RearCamera" + File.separator + millis2String(System.currentTimeMillis(), getMdFormat())
+ File.separator + mTakeOverRecordInfo.bagId) + ".png"
val rearCameraUri = Uri.parse(rearCameraPath)
ivRearCamera.setImageURI(rearCameraUri)
//展示高精地图截图
val mapScreenPath: String = ((Environment.getExternalStorageDirectory()
.absolutePath + File.separator) +
"MapScreen" + File.separator + millis2String(System.currentTimeMillis(), getMdFormat())
+ File.separator + mTakeOverRecordInfo.bagId) + ".png"
val mapScreenUri = Uri.parse(mapScreenPath)
ivMapScreen.setImageURI(mapScreenUri)
//前向120°摄像头
ivFrontCamera.setOnClickListener {
showSceneWindow(frontCameraUri,rearCameraUri,mapScreenUri,0)
}
//后向120°摄像头
ivRearCamera.setOnClickListener {
showSceneWindow(frontCameraUri,rearCameraUri,mapScreenUri,1)
}
//高精地图截图
ivMapScreen.setOnClickListener {
showSceneWindow(frontCameraUri,rearCameraUri,mapScreenUri,2)
}
setWindowShowStatus(true)
}

View File

@@ -0,0 +1,113 @@
package com.zhjt.mogo_core_function_devatools.workorder
import android.annotation.SuppressLint
import android.app.Activity
import android.graphics.PixelFormat
import android.net.Uri
import android.util.DisplayMetrics
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.WindowManager
import android.widget.ImageView
import androidx.viewpager.widget.ViewPager
import com.mogo.eagle.core.utilcode.util.BarUtils
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.zhjt.mogo_core_function_devatools.R
import com.zhjt.mogo_core_function_devatools.workorder.adapter.TakeOverSceneAdapter
/**
* 场景图像查看窗口
*/
class TakeOverSceneWindow constructor(activity: Activity) {
companion object{
const val TAG = "TakeOverSceneWindow"
}
private var mActivity: Activity = activity
private var mWindowParams: WindowManager.LayoutParams? = null
private var mWindowManager: WindowManager? = null
private lateinit var mFloatLayout: View
private lateinit var vpSceneImage: ViewPager
private lateinit var ivSceneClose: ImageView
private lateinit var ivScenePrevious: ImageView
private lateinit var ivSceneNext: ImageView
private val takeOverSceneAdapter = TakeOverSceneAdapter()
private var currentIndex = 0
init {
initFloatWindow()
}
private fun initFloatWindow(){
mFloatLayout = LayoutInflater.from(mActivity).inflate(R.layout.view_take_over_scene, null) as View
initView()
initEvent()
mWindowParams = WindowManager.LayoutParams()
mWindowManager = mActivity.windowManager
mWindowParams?.let {
it.format = PixelFormat.RGBA_8888
it.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
it.gravity = Gravity.START or Gravity.TOP
it.width = WindowManager.LayoutParams.MATCH_PARENT
it.height = 1535
it.alpha = 1.0f
}
}
private fun initView(){
vpSceneImage = mFloatLayout.findViewById(R.id.vpSceneImage)
ivSceneClose = mFloatLayout.findViewById(R.id.ivSceneClose)
ivScenePrevious = mFloatLayout.findViewById(R.id.ivScenePrevious)
ivSceneNext = mFloatLayout.findViewById(R.id.ivSceneNext)
}
private fun initEvent(){
vpSceneImage.adapter =takeOverSceneAdapter
//关闭弹窗
ivSceneClose.setOnClickListener {
hideFloatWindow()
}
//前一个场景
ivScenePrevious.setOnClickListener {
if(currentIndex == 0){
ToastUtils.showShort("没有上一个场景了")
}else{
currentIndex = (currentIndex-1).coerceAtLeast(0)
vpSceneImage.currentItem = currentIndex
}
}
//后一个场景
ivSceneNext.setOnClickListener {
if(currentIndex < 2){
currentIndex = (currentIndex + 1).coerceAtMost(2)
vpSceneImage.currentItem = currentIndex
}else{
ToastUtils.showShort("没有下一个场景了")
}
}
}
@SuppressLint("SetTextI18n")
fun showFloatWindow(frontCameraUri: Uri, rearCameraUri: Uri, mapScreenUri: Uri, currentItem: Int) {
if (mFloatLayout.parent == null) {
val metrics = DisplayMetrics()
// 默认固定位置,靠屏幕右边缘的中间
mWindowManager!!.defaultDisplay.getMetrics(metrics)
mWindowParams!!.x = 0
mWindowParams!!.y = metrics.heightPixels - BarUtils.getStatusBarHeight()
mWindowManager!!.addView(mFloatLayout, mWindowParams)
takeOverSceneAdapter.setSceneUri(frontCameraUri, rearCameraUri, mapScreenUri)
currentIndex = currentItem
vpSceneImage.currentItem = currentItem
}
}
fun hideFloatWindow() {
if (mFloatLayout.parent != null){
mWindowManager!!.removeView(mFloatLayout)
}
}
}

View File

@@ -0,0 +1,69 @@
package com.zhjt.mogo_core_function_devatools.workorder.adapter
import android.net.Uri
import android.os.Environment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.viewpager.widget.PagerAdapter
import com.mogo.eagle.core.utilcode.util.TimeUtils.getMdFormat
import com.mogo.eagle.core.utilcode.util.TimeUtils.millis2String
import com.zhjt.mogo_core_function_devatools.R
import java.io.File
class TakeOverSceneAdapter: PagerAdapter() {
private lateinit var mFrontCameraUri: Uri
private lateinit var mRearCameraUri: Uri
private lateinit var mMapScreenUri: Uri
fun setSceneUri(frontCameraUri: Uri,rearCameraUri: Uri,mapScreenUri: Uri){
mFrontCameraUri = frontCameraUri
mRearCameraUri = rearCameraUri
mMapScreenUri = mapScreenUri
}
// 获取要滑动的控件的数量
override fun getCount(): Int {
return 3
}
// 来判断显示的是否是同一张图片,这里我们将两个参数相比较返回即可
override fun isViewFromObject(view: View, `object`: Any): Boolean {
return view == `object`
}
// 当要显示的图片可以进行缓存的时候,会调用这个方法进行显示图片的初始化,
// 我们将要显示的ImageView加入到ViewGroup中然后作为返回值返回即可
override fun instantiateItem(container: ViewGroup, position: Int): Any {
val inflater = LayoutInflater.from(container.context)
val view = inflater.inflate(R.layout.layout_scene_pager,container,false)
val sceneName: TextView = view.findViewById(R.id.tvSceneName)
val ivSceneImage: ImageView = view.findViewById(R.id.ivSceneImage)
when (position) {
0 -> {
sceneName.text = container.resources.getString(R.string.take_over_front_camera)
ivSceneImage.setImageURI(mFrontCameraUri)
}
1 -> {
sceneName.text = container.resources.getString(R.string.take_over_rear_camera)
ivSceneImage.setImageURI(mRearCameraUri)
}
else -> {
sceneName.text = container.resources.getString(R.string.take_over_map_screen)
ivSceneImage.setImageURI(mMapScreenUri)
}
}
container.addView(view)
return view
}
// PagerAdapter只缓存三张要显示的图片如果滑动的图片超出了缓存的范围就会调用这个方法将图片销毁
override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
container.removeView(`object` as View)
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:startColor="#00000000"
android:centerColor="#80000000"
android:endColor="#00000000"
android:angle="0"
android:gradientRadius="@dimen/dp_8"
/>
</shape>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/ivSceneImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/take_over_scene_image"
android:scaleType="fitXY"
/>
<TextView
android:id="@+id/tvSceneName"
android:layout_width="@dimen/dp_754"
android:layout_height="@dimen/dp_98"
android:layout_gravity="center_horizontal"
android:layout_marginTop="@dimen/dp_64"
android:textSize="@dimen/sp_48"
android:textColor="@color/white"
android:gravity="center"
android:background="@drawable/bg_scene_name"
/>
</FrameLayout>

View File

@@ -145,6 +145,111 @@
android:contentDescription="@string/take_over_note_audio"
/>
<TextView
android:id="@+id/tvTakeOverSceneImageTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/take_over_scene_image"
android:textSize="@dimen/sp_38"
android:textColor="@color/white"
app:layout_constraintTop_toBottomOf="@id/etNoteInput"
app:layout_constraintLeft_toLeftOf="@id/etNoteInput"
android:layout_marginTop="@dimen/dp_36"
/>
<ScrollView
android:layout_width="@dimen/dp_779"
android:layout_height="@dimen/dp_0"
app:layout_constraintTop_toBottomOf="@id/tvTakeOverSceneImageTitle"
app:layout_constraintLeft_toLeftOf="@id/tvTakeOverSceneImageTitle"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginTop="@dimen/dp_13"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/ivFrontCamera"
android:layout_width="@dimen/dp_779"
android:layout_height="@dimen/dp_422"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:contentDescription="@string/take_over_front_camera"
android:scaleType="fitXY"
/>
<TextView
android:layout_width="@dimen/dp_779"
android:layout_height="@dimen/dp_72"
app:layout_constraintLeft_toLeftOf="@id/ivFrontCamera"
app:layout_constraintRight_toRightOf="@id/ivFrontCamera"
app:layout_constraintBottom_toBottomOf="@id/ivFrontCamera"
android:background="#66000000"
android:text="@string/take_over_front_camera"
android:textColor="@color/white"
android:textSize="@dimen/sp_30"
android:gravity="center"
/>
<ImageView
android:id="@+id/ivRearCamera"
android:layout_width="@dimen/dp_779"
android:layout_height="@dimen/dp_422"
app:layout_constraintTop_toBottomOf="@id/ivFrontCamera"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:contentDescription="@string/take_over_rear_camera"
android:layout_marginTop="@dimen/dp_13"
android:scaleType="fitXY"
/>
<TextView
android:layout_width="@dimen/dp_779"
android:layout_height="@dimen/dp_72"
app:layout_constraintLeft_toLeftOf="@id/ivRearCamera"
app:layout_constraintRight_toRightOf="@id/ivRearCamera"
app:layout_constraintBottom_toBottomOf="@id/ivRearCamera"
android:background="#66000000"
android:text="@string/take_over_rear_camera"
android:textColor="@color/white"
android:textSize="@dimen/sp_30"
android:gravity="center"
/>
<ImageView
android:id="@+id/ivMapScreen"
android:layout_width="@dimen/dp_779"
android:layout_height="@dimen/dp_422"
app:layout_constraintTop_toBottomOf="@id/ivRearCamera"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:contentDescription="@string/take_over_map_screen"
android:layout_marginTop="@dimen/dp_13"
android:layout_marginBottom="@dimen/dp_160"
android:scaleType="fitXY"
/>
<TextView
android:layout_width="@dimen/dp_779"
android:layout_height="@dimen/dp_72"
app:layout_constraintLeft_toLeftOf="@id/ivMapScreen"
app:layout_constraintRight_toRightOf="@id/ivMapScreen"
app:layout_constraintBottom_toBottomOf="@id/ivMapScreen"
android:background="#66000000"
android:text="@string/take_over_map_screen"
android:textColor="@color/white"
android:textSize="@dimen/sp_30"
android:gravity="center"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
<TextView
android:id="@+id/tvTakeOverSave"
android:layout_width="@dimen/dp_380"

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.viewpager.widget.ViewPager
android:id="@+id/vpSceneImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<ImageView
android:id="@+id/ivSceneClose"
android:layout_width="@dimen/dp_170"
android:layout_height="@dimen/dp_170"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:src="@drawable/icon_scene_close"
android:contentDescription="@string/take_over_close_scene"
android:layout_marginBottom="@dimen/dp_110"
/>
<ImageView
android:id="@+id/ivScenePrevious"
android:layout_width="@dimen/dp_170"
android:layout_height="@dimen/dp_170"
app:layout_constraintTop_toTopOf="@id/ivSceneClose"
app:layout_constraintBottom_toBottomOf="@id/ivSceneClose"
app:layout_constraintRight_toLeftOf="@id/ivSceneClose"
android:src="@drawable/icon_scene_left"
android:layout_marginRight="@dimen/dp_108"
android:contentDescription="@string/take_over_previous_scene"
/>
<ImageView
android:id="@+id/ivSceneNext"
android:layout_width="@dimen/dp_170"
android:layout_height="@dimen/dp_170"
app:layout_constraintTop_toTopOf="@id/ivSceneClose"
app:layout_constraintBottom_toBottomOf="@id/ivSceneClose"
app:layout_constraintLeft_toRightOf="@id/ivSceneClose"
android:src="@drawable/icon_scene_right"
android:layout_marginLeft="@dimen/dp_108"
android:contentDescription="@string/take_over_next_scene"
/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -66,6 +66,13 @@
<string name="fault_note_supplement">(选填)</string>
<string name="take_over_note_input">手动输入</string>
<string name="take_over_note_audio">补充描述语音输入</string>
<string name="take_over_scene_image">场景图像</string>
<string name="take_over_front_camera">前向120°摄像头</string>
<string name="take_over_rear_camera">后向120°摄像头</string>
<string name="take_over_map_screen">高精地图截图</string>
<string name="take_over_previous_scene">上一个场景</string>
<string name="take_over_close_scene">关闭场景</string>
<string name="take_over_next_scene">下一个场景</string>
<string name="fault_report">上报</string>
<string name="take_over_save">保存</string>
<string name="take_over_cancel">取消</string>

View File

@@ -18,6 +18,7 @@ import com.mogo.eagle.core.function.hmi.R
import com.mogo.eagle.core.utilcode.kotlin.onClick
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.Logger
import com.mogo.eagle.core.utilcode.util.SoundPoolUtils
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
import com.zhjt.mogo_core_function_devatools.status.StatusManager
import com.zhjt.mogo_core_function_devatools.status.entity.AcceleratorStatus
@@ -30,6 +31,7 @@ import com.zhjt.mogo_core_function_devatools.status.entity.IAutopilotBeforeLaunc
import com.zhjt.mogo_core_function_devatools.status.entity.Status
import com.zhjt.mogo_core_function_devatools.status.entity.SteerStatus
import kotlinx.android.synthetic.main.view_start_autopilot_status.view.fSMStatusLayout
import kotlinx.android.synthetic.main.view_start_autopilot_status.view.ivFsmDemoModeError
import kotlinx.android.synthetic.main.view_start_autopilot_status.view.iv_accelerator
import kotlinx.android.synthetic.main.view_start_autopilot_status.view.iv_brake
import kotlinx.android.synthetic.main.view_start_autopilot_status.view.iv_double_flash
@@ -68,7 +70,8 @@ class StartAutoPilotStatusView @JvmOverloads constructor(
}
private val hasFSM by lazy { AtomicBoolean(true) }
//是否进行了语音提示当开启美化模式后若fsm输出自车处于安全停车状态中提示音提示一次
private var isAlreadyPrompted: Boolean = false
init {
LayoutInflater.from(context).inflate(R.layout.view_start_autopilot_status, this, true)
@@ -87,9 +90,11 @@ class StartAutoPilotStatusView @JvmOverloads constructor(
CallerLogger.i(TAG, "changeStatusContainer 切换展示hasFSM=$hasFSMModule")
if (hasFSMModule) {
fSMStatusLayout?.visibility = View.VISIBLE
ivFsmDemoModeError?.visibility = View.GONE
withoutFSMStatusLayout?.visibility = View.GONE
} else {
fSMStatusLayout?.visibility = View.GONE
ivFsmDemoModeError?.visibility = View.GONE
withoutFSMStatusLayout?.visibility = View.VISIBLE
}
}
@@ -104,11 +109,6 @@ class StartAutoPilotStatusView @JvmOverloads constructor(
}
hasFSM.set(newHasFSM)
if (FunctionBuildConfig.isDemoMode && status.isException()) {
// 美化模式下如果是异常的,修改成正常的
status.state = FSMStateCode.ExistNormal
}
when (status.state) {
FSMStateCode.UnKnown -> {
fSMStatusLayout?.setOnClickListener(null)
@@ -118,6 +118,8 @@ class StartAutoPilotStatusView @JvmOverloads constructor(
R.drawable.icon_fsm_status_bg_unknown
)
)
ivFsmDemoModeError?.visibility = View.GONE
isAlreadyPrompted = false
}
FSMStateCode.NotExist -> {
@@ -128,6 +130,8 @@ class StartAutoPilotStatusView @JvmOverloads constructor(
R.drawable.icon_fsm_status_bg_unknown
)
)
ivFsmDemoModeError?.visibility = View.GONE
isAlreadyPrompted = false
}
FSMStateCode.ExistNormal -> {
@@ -138,18 +142,41 @@ class StartAutoPilotStatusView @JvmOverloads constructor(
R.drawable.icon_fsm_status_bg_normal
)
)
ivFsmDemoModeError?.visibility = View.GONE
isAlreadyPrompted = false
}
FSMStateCode.ExistError -> {
fSMStatusLayout?.onClick {
CallerHmiManager.showFSMExceptionStatusWindow(status.descList)
}
fSMStatusLayout?.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.icon_fsm_status_bg_error
if(FunctionBuildConfig.isDemoMode){
fSMStatusLayout?.setOnClickListener(null)
fSMStatusLayout?.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.icon_fsm_status_bg_normal
)
)
)
ivFsmDemoModeError?.visibility = View.VISIBLE
if(!isAlreadyPrompted){
try {
SoundPoolUtils.getSoundPool().playSoundWithRedId(context,R.raw.weak_net_tips)
}catch (e: Exception){
e.printStackTrace()
}
isAlreadyPrompted = true
}
}else{
fSMStatusLayout?.onClick {
CallerHmiManager.showFSMExceptionStatusWindow(status.descList)
}
fSMStatusLayout?.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.icon_fsm_status_bg_error
)
)
ivFsmDemoModeError?.visibility = View.GONE
isAlreadyPrompted = false
}
}
}
notifyStatus(status.isException())

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -194,7 +194,6 @@
app:layout_constraintBottom_toBottomOf="@+id/tvADVersion"
app:layout_constraintRight_toRightOf="@+id/tvCarExit"
app:layout_constraintTop_toTopOf="@+id/tvADVersion"
android:visibility="gone"
/>
<TextView

View File

@@ -15,6 +15,19 @@
android:visibility="visible"
tools:visibility="visible"/>
<ImageView
android:id="@+id/ivFsmDemoModeError"
android:layout_width="@dimen/dp_30"
android:layout_height="@dimen/dp_30"
android:src="@drawable/icon_fsm_demo_mode_error"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginStart="@dimen/dp_19"
android:layout_marginBottom="@dimen/dp_39"
android:contentDescription="@string/fsm_demo_mode_error"
android:visibility="gone"
/>
<LinearLayout
android:id="@+id/withoutFSMStatusLayout"
android:layout_width="match_parent"

View File

@@ -267,4 +267,6 @@
<string name="ota_result_fail_tip">请联系管理员</string>
<string name="ota_result_close">关闭</string>
<string name="fsm_demo_mode_error">FSM美化模式状态下异常标识</string>
</resources>

View File

@@ -11,6 +11,22 @@ import perception.FusionTrafficLightOuterClass
*/
interface IMoGoAutopilotIdentifyListener {
/**
* 判断是否有车龙
*/
fun isLongVehicleQueue(
type: Int,
polygon: List<MessagePad.Location>?
): Boolean {
// 检查 type 是否为 707 表示NED陈数据
val isRoadCongested = type == 707
// 检查 polygon 是否不为空且个数大于 1
val hasEnoughPolygonPoints = (polygon?.size ?: 0) > 1
// 同时满足两个条件
return isRoadCongested && hasEnoughPolygonPoints
}
/**
* 识别交通元素数据发生更新
*

View File

@@ -0,0 +1,82 @@
syntax = "proto3";
package mogo.nde.service.dto.protocol;
option java_package = "mogo.nde.service.dto.protocol";
//TODO 仅做备份使用
// 鹰眼推荐车道
message AutoSteerInfo {
/**
* 道路Id
*/
string roadId = 1;
/**
* 生成时间
*/
int64 systemTime = 2;
/**
* 具体内容
*/
repeated RecommendInfo recommendInfo = 3;
}
message RecommendInfo{
/**
* 车龙id,如果有车龙的话,没有不传
*/
string uuid = 1;
/**
* 车道号
*/
int32 laneNum = 2;
/**
* 车龙车辆id集合若无车龙则为空集合
*/
repeated string uuids = 3;
/**
* 车辆轨迹,有车龙有值
*/
repeated Point2D points = 4;
/**
* 车道线轨迹,车道中心线与停止线交点
*/
repeated Point2D lanePoints = 5;
/**
* 车龙长度
*/
double length = 6;
/**
* 是否是建议车道
*/
bool suggestedLanes = 7;
/**
车道类型
直行 201
直行或左转 202
直行或右转 203
直行或掉头 204
左转 205
左转或掉头 206
左弯或向左合流 207
右转 208
右转或向右合流209
左右转弯 210
掉头211
禁止左转212
禁止右转213
禁止掉头214
直行或左转或右转215
直行或掉头或左转216
右转或掉头217
禁止右转或向右合流218
*/
int32 arrowType = 8;
}
//2维点
message Point2D {
// 经度
double lon = 1;
// 维度
double lat = 2;
}

View File

@@ -317,7 +317,9 @@ message TrackedObject
uint32 drawLevel = 12; //危险等级 1 绿,2 黄,3 红
double driverTime = 13; //驱动感知时间, abandoned
repeated TrackedSource tracked_source = 14;
repeated Location polygon = 15;
repeated Location polygon = 15;//当 type == 707 时
//车龙轨迹对应NED原始PB EagleEyeRecommend.proto中的lanePoints字段原始PB中那个points和lanePoints区别points字段里面是车龙上的车辆中心点练起来的线可能歪歪扭扭的。lanePoints字段里面是车龙所在车道的车道中心线连续更平滑
//此字段 size > 1 时表示有车龙轨迹,有车龙时仅longitude和latitude赋值 size == 1 时表示无车龙
geometry.Point center = 16;
AdditionalAttribute add_attribute = 17; //事件类型
double angle = 18; //相对于自车x轴的角度左正右负
@@ -326,7 +328,19 @@ message TrackedObject
string camera_ip = 21; //来源IP
uint64 detect_start_time = 22; //V2N事件生成UTC时间单位毫秒
string v2x_uuid = 23; //V2X目标uuid
reserved 24 to 100;
//对应NED原始PB EagleEyeRecommend.proto中的uuid字段
//与NED原始数据稍有不同。NED原石数据无车龙时不传参数域控融合后的的数据有车龙是id样式2b9564b8-1b7f-4533-9c66-b472780c986a 无车龙id样式是数字1、2、3、4、……
string roadId = 24; //V2N车龙道路ID 对应NED原始PB EagleEyeRecommend.proto中的roadId字段
int32 laneNum = 25; //V2N车龙彻车道号 对应NED原始PB EagleEyeRecommend.proto中的laneNum字段
bool suggestedLanes = 26; //V2N车龙是否是建议车道 对应NED原始PB EagleEyeRecommend.proto中的suggestedLanes字段
int32 arrowType = 27; //V2N车龙车道类型
//对应NED原始PB EagleEyeRecommend.proto中的arrowType字段
//目前除以下注释里面的值,其他的数字都没有意义
//直行 201直行或左转 202直行或右转 203直行或掉头 204
//左转 205左转或掉头 206左弯或向左合流 207右转 208右转或向右合流 209
//左右转弯 210掉头 211禁止左转 212禁止右转 213禁止掉头 214直行或左转或右转 215
//直行或掉头或左转 216右转或掉头 217禁止右转或向右合流 218
reserved 28 to 100;
string strUuid = 101;//String类型车辆ID
}

View File

@@ -5,13 +5,11 @@ import androidx.annotation.NonNull;
import com.zhjt.mogo.adas.common.MessageType;
import com.zhjt.mogo.adas.data.bean.ReceivedAck;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
import mogo.telematics.pad.MessagePad;
@@ -22,8 +20,8 @@ public class ReceivedAckManager {
private static final String TAG = ReceivedAckManager.class.getSimpleName();
private volatile Timer timer;
private final List<ReceivedAck> list = Collections.synchronizedList(new ArrayList<>());
private final AtomicBoolean isSupport = new AtomicBoolean(false);//是否支持回执功能
private final ConcurrentLinkedQueue<ReceivedAck> queue = new ConcurrentLinkedQueue<>();
private final AtomicInteger isSupport = new AtomicInteger(-1);//是否支持回执功能 -1未知 0不支持 1支持
private OnReceivedAckListener listener;
public void setListener(OnReceivedAckListener listener) {
@@ -47,10 +45,10 @@ public class ReceivedAckManager {
}
public void setSupport(int version) {
isSupport.set(version >= 30800);
CupidLogUtils.log(TAG, version + " 是否支持回执功能=" + isSupport.get());
if (!isSupport.get()) {
stop();
isSupport.set(version >= 30800 ? 1 : 0);
CupidLogUtils.log(TAG, version + " 是否支持回执功能=" + (isSupport.get() == 1));
if (isSupport.get() != 1) {
destroy();
}
}
@@ -63,11 +61,13 @@ public class ReceivedAckManager {
* @param sendData
*/
public void addNeedAckData(long sendTime, long msgId, MessageType messageType, byte[] sendData) {
if (isSupport.get()) {
if (isSupport.get() == -1 || isSupport.get() == 1) {
queue.add(new ReceivedAck(sendTime, msgId, messageType, sendData));
}
if (isSupport.get() == 1) {
start();
list.add(new ReceivedAck(sendTime, msgId, messageType, sendData));
} else {
stop();
} else if (isSupport.get() == 0) {
destroy();
}
}
@@ -78,8 +78,13 @@ public class ReceivedAckManager {
* @param receivedAck 回执数据
*/
public void receiveReceivedAck(long time, MessagePad.ReceivedAck receivedAck) {
if (isSupport.get() != 1) {
isSupport.set(1);
CupidLogUtils.log(TAG, "当前域控版本支持回执功能");
start();
}
int count = receivedAck.getMsgidsCount();
if (count == 0 || list.isEmpty()) {
if (count == 0 || queue.isEmpty()) {
if (listener != null) {
ReceivedAck ack = new ReceivedAck(0, 0, MessageType.TYPE_DEFAULT, null);
ack.setStatus(count == 0 ? ReceivedAck.Status.RECEIVED_ACK_DATA_ERROR : ReceivedAck.Status.WAITING_RECEIVED_ACK_LIST_EMPTY);
@@ -89,7 +94,8 @@ public class ReceivedAckManager {
}
return;
}
Iterator<ReceivedAck> iterator = list.iterator();
Iterator<ReceivedAck> iterator = queue.iterator();
while (iterator.hasNext()) {
ReceivedAck ack = iterator.next();
for (int i = 0; i < count; i++) {
@@ -114,9 +120,9 @@ public class ReceivedAckManager {
timer.schedule(new TimerTask() {
@Override
public void run() {
if (!list.isEmpty()) {
if (!queue.isEmpty()) {
long time = System.currentTimeMillis();
Iterator<ReceivedAck> iterator = list.iterator();
Iterator<ReceivedAck> iterator = queue.iterator();
while (iterator.hasNext()) {
ReceivedAck ack = iterator.next();
long t = ack.getMessageType().timeoutMillis;
@@ -136,8 +142,13 @@ public class ReceivedAckManager {
}
public void stop() {
if (!list.isEmpty()) {
list.clear();
destroy();
isSupport.set(-1);
}
private void destroy() {
if (!queue.isEmpty()) {
queue.clear();
}
if (timer != null) {
timer.cancel();