feat(巡逻): 增强巡逻功能并支持循环、等待和非停止模式
- 在 MqttManager 中解析巡逻命令的 times、waiting 和 nonStop 参数 - 修改 MainActivity.startPatrolMode 以接收新参数并管理巡逻循环 - 实现 moveToCurrentPatrolTarget 和 scheduleNextPatrolMove 方法以支持连续巡逻 - 添加离开 Home Base 的状态跟踪以避免逻辑冲突 - 注释掉原有的 NavPatrol 调用以准备自定义巡逻实现
This commit is contained in:
@@ -56,6 +56,11 @@ class MainActivity : AppCompatActivity(), OnRobotReadyListener, TtsListener, OnG
|
|||||||
private var receptionDestination: String = ""
|
private var receptionDestination: String = ""
|
||||||
private var patrolRoute: List<String> = emptyList()
|
private var patrolRoute: List<String> = emptyList()
|
||||||
private var patrolIndex: Int = 0
|
private var patrolIndex: Int = 0
|
||||||
|
private var patrolLoopsRemaining: Int = 1
|
||||||
|
private var patrolWaitingSeconds: Int = 3
|
||||||
|
private var patrolNonStop: Boolean = false
|
||||||
|
private var patrolMoveJob: Job? = null
|
||||||
|
private var isLeavingHomeBase: Boolean = false
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
@@ -196,6 +201,7 @@ class MainActivity : AppCompatActivity(), OnRobotReadyListener, TtsListener, OnG
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (isAbort) {
|
if (isAbort) {
|
||||||
|
isLeavingHomeBase = false
|
||||||
endNonSpecialTask("goTo aborted: $location, status=$status")
|
endNonSpecialTask("goTo aborted: $location, status=$status")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -203,6 +209,7 @@ class MainActivity : AppCompatActivity(), OnRobotReadyListener, TtsListener, OnG
|
|||||||
if (lastArrivalLocation == location && now - lastArrivalAt < 5000L) {
|
if (lastArrivalLocation == location && now - lastArrivalAt < 5000L) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
isLeavingHomeBase = false
|
||||||
lastArrivalLocation = location
|
lastArrivalLocation = location
|
||||||
lastArrivalAt = now
|
lastArrivalAt = now
|
||||||
prefs.edit().putString("current_location", location).apply()
|
prefs.edit().putString("current_location", location).apply()
|
||||||
@@ -244,7 +251,7 @@ class MainActivity : AppCompatActivity(), OnRobotReadyListener, TtsListener, OnG
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Home Base logic
|
// Home Base logic
|
||||||
if (lastArrivalLocation?.lowercase() == "home base") {
|
if (currentTask == "" && lastArrivalLocation?.lowercase() == "home base" && !isLeavingHomeBase) {
|
||||||
// Check if special task mode is enabled, if so, skip door logic
|
// Check if special task mode is enabled, if so, skip door logic
|
||||||
if (isSpecialModeEnabled() && currentTask.isEmpty()) {
|
if (isSpecialModeEnabled() && currentTask.isEmpty()) {
|
||||||
Log.i("MainActivity", "Special task mode: Door logic skipped at Home Base.")
|
Log.i("MainActivity", "Special task mode: Door logic skipped at Home Base.")
|
||||||
@@ -331,15 +338,20 @@ class MainActivity : AppCompatActivity(), OnRobotReadyListener, TtsListener, OnG
|
|||||||
setCurrentTask("")
|
setCurrentTask("")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startPatrolMode(route: List<String>) {
|
fun startPatrolMode(route: List<String>, times: Int = 1, waiting: Int = 3, nonStop: Boolean = false) {
|
||||||
if (route.isEmpty()) {
|
if (route.isEmpty()) {
|
||||||
setCurrentTask("")
|
setCurrentTask("")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
patrolRoute = route
|
patrolRoute = route
|
||||||
patrolIndex = 0
|
patrolIndex = 0
|
||||||
|
patrolLoopsRemaining = times.coerceAtLeast(1)
|
||||||
|
patrolWaitingSeconds = waiting.coerceAtLeast(0)
|
||||||
|
patrolNonStop = nonStop
|
||||||
|
patrolMoveJob?.cancel()
|
||||||
setCurrentTask("patrol")
|
setCurrentTask("patrol")
|
||||||
Log.i("MainActivity", "Patrol mode started: route=${route.joinToString()}")
|
Log.i("MainActivity", "Patrol mode started: route=${route.joinToString()}")
|
||||||
|
moveToCurrentPatrolTarget()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handlePatrolArrival(location: String) {
|
private fun handlePatrolArrival(location: String) {
|
||||||
@@ -354,8 +366,50 @@ class MainActivity : AppCompatActivity(), OnRobotReadyListener, TtsListener, OnG
|
|||||||
patrolIndex = matchIndex + 1
|
patrolIndex = matchIndex + 1
|
||||||
}
|
}
|
||||||
if (patrolIndex >= patrolRoute.size) {
|
if (patrolIndex >= patrolRoute.size) {
|
||||||
Log.i("MainActivity", "Patrol route completed: ${patrolRoute.joinToString()}")
|
patrolLoopsRemaining -= 1
|
||||||
setCurrentTask("")
|
if (patrolLoopsRemaining <= 0) {
|
||||||
|
Log.i("MainActivity", "Patrol route completed: ${patrolRoute.joinToString()}")
|
||||||
|
setCurrentTask("")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
patrolIndex = 0
|
||||||
|
}
|
||||||
|
scheduleNextPatrolMove()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun moveToCurrentPatrolTarget() {
|
||||||
|
if (currentTask != "patrol") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val target = patrolRoute.getOrNull(patrolIndex) ?: return
|
||||||
|
if (lastArrivalLocation?.equals(target, ignoreCase = true) == true) {
|
||||||
|
patrolIndex += 1
|
||||||
|
if (patrolIndex >= patrolRoute.size) {
|
||||||
|
Log.i("MainActivity", "Patrol route completed: ${patrolRoute.joinToString()}")
|
||||||
|
setCurrentTask("")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
moveToCurrentPatrolTarget()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Log.i("MainActivity", "Patrol moving to next target: $target")
|
||||||
|
if (lastArrivalLocation?.equals("home base", ignoreCase = true) == true &&
|
||||||
|
!target.equals("home base", ignoreCase = true)
|
||||||
|
) {
|
||||||
|
isLeavingHomeBase = true
|
||||||
|
}
|
||||||
|
navCon.goTo(target, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun scheduleNextPatrolMove() {
|
||||||
|
patrolMoveJob?.cancel()
|
||||||
|
if (patrolNonStop || patrolWaitingSeconds <= 0) {
|
||||||
|
moveToCurrentPatrolTarget()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
patrolMoveJob = mainScope.launch {
|
||||||
|
delay(patrolWaitingSeconds * 1000L)
|
||||||
|
moveToCurrentPatrolTarget()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,6 +431,11 @@ class MainActivity : AppCompatActivity(), OnRobotReadyListener, TtsListener, OnG
|
|||||||
if (finalTask != "patrol") {
|
if (finalTask != "patrol") {
|
||||||
patrolRoute = emptyList()
|
patrolRoute = emptyList()
|
||||||
patrolIndex = 0
|
patrolIndex = 0
|
||||||
|
patrolLoopsRemaining = 1
|
||||||
|
patrolWaitingSeconds = 3
|
||||||
|
patrolNonStop = false
|
||||||
|
patrolMoveJob?.cancel()
|
||||||
|
patrolMoveJob = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -229,6 +229,9 @@ class MqttManager(
|
|||||||
"patrol" -> {
|
"patrol" -> {
|
||||||
speak("接到巡逻任务", "zh")
|
speak("接到巡逻任务", "zh")
|
||||||
val flag = obj.optBoolean("flag", true)
|
val flag = obj.optBoolean("flag", true)
|
||||||
|
val times = obj.optInt("times", 1)
|
||||||
|
val waiting = obj.optInt("waiting", obj.optInt("wait", 3))
|
||||||
|
val nonStop = obj.optBoolean("nonStop", obj.optBoolean("non_stop", false))
|
||||||
var patrolLocations: List<String> = emptyList()
|
var patrolLocations: List<String> = emptyList()
|
||||||
if (flag) {
|
if (flag) {
|
||||||
Log.d(TAG, "navController.randomPatrol() called.")
|
Log.d(TAG, "navController.randomPatrol() called.")
|
||||||
@@ -239,8 +242,8 @@ class MqttManager(
|
|||||||
val locations = List(locationsArray.length()) {
|
val locations = List(locationsArray.length()) {
|
||||||
locationsArray.getString(it)
|
locationsArray.getString(it)
|
||||||
}
|
}
|
||||||
Log.d(TAG, "navController.NavPatrol() called with locations: $locations")
|
Log.d(TAG, "Patrol route received with locations: $locations")
|
||||||
navController.NavPatrol(locations)
|
// navController.NavPatrol(locations)
|
||||||
patrolLocations = locations
|
patrolLocations = locations
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "Patrol command received without locations, falling back to random patrol.")
|
Log.w(TAG, "Patrol command received without locations, falling back to random patrol.")
|
||||||
@@ -250,7 +253,7 @@ class MqttManager(
|
|||||||
scope.launch(Dispatchers.Main) {
|
scope.launch(Dispatchers.Main) {
|
||||||
val activity = context as? MainActivity
|
val activity = context as? MainActivity
|
||||||
if (patrolLocations.isNotEmpty()) {
|
if (patrolLocations.isNotEmpty()) {
|
||||||
activity?.startPatrolMode(patrolLocations)
|
activity?.startPatrolMode(patrolLocations, times, waiting, nonStop)
|
||||||
} else {
|
} else {
|
||||||
activity?.setCurrentTask("")
|
activity?.setCurrentTask("")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ class NavController(private val robot: Robot) {
|
|||||||
val patrolCount = (3..minOf(6, availablePatrolLocations.size)).random()
|
val patrolCount = (3..minOf(6, availablePatrolLocations.size)).random()
|
||||||
val patrolLocations = availablePatrolLocations.shuffled().take(patrolCount)
|
val patrolLocations = availablePatrolLocations.shuffled().take(patrolCount)
|
||||||
Log.i(TAG, "Starting random patrol with $patrolCount locations: ${patrolLocations.joinToString()}.")
|
Log.i(TAG, "Starting random patrol with $patrolCount locations: ${patrolLocations.joinToString()}.")
|
||||||
NavPatrol(patrolLocations, false, 1, 5)
|
// 官方 patrol 调用保留(部分版本可能无效)
|
||||||
|
// NavPatrol(patrolLocations, false, 1, 5)
|
||||||
return patrolLocations
|
return patrolLocations
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user