[Sweeper Cloud] feat: 增加 子任务开始/结束 时的高精地图Marker ;

This commit is contained in:
aibingbing
2023-07-21 18:55:42 +08:00
parent 99f899aa44
commit 91e6f0fab5
2 changed files with 219 additions and 54 deletions

View File

@@ -55,9 +55,9 @@ class SweeperConst {
const val EVENT_PARAM_UNABLE_START_REASON = "unable_start_reason";
/**
* 订单起终点Marker类型
* 子任务起终点Marker类型
*/
const val TYPE_MARKER_SWEEPER_ORDER = "TYPE_MARKER_SWEEPER_ORDER"
const val TYPE_MARKER_SWEEPER_SUBTASK_START_END = "TYPE_MARKER_SWEEPER_SUBTASK_START_END"
const val TIMER_START_AUTOPILOT_INTERVAL = 20 * 1000L

View File

@@ -7,13 +7,18 @@ import chassis.ChassisStatesOuterClass
import com.amap.api.maps.model.LatLng
import com.mogo.eagle.core.data.map.MogoLocation
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener.Companion.STATUS_AUTOPILOT_ENABLE
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.mogo.map.overlay.core.Level
import com.mogo.map.overlay.point.Point
import com.mogo.och.common.module.utils.OCHThreadPoolManager
import com.mogo.och.common.module.voice.VoiceNotice.showNotice
import com.mogo.och.sweepercloud.R
import com.mogo.och.sweepercloud.bean.SweeperRoutePlanningUpdateReqBean
import com.mogo.och.sweepercloud.callback.SweeperCloudDialogClickListener
import com.mogo.och.sweepercloud.constant.SweeperConst.Companion.TYPE_MARKER_SWEEPER_SUBTASK_START_END
import com.mogo.och.sweepercloud.database.MyDataBase
import com.mogo.och.sweepercloud.presenter.SweeperPresenter
import com.mogo.och.sweepercloud.ui.dialog.SweeperCloudDialog
@@ -59,7 +64,11 @@ class SweeperFragment : BaseSweeperTabFragment<SweeperFragment?, SweeperPresente
private var mSubTaskType: TaskModel = TaskModel.DEFAULT_MODEL //1:自动驾驶子任务 2人工驾驶子任务 -1:未知任务类型
private var mCurrentRunningSubTaskInfo: SubTaskInfo? = null//当前正在执行的子任务
private var mCurrentSuspendSubTaskInfo: SubTaskInfo? = null//当前暂停的子任务
private val mLoadingDialog: SweeperCloudLoadingDialog by lazy { SweeperCloudLoadingDialog(requireContext()) }
private val mLoadingDialog: SweeperCloudLoadingDialog by lazy {
SweeperCloudLoadingDialog(
requireContext()
)
}
private var mDialog: SweeperCloudDialog? = null
override fun getTagName(): String {
@@ -119,9 +128,14 @@ class SweeperFragment : BaseSweeperTabFragment<SweeperFragment?, SweeperPresente
//前置条件 (1)必须处于人工驾驶状态 2必须有正在执行的子任务且子任务类型为自动驾驶子任务 才能请求云端进入自驾
mCurrentRunningSubTaskInfo?.let {
if (mPresenter?.autopilotState == STATUS_AUTOPILOT_ENABLE
&& it.taskModel == TaskModel.AUTO) {
&& it.taskModel == TaskModel.AUTO
) {
mLoadingDialog.showLoading()
mPresenter?.sendSweeperAutopilotBootable(mTaskInfo?.taskId, it.subTaskId, it.lineId.toLong())
mPresenter?.sendSweeperAutopilotBootable(
mTaskInfo?.taskId,
it.subTaskId,
it.lineId.toLong()
)
}
}
}
@@ -184,7 +198,10 @@ class SweeperFragment : BaseSweeperTabFragment<SweeperFragment?, SweeperPresente
/**
* 设置云端任务信息
*/
fun onSweeperCloudTask(messageType: SweeperCloudTask.MessageType, taskInfo: SweeperTask.TaskInfo?) {
fun onSweeperCloudTask(
messageType: SweeperCloudTask.MessageType,
taskInfo: SweeperTask.TaskInfo?
) {
this.mTaskInfo = taskInfo
this.mSubMutableList = taskInfo?.subListList
CallerLogger.d(SceneConstant.M_SWEEPER + TAG, taskInfo?.let { printMessage(it) })
@@ -206,7 +223,10 @@ class SweeperFragment : BaseSweeperTabFragment<SweeperFragment?, SweeperPresente
mPresenter?.isHasTaskInfo(true)
// 默认发送接收到消息的ACK回执
mPresenter?.sendSweeperStartTaskResp(taskInfo.taskId, SweeperTask.StartTaskCode.RECEIVED)
mPresenter?.sendSweeperStartTaskResp(
taskInfo.taskId,
SweeperTask.StartTaskCode.RECEIVED
)
if (taskInfo.isPop) {
showReceivedBigTaskDialog()
@@ -221,7 +241,11 @@ class SweeperFragment : BaseSweeperTabFragment<SweeperFragment?, SweeperPresente
/**
* 根据云端同步的子任务状态,更新列表中任务状态
*/
fun onSweeperUpdateSubTaskStatus(taskId: String, subTaskId: String, subTaskStatus: SweeperCommon.TaskStatus) {
fun onSweeperUpdateSubTaskStatus(
taskId: String,
subTaskId: String,
subTaskStatus: SweeperCommon.TaskStatus
) {
mLoadingDialog.hideLoading()
updateSubTaskInfo(taskId, subTaskId, subTaskStatus)
}
@@ -229,7 +253,11 @@ class SweeperFragment : BaseSweeperTabFragment<SweeperFragment?, SweeperPresente
/**
* 子任务确认时,更新子任务信息
*/
private fun updateSubTaskInfo(taskId: String, subTaskId: String, subTaskStatus: SweeperCommon.TaskStatus) {
private fun updateSubTaskInfo(
taskId: String,
subTaskId: String,
subTaskStatus: SweeperCommon.TaskStatus
) {
mTaskInfo?.let {
//如果云端要更新的任务和本地缓存任务不是同一个,在无法更新子任务状态
if (taskId != it.taskId) {
@@ -244,6 +272,10 @@ class SweeperFragment : BaseSweeperTabFragment<SweeperFragment?, SweeperPresente
mCurrentRunningSubTaskInfo = subBuilder.build()
//更新当前正在执行的任务状态
updateCurrentSubTaskInfo(index + 1)
// 先移除在添加 起终点 Marker
removeHDMapMarkerBySubTask(subTaskList[index])
addHDMapMarkerBySubTask(subTaskList[index])
} else {
mCurrentRunningSubTaskInfo = null
}
@@ -257,6 +289,14 @@ class SweeperFragment : BaseSweeperTabFragment<SweeperFragment?, SweeperPresente
//已完成的计入任务进度,未完成的不计入
ToastUtils.showLong("任务完成")
showNotice("任务完成")
removeHDMapMarkerBySubTask(subTaskList[index])
}
// 其他异常结束时也需要remove marker
if (subTaskStatus == SweeperCommon.TaskStatus.ABNORMAL ||
subTaskStatus == SweeperCommon.TaskStatus.CANCEL
) {
removeHDMapMarkerBySubTask(subTaskList[index])
}
val builder = it.toBuilder()
builder.setSubList(index, subBuilder.build())
@@ -272,7 +312,11 @@ class SweeperFragment : BaseSweeperTabFragment<SweeperFragment?, SweeperPresente
/**
* 云端请求结束大任务
*/
fun onSweeperCloudTaskStop(taskId: String, stopTaskType: SweeperTaskStop.StopTaskType, isPop: Boolean) {
fun onSweeperCloudTaskStop(
taskId: String,
stopTaskType: SweeperTaskStop.StopTaskType,
isPop: Boolean
) {
mTaskInfo?.let {
//如果云端要更新的任务和本地缓存任务不是同一个,在无法结束任务
if (taskId != it.taskId) {
@@ -289,9 +333,14 @@ class SweeperFragment : BaseSweeperTabFragment<SweeperFragment?, SweeperPresente
/**
* 结束任务弹窗处理
*/
private fun sweeperCloudTaskStopDialog(taskId: String, stopTaskType: SweeperTaskStop.StopTaskType, taskInfo: SweeperTask.TaskInfo) {
private fun sweeperCloudTaskStopDialog(
taskId: String,
stopTaskType: SweeperTaskStop.StopTaskType,
taskInfo: SweeperTask.TaskInfo
) {
mLoadingDialog.hideLoading()
val timeoutHintString: String = SweeperCloudTaskUtils.getTimeSpentString(taskInfo.taskEndTime)
val timeoutHintString: String =
SweeperCloudTaskUtils.getTimeSpentString(taskInfo.taskEndTime)
//数据重复导致连续弹窗
if (mDialog != null && mDialog!!.isShowing) {
return
@@ -361,26 +410,30 @@ class SweeperFragment : BaseSweeperTabFragment<SweeperFragment?, SweeperPresente
* 大任务异常结束弹窗(异常 / 取消)
*/
private fun sweeperCloudTaskExceptionEndDialog(isCancel: Boolean): SweeperCloudDialog? {
return createSweeperTaskExceptionEndDialog(context, object : SweeperCloudDialogClickListener {
override fun onConfirm() {
return createSweeperTaskExceptionEndDialog(
context,
object : SweeperCloudDialogClickListener {
override fun onConfirm() {
// ToastUtils.showLong("任务已结束")
// resetTaskInfoPanel()
}
}
override fun onRefuseOrEnd() {
override fun onRefuseOrEnd() {
}
}
override fun onCountDownStop() {
override fun onCountDownStop() {
// ToastUtils.showLong("任务已结束")
// resetTaskInfoPanel()
}
}
override fun onNext() {
override fun onNext() {
}
}
}, isCancel)
},
isCancel
)
}
/**
@@ -397,17 +450,19 @@ class SweeperFragment : BaseSweeperTabFragment<SweeperFragment?, SweeperPresente
//大任务处于取消状态/异常结束/正常结束 时都代表大任务结束了,任务列表切换为无任务列表状态
if (bigTaskStatus == SweeperCommon.TaskStatus.CANCEL
|| bigTaskStatus == SweeperCommon.TaskStatus.ABNORMAL
|| bigTaskStatus == SweeperCommon.TaskStatus.FINISHED) {
|| bigTaskStatus == SweeperCommon.TaskStatus.FINISHED
) {
mPresenter?.isHasTaskInfo(false)
//数据重复导致连续弹窗
if (mDialog != null && mDialog!!.isShowing) {
return
}
mDialog = if (bigTaskStatus == SweeperCommon.TaskStatus.CANCEL
|| bigTaskStatus == SweeperCommon.TaskStatus.ABNORMAL)
sweeperCloudTaskExceptionEndDialog(bigTaskStatus == SweeperCommon.TaskStatus.CANCEL)
else
sweeperCloudTaskNormalEndDialog()
|| bigTaskStatus == SweeperCommon.TaskStatus.ABNORMAL
)
sweeperCloudTaskExceptionEndDialog(bigTaskStatus == SweeperCommon.TaskStatus.CANCEL)
else
sweeperCloudTaskNormalEndDialog()
mDialog?.show()
showNotice("任务已结束")
@@ -421,7 +476,8 @@ class SweeperFragment : BaseSweeperTabFragment<SweeperFragment?, SweeperPresente
mTaskInfo = builder.build()
getCurrentTaskView().setData(mTaskInfo, getCurrentRunningSubTaskPosition())
} else if (it.taskStatus == SweeperCommon.TaskStatus.SUSPENDED
&& bigTaskStatus == SweeperCommon.TaskStatus.RUNNING) { //恢复
&& bigTaskStatus == SweeperCommon.TaskStatus.RUNNING
) { //恢复
showNotice("任务已恢复")
ToastUtils.showLong("任务已恢复")
@@ -437,7 +493,11 @@ class SweeperFragment : BaseSweeperTabFragment<SweeperFragment?, SweeperPresente
/**
* 云端同步 暂停/恢复 大任务状态
*/
fun onSweeperCloudBigTaskSuspendOrResume(taskId: String, actionType: SweeperTaskCloudSuspendResume.ActionType, isPop:Boolean) {
fun onSweeperCloudBigTaskSuspendOrResume(
taskId: String,
actionType: SweeperTaskCloudSuspendResume.ActionType,
isPop: Boolean
) {
//隐藏loading
mLoadingDialog.hideLoading()
mTaskInfo?.let {
@@ -446,7 +506,10 @@ class SweeperFragment : BaseSweeperTabFragment<SweeperFragment?, SweeperPresente
return
}
// 发送接收到信息的ACK回执
mPresenter?.sendSweeperSuspendResumeTaskResp(taskId, SweeperTaskCloudSuspendResume.Code.RECEIVED)
mPresenter?.sendSweeperSuspendResumeTaskResp(
taskId,
SweeperTaskCloudSuspendResume.Code.RECEIVED
)
if (isPop) {
//数据重复导致连续弹窗
if (mDialog != null && mDialog!!.isShowing) {
@@ -457,18 +520,22 @@ class SweeperFragment : BaseSweeperTabFragment<SweeperFragment?, SweeperPresente
mDialog = sweeperCloudTaskSuspendDialog()
showNotice("云端暂停任务,注意车辆即将停车!")
}
else -> {
mDialog = sweeperCloudTaskResumeDialog()
var ttsString = "云端恢复任务,注意车辆即将启动!"
mCurrentSuspendSubTaskInfo?.also { suspendSub ->
val isAutoPoilotState = mPresenter?.autopilotState == STATUS_AUTOPILOT_ENABLE
val isAutoPoilotState =
mPresenter?.autopilotState == STATUS_AUTOPILOT_ENABLE
when {
suspendSub.taskModel == TaskModel.MANUAL -> {
ttsString = "云端恢复任务,请继续手动驾驶完成任务!"
}
suspendSub.taskModel == TaskModel.AUTO && isAutoPoilotState -> {
ttsString = "云端恢复任务,注意车辆即将启动!"
}
suspendSub.taskModel == TaskModel.AUTO && !isAutoPoilotState -> {
ttsString = "云端恢复任务,请到达合适的位置后开启自动驾驶!"
}
@@ -485,7 +552,11 @@ class SweeperFragment : BaseSweeperTabFragment<SweeperFragment?, SweeperPresente
/**
* pad请求云端进入自动驾驶回调
*/
fun onSweeperCloudAutopilotBootable(taskId: String, subTaskId: String, isBootableResp: SweeperBootable.IsBootableResp) {
fun onSweeperCloudAutopilotBootable(
taskId: String,
subTaskId: String,
isBootableResp: SweeperBootable.IsBootableResp
) {
mLoadingDialog.hideLoading()
//如果云端要更新的任务和本地缓存任务不是同一个,在无法进行任务列表状态更新
mTaskInfo?.let {
@@ -517,6 +588,7 @@ class SweeperFragment : BaseSweeperTabFragment<SweeperFragment?, SweeperPresente
setShowCurrentTaskPanelView(false)
mTaskInfo = null
mCurrentRunningSubTaskInfo = null
mCurrentSuspendSubTaskInfo = null
mSubMutableList = null
mSubTaskType = TaskModel.DEFAULT_MODEL
setTaskProgress("0")
@@ -585,7 +657,11 @@ class SweeperFragment : BaseSweeperTabFragment<SweeperFragment?, SweeperPresente
val subInfo = getSubTaskInfoBySubId(subTaskId)
subInfo?.let {
// 发送接收到消息的ACK回执
mPresenter?.sendSweeperTaskConfirmResp(taskId, subTaskId, SweeperTaskConfirm.TaskConfirmCode.RECEIVED)
mPresenter?.sendSweeperTaskConfirmResp(
taskId,
subTaskId,
SweeperTaskConfirm.TaskConfirmCode.RECEIVED
)
updateSubTaskInfo(taskId, subTaskId, SweeperCommon.TaskStatus.RUNNING)
if (isPop) {
@@ -597,7 +673,11 @@ class SweeperFragment : BaseSweeperTabFragment<SweeperFragment?, SweeperPresente
/**
* 云控下发子任务确认弹窗
*/
private fun showSubTaskConfirmDialog(taskId: String, subTaskId: String, subTaskInfo: SubTaskInfo) {
private fun showSubTaskConfirmDialog(
taskId: String,
subTaskId: String,
subTaskInfo: SubTaskInfo
) {
mLoadingDialog.hideLoading()
if (mTaskInfo == null) return
if (mTaskInfo?.taskId != taskId) return
@@ -605,33 +685,34 @@ class SweeperFragment : BaseSweeperTabFragment<SweeperFragment?, SweeperPresente
if (mDialog != null && mDialog!!.isShowing) {
return
}
mDialog = createConfirmStartSubTaskDialog(context, object : SweeperCloudDialogClickListener {
override fun onConfirm() {
mDialog =
createConfirmStartSubTaskDialog(context, object : SweeperCloudDialogClickListener {
override fun onConfirm() {
// //ToastUtils.showLong("确认")
// mPresenter?.sendSweeperTaskConfirmResp(taskId, subTaskId, SweeperTaskConfirm.TaskConfirmCode.MANUAL_CONFIRM)
// //mPresenter?.setPreLineId(-1)
// updateSubTaskInfo(taskId, subTaskId, SweeperCommon.TaskStatus.RUNNING)
// mLoadingDialog.showLoading()
}
}
override fun onRefuseOrEnd() {
override fun onRefuseOrEnd() {
// //ToastUtils.showLong("结束")
// mPresenter?.sendSweeperTaskConfirmResp(taskId, subTaskId, SweeperTaskConfirm.TaskConfirmCode.MANUAL_REFUSE_ALL)
// mLoadingDialog.showLoading()
}
}
override fun onCountDownStop() {
override fun onCountDownStop() {
// //ToastUtils.showLong("倒计时结束")
// mPresenter?.sendSweeperTaskConfirmResp(taskId, subTaskId, SweeperTaskConfirm.TaskConfirmCode.OVER_TIME)
// mLoadingDialog.showLoading()
}
}
override fun onNext() {
override fun onNext() {
// //ToastUtils.showLong("下一个")
// mPresenter?.sendSweeperTaskConfirmResp(taskId, subTaskId, SweeperTaskConfirm.TaskConfirmCode.MANUAL_REFUSE_SINGLE)
// mLoadingDialog.showLoading()
}
}, subTaskInfo)
}
}, subTaskInfo)
mDialog?.show()
if (subTaskInfo.taskModel == TaskModel.MANUAL) {
showNotice("请确认并执行子任务")
@@ -650,8 +731,9 @@ class SweeperFragment : BaseSweeperTabFragment<SweeperFragment?, SweeperPresente
if (mDialog != null && mDialog!!.isShowing) {
return
}
mDialog = createReceivedBigTaskInfoDialog(context, object : SweeperCloudDialogClickListener {
override fun onConfirm() {
mDialog =
createReceivedBigTaskInfoDialog(context, object : SweeperCloudDialogClickListener {
override fun onConfirm() {
// ToastUtils.showLong("确认")
// mPresenter?.sendSweeperStartTaskResp(it.taskId, SweeperTask.StartTaskCode.MANUAL_CONFIRM)
// setShowCurrentTaskPanelView(true)
@@ -659,26 +741,26 @@ class SweeperFragment : BaseSweeperTabFragment<SweeperFragment?, SweeperPresente
// mLoadingDialog.showLoading()
// addTaskData()
// mPresenter?.isHasTaskInfo(true)
}
}
override fun onRefuseOrEnd() {
override fun onRefuseOrEnd() {
// ToastUtils.showLong("拒绝")
// mPresenter?.sendSweeperStartTaskResp(it.taskId, SweeperTask.StartTaskCode.MANUAL_REFUSE)
// mLoadingDialog.showLoading()
// resetTaskInfoPanel()
}
}
override fun onCountDownStop() {
override fun onCountDownStop() {
// ToastUtils.showLong("倒计时结束")
// resetTaskInfoPanel()
// mPresenter?.sendSweeperStartTaskResp(it.taskId, SweeperTask.StartTaskCode.OVER_TIME)
// mLoadingDialog.showLoading()
}
}
override fun onNext() {
override fun onNext() {
}
}, it)
}
}, it)
mDialog?.show()
showNotice("已为您接取任务")
}
@@ -729,4 +811,87 @@ class SweeperFragment : BaseSweeperTabFragment<SweeperFragment?, SweeperPresente
}
})
}
/**
* 添加高精地图中的 子任务 起终点 Marker
*/
private fun addHDMapMarkerBySubTask(subTask: SubTaskInfo) {
if (subTask.startLocation == null
|| subTask.endLocation == null
|| subTask.subTaskId == null
) {
return
}
val startPoint = subTask.startLocation
val endPoint = subTask.endLocation
val hdMarkerIdStart = "marker_sweeper_subtask_${subTask.subTaskId}_start"
val hdMarkerIdEnd = "marker_sweeper_subtask_${subTask.subTaskId}_end"
setMapMaker(hdMarkerIdStart, startPoint.longitude, startPoint.latitude, true)
setMapMaker(hdMarkerIdEnd, endPoint.longitude, endPoint.latitude, false)
}
/**
* 移除高精地图中的 子任务 起终点 Marker
*/
private fun removeHDMapMarkerBySubTask(subTask: SubTaskInfo) {
removeMapMaker()
}
/**
* 设置高精地图里的Marker
*/
private fun setMapMaker(
uuid: String,
longitude: Double,
latitude: Double,
isStartMarker: Boolean
) {
//开启线程执行起终点marker设置
val setMapMarkerRunnable = Runnable {
CallerLogger.d(
SceneConstant.M_SWEEPER + TAG + "setMapMaker",
"threadName=${Thread.currentThread().name}, uuid=$uuid, latitude=$latitude, longitude=$longitude"
)
val builder =
Point.Options.Builder(TYPE_MARKER_SWEEPER_SUBTASK_START_END, Level.MAP_MARKER)
.setId(uuid)
.anchor(0.5f, 0.5f)
.set3DMode(true)
.isUseGps(true)
.controlAngle(true)
.icon3DRes(if (isStartMarker) R.raw.star_marker else R.raw.end_marker)
.longitude(longitude)
.latitude(latitude)
val mapUIController = CallerMapUIServiceManager.getMapUIController()
if (mapUIController != null) {
val centerLine = mapUIController.getCenterLineInfo(longitude, latitude, -1f)
if (null != centerLine) { // 有可能鹰眼map为空没有角度。判空使用后可能造成maker角度跟道路角度不一致 地图未初始化会返回空
val angle = centerLine.angle
if (angle != null) {
builder.rotate(angle.toFloat())
}
}
}
val overlayManager = CallerMapUIServiceManager.getOverlayManager()
overlayManager?.showOrUpdatePoint(builder.build())
}
OCHThreadPoolManager.getsInstance().execute(setMapMarkerRunnable)
}
/**
* 移除高精地图里的Marker
*/
private fun removeMapMaker() {
//开启线程移除起终点marker设置
val removeMapMarkerRunnable = Runnable {
CallerLogger.d(
SceneConstant.M_SWEEPER + TAG + "RemoveMapMaker",
"threadName=${Thread.currentThread().name}"
)
val overlayManager = CallerMapUIServiceManager.getOverlayManager()
overlayManager?.removeAllPointsInOwner(TYPE_MARKER_SWEEPER_SUBTASK_START_END)
}
OCHThreadPoolManager.getsInstance().execute(removeMapMarkerRunnable)
}
}