isar 1.33.5__py3-none-any.whl → 1.33.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of isar might be problematic. Click here for more details.
- isar/apis/api.py +34 -0
- isar/apis/models/models.py +5 -0
- isar/apis/schedule/scheduling_controller.py +34 -0
- isar/models/events.py +17 -1
- isar/robot/robot.py +32 -0
- isar/robot/robot_pause_mission.py +63 -0
- isar/robot/robot_stop_mission.py +1 -1
- isar/services/utilities/scheduling_utilities.py +50 -4
- isar/state_machine/state_machine.py +27 -7
- isar/state_machine/states/await_next_mission.py +19 -1
- isar/state_machine/states/going_to_lockdown.py +80 -0
- isar/state_machine/states/home.py +15 -0
- isar/state_machine/states/lockdown.py +37 -0
- isar/state_machine/states/monitor.py +16 -0
- isar/state_machine/states/paused.py +19 -1
- isar/state_machine/states/pausing.py +74 -0
- isar/state_machine/states/pausing_return_home.py +74 -0
- isar/state_machine/states/recharging.py +16 -0
- isar/state_machine/states/return_home_paused.py +17 -1
- isar/state_machine/states/returning_home.py +18 -2
- isar/state_machine/states/stopping_go_to_lockdown.py +79 -0
- isar/state_machine/states_enum.py +5 -0
- isar/state_machine/transitions/functions/fail_mission.py +7 -0
- isar/state_machine/transitions/functions/pause.py +20 -80
- isar/state_machine/transitions/mission.py +55 -10
- isar/state_machine/transitions/return_home.py +53 -0
- {isar-1.33.5.dist-info → isar-1.33.6.dist-info}/METADATA +1 -1
- {isar-1.33.5.dist-info → isar-1.33.6.dist-info}/RECORD +33 -27
- robot_interface/models/mission/status.py +2 -0
- {isar-1.33.5.dist-info → isar-1.33.6.dist-info}/WHEEL +0 -0
- {isar-1.33.5.dist-info → isar-1.33.6.dist-info}/entry_points.txt +0 -0
- {isar-1.33.5.dist-info → isar-1.33.6.dist-info}/licenses/LICENSE +0 -0
- {isar-1.33.5.dist-info → isar-1.33.6.dist-info}/top_level.txt +0 -0
|
@@ -3,6 +3,7 @@ from typing import TYPE_CHECKING, Callable, List, Optional
|
|
|
3
3
|
from isar.config.settings import settings
|
|
4
4
|
from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
|
|
5
5
|
from isar.models.events import Event
|
|
6
|
+
from isar.state_machine.utils.common_event_handlers import stop_mission_event_handler
|
|
6
7
|
|
|
7
8
|
if TYPE_CHECKING:
|
|
8
9
|
from isar.state_machine.state_machine import StateMachine
|
|
@@ -29,11 +30,23 @@ class Paused(EventHandlerBase):
|
|
|
29
30
|
return state_machine.stop # type: ignore
|
|
30
31
|
return None
|
|
31
32
|
|
|
33
|
+
def _send_to_lockdown_event_handler(
|
|
34
|
+
event: Event[bool],
|
|
35
|
+
) -> Optional[Callable]:
|
|
36
|
+
should_lockdown: bool = event.consume_event()
|
|
37
|
+
if should_lockdown:
|
|
38
|
+
state_machine._finalize()
|
|
39
|
+
state_machine.logger.warning(
|
|
40
|
+
"Cancelling current mission due to robot going to lockdown"
|
|
41
|
+
)
|
|
42
|
+
return state_machine.stop_go_to_lockdown # type: ignore
|
|
43
|
+
return None
|
|
44
|
+
|
|
32
45
|
event_handlers: List[EventHandlerMapping] = [
|
|
33
46
|
EventHandlerMapping(
|
|
34
47
|
name="stop_mission_event",
|
|
35
48
|
event=events.api_requests.stop_mission.request,
|
|
36
|
-
handler=lambda event: state_machine
|
|
49
|
+
handler=lambda event: stop_mission_event_handler(state_machine, event),
|
|
37
50
|
),
|
|
38
51
|
EventHandlerMapping(
|
|
39
52
|
name="resume_mission_event",
|
|
@@ -45,6 +58,11 @@ class Paused(EventHandlerBase):
|
|
|
45
58
|
event=shared_state.robot_battery_level,
|
|
46
59
|
handler=_robot_battery_level_updated_handler,
|
|
47
60
|
),
|
|
61
|
+
EventHandlerMapping(
|
|
62
|
+
name="send_to_lockdown_event",
|
|
63
|
+
event=events.api_requests.send_to_lockdown.request,
|
|
64
|
+
handler=_send_to_lockdown_event_handler,
|
|
65
|
+
),
|
|
48
66
|
]
|
|
49
67
|
super().__init__(
|
|
50
68
|
state_name="paused",
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Callable, List, Optional
|
|
2
|
+
|
|
3
|
+
from isar.apis.models.models import ControlMissionResponse
|
|
4
|
+
from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
|
|
5
|
+
from isar.models.events import Event
|
|
6
|
+
from robot_interface.models.exceptions.robot_exceptions import ErrorMessage
|
|
7
|
+
from robot_interface.models.mission.status import MissionStatus, TaskStatus
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from isar.state_machine.state_machine import StateMachine
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Pausing(EventHandlerBase):
|
|
14
|
+
|
|
15
|
+
def __init__(self, state_machine: "StateMachine"):
|
|
16
|
+
events = state_machine.events
|
|
17
|
+
|
|
18
|
+
def _failed_pause_event_handler(
|
|
19
|
+
event: Event[ErrorMessage],
|
|
20
|
+
) -> Optional[Callable]:
|
|
21
|
+
error_message: Optional[ErrorMessage] = event.consume_event()
|
|
22
|
+
|
|
23
|
+
paused_mission_response: ControlMissionResponse = (
|
|
24
|
+
state_machine._make_control_mission_response()
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
state_machine.events.api_requests.pause_mission.response.trigger_event(
|
|
28
|
+
paused_mission_response
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
state_machine.publish_mission_status()
|
|
32
|
+
state_machine.send_task_status()
|
|
33
|
+
|
|
34
|
+
if error_message is not None:
|
|
35
|
+
return state_machine.mission_pausing_failed # type: ignore
|
|
36
|
+
return None
|
|
37
|
+
|
|
38
|
+
def _successful_pause_event_handler(event: Event[bool]) -> Optional[Callable]:
|
|
39
|
+
if event.consume_event():
|
|
40
|
+
|
|
41
|
+
state_machine.current_mission.status = MissionStatus.Paused
|
|
42
|
+
state_machine.current_task.status = TaskStatus.Paused
|
|
43
|
+
|
|
44
|
+
paused_mission_response: ControlMissionResponse = (
|
|
45
|
+
state_machine._make_control_mission_response()
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
state_machine.events.api_requests.pause_mission.response.trigger_event(
|
|
49
|
+
paused_mission_response
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
state_machine.publish_mission_status()
|
|
53
|
+
state_machine.send_task_status()
|
|
54
|
+
|
|
55
|
+
return state_machine.mission_paused # type:ignore
|
|
56
|
+
return None
|
|
57
|
+
|
|
58
|
+
event_handlers: List[EventHandlerMapping] = [
|
|
59
|
+
EventHandlerMapping(
|
|
60
|
+
name="failed_pause_event",
|
|
61
|
+
event=events.robot_service_events.mission_failed_to_pause,
|
|
62
|
+
handler=_failed_pause_event_handler,
|
|
63
|
+
),
|
|
64
|
+
EventHandlerMapping(
|
|
65
|
+
name="successful_pause_event",
|
|
66
|
+
event=events.robot_service_events.mission_successfully_paused,
|
|
67
|
+
handler=_successful_pause_event_handler,
|
|
68
|
+
),
|
|
69
|
+
]
|
|
70
|
+
super().__init__(
|
|
71
|
+
state_name="pausing",
|
|
72
|
+
state_machine=state_machine,
|
|
73
|
+
event_handler_mappings=event_handlers,
|
|
74
|
+
)
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Callable, List, Optional
|
|
2
|
+
|
|
3
|
+
from isar.apis.models.models import ControlMissionResponse
|
|
4
|
+
from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
|
|
5
|
+
from isar.models.events import Event
|
|
6
|
+
from robot_interface.models.exceptions.robot_exceptions import ErrorMessage
|
|
7
|
+
from robot_interface.models.mission.status import MissionStatus, TaskStatus
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from isar.state_machine.state_machine import StateMachine
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class PausingReturnHome(EventHandlerBase):
|
|
14
|
+
|
|
15
|
+
def __init__(self, state_machine: "StateMachine"):
|
|
16
|
+
events = state_machine.events
|
|
17
|
+
|
|
18
|
+
def _failed_pause_event_handler(
|
|
19
|
+
event: Event[ErrorMessage],
|
|
20
|
+
) -> Optional[Callable]:
|
|
21
|
+
error_message: Optional[ErrorMessage] = event.consume_event()
|
|
22
|
+
|
|
23
|
+
paused_mission_response: ControlMissionResponse = (
|
|
24
|
+
state_machine._make_control_mission_response()
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
state_machine.events.api_requests.pause_mission.response.trigger_event(
|
|
28
|
+
paused_mission_response
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
state_machine.publish_mission_status()
|
|
32
|
+
state_machine.send_task_status()
|
|
33
|
+
|
|
34
|
+
if error_message is not None:
|
|
35
|
+
return state_machine.return_home_mission_pausing_failed # type: ignore
|
|
36
|
+
return None
|
|
37
|
+
|
|
38
|
+
def _successful_pause_event_handler(event: Event[bool]) -> Optional[Callable]:
|
|
39
|
+
if event.consume_event():
|
|
40
|
+
|
|
41
|
+
state_machine.current_mission.status = MissionStatus.Paused
|
|
42
|
+
state_machine.current_task.status = TaskStatus.Paused
|
|
43
|
+
|
|
44
|
+
paused_mission_response: ControlMissionResponse = (
|
|
45
|
+
state_machine._make_control_mission_response()
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
state_machine.events.api_requests.pause_mission.response.trigger_event(
|
|
49
|
+
paused_mission_response
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
state_machine.publish_mission_status()
|
|
53
|
+
state_machine.send_task_status()
|
|
54
|
+
|
|
55
|
+
return state_machine.return_home_mission_paused # type: ignore
|
|
56
|
+
return None
|
|
57
|
+
|
|
58
|
+
event_handlers: List[EventHandlerMapping] = [
|
|
59
|
+
EventHandlerMapping(
|
|
60
|
+
name="failed_pause_event",
|
|
61
|
+
event=events.robot_service_events.mission_failed_to_pause,
|
|
62
|
+
handler=_failed_pause_event_handler,
|
|
63
|
+
),
|
|
64
|
+
EventHandlerMapping(
|
|
65
|
+
name="successful_stop_event",
|
|
66
|
+
event=events.robot_service_events.mission_successfully_paused,
|
|
67
|
+
handler=_successful_pause_event_handler,
|
|
68
|
+
),
|
|
69
|
+
]
|
|
70
|
+
super().__init__(
|
|
71
|
+
state_name="pausing_return_home",
|
|
72
|
+
state_machine=state_machine,
|
|
73
|
+
event_handler_mappings=event_handlers,
|
|
74
|
+
)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING, List
|
|
2
2
|
|
|
3
|
+
from isar.apis.models.models import LockdownResponse
|
|
3
4
|
from isar.config.settings import settings
|
|
4
5
|
from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
|
|
5
6
|
from isar.models.events import Event
|
|
@@ -13,6 +14,7 @@ class Recharging(EventHandlerBase):
|
|
|
13
14
|
|
|
14
15
|
def __init__(self, state_machine: "StateMachine"):
|
|
15
16
|
shared_state = state_machine.shared_state
|
|
17
|
+
events = state_machine.events
|
|
16
18
|
|
|
17
19
|
def robot_battery_level_updated_handler(event: Event[float]):
|
|
18
20
|
battery_level: float = event.check()
|
|
@@ -25,6 +27,15 @@ class Recharging(EventHandlerBase):
|
|
|
25
27
|
if robot_status == RobotStatus.Offline:
|
|
26
28
|
return state_machine.robot_went_offline # type: ignore
|
|
27
29
|
|
|
30
|
+
def _send_to_lockdown_event_handler(event: Event[bool]):
|
|
31
|
+
should_lockdown: bool = event.consume_event()
|
|
32
|
+
if should_lockdown:
|
|
33
|
+
events.api_requests.send_to_lockdown.response.trigger_event(
|
|
34
|
+
LockdownResponse(lockdown_started=True)
|
|
35
|
+
)
|
|
36
|
+
return state_machine.reached_lockdown # type: ignore
|
|
37
|
+
return None
|
|
38
|
+
|
|
28
39
|
event_handlers: List[EventHandlerMapping] = [
|
|
29
40
|
EventHandlerMapping(
|
|
30
41
|
name="robot_battery_update_event",
|
|
@@ -36,6 +47,11 @@ class Recharging(EventHandlerBase):
|
|
|
36
47
|
event=shared_state.robot_status,
|
|
37
48
|
handler=robot_offline_handler,
|
|
38
49
|
),
|
|
50
|
+
EventHandlerMapping(
|
|
51
|
+
name="send_to_lockdown_event",
|
|
52
|
+
event=events.api_requests.send_to_lockdown.request,
|
|
53
|
+
handler=_send_to_lockdown_event_handler,
|
|
54
|
+
),
|
|
39
55
|
]
|
|
40
56
|
super().__init__(
|
|
41
57
|
state_name="recharging",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING, Callable, List, Optional
|
|
2
2
|
|
|
3
|
-
from isar.apis.models.models import MissionStartResponse
|
|
3
|
+
from isar.apis.models.models import LockdownResponse, MissionStartResponse
|
|
4
4
|
from isar.config.settings import settings
|
|
5
5
|
from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
|
|
6
6
|
from isar.models.events import Event
|
|
@@ -42,6 +42,17 @@ class ReturnHomePaused(EventHandlerBase):
|
|
|
42
42
|
return state_machine.stop_return_home # type: ignore
|
|
43
43
|
return None
|
|
44
44
|
|
|
45
|
+
def _send_to_lockdown_event_handler(
|
|
46
|
+
event: Event[bool],
|
|
47
|
+
) -> Optional[Callable]:
|
|
48
|
+
should_lockdown: bool = event.consume_event()
|
|
49
|
+
if should_lockdown:
|
|
50
|
+
events.api_requests.send_to_lockdown.response.trigger_event(
|
|
51
|
+
LockdownResponse(lockdown_started=True)
|
|
52
|
+
)
|
|
53
|
+
return state_machine.resume_lockdown # type: ignore
|
|
54
|
+
return None
|
|
55
|
+
|
|
45
56
|
event_handlers: List[EventHandlerMapping] = [
|
|
46
57
|
EventHandlerMapping(
|
|
47
58
|
name="resume_return_home_event",
|
|
@@ -58,6 +69,11 @@ class ReturnHomePaused(EventHandlerBase):
|
|
|
58
69
|
event=events.api_requests.start_mission.request,
|
|
59
70
|
handler=_start_mission_event_handler,
|
|
60
71
|
),
|
|
72
|
+
EventHandlerMapping(
|
|
73
|
+
name="send_to_lockdown_event",
|
|
74
|
+
event=events.api_requests.send_to_lockdown.request,
|
|
75
|
+
handler=_send_to_lockdown_event_handler,
|
|
76
|
+
),
|
|
61
77
|
]
|
|
62
78
|
super().__init__(
|
|
63
79
|
state_name="return_home_paused",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING, Callable, List, Optional
|
|
2
2
|
|
|
3
|
-
from isar.apis.models.models import MissionStartResponse
|
|
3
|
+
from isar.apis.models.models import LockdownResponse, MissionStartResponse
|
|
4
4
|
from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
|
|
5
5
|
from isar.models.events import Event
|
|
6
6
|
from isar.state_machine.utils.common_event_handlers import (
|
|
@@ -25,7 +25,7 @@ class ReturningHome(EventHandlerBase):
|
|
|
25
25
|
|
|
26
26
|
def _pause_mission_event_handler(event: Event[bool]) -> Optional[Callable]:
|
|
27
27
|
if event.consume_event():
|
|
28
|
-
return state_machine.
|
|
28
|
+
return state_machine.pause_return_home # type: ignore
|
|
29
29
|
return None
|
|
30
30
|
|
|
31
31
|
def _handle_task_completed(status: TaskStatus):
|
|
@@ -60,6 +60,17 @@ class ReturningHome(EventHandlerBase):
|
|
|
60
60
|
return state_machine.stop_return_home # type: ignore
|
|
61
61
|
return None
|
|
62
62
|
|
|
63
|
+
def _send_to_lockdown_event_handler(
|
|
64
|
+
event: Event[bool],
|
|
65
|
+
) -> Optional[Callable]:
|
|
66
|
+
should_lockdown: bool = event.consume_event()
|
|
67
|
+
if should_lockdown:
|
|
68
|
+
events.api_requests.send_to_lockdown.response.trigger_event(
|
|
69
|
+
LockdownResponse(lockdown_started=True)
|
|
70
|
+
)
|
|
71
|
+
return state_machine.go_to_lockdown # type: ignore
|
|
72
|
+
return None
|
|
73
|
+
|
|
63
74
|
event_handlers: List[EventHandlerMapping] = [
|
|
64
75
|
EventHandlerMapping(
|
|
65
76
|
name="pause_mission_event",
|
|
@@ -99,6 +110,11 @@ class ReturningHome(EventHandlerBase):
|
|
|
99
110
|
state_machine, _handle_task_completed, event
|
|
100
111
|
),
|
|
101
112
|
),
|
|
113
|
+
EventHandlerMapping(
|
|
114
|
+
name="send_to_lockdown_event",
|
|
115
|
+
event=events.api_requests.send_to_lockdown.request,
|
|
116
|
+
handler=_send_to_lockdown_event_handler,
|
|
117
|
+
),
|
|
102
118
|
]
|
|
103
119
|
super().__init__(
|
|
104
120
|
state_name="returning_home",
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Callable, List, Optional
|
|
2
|
+
|
|
3
|
+
from isar.apis.models.models import LockdownResponse
|
|
4
|
+
from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
|
|
5
|
+
from isar.models.events import Event
|
|
6
|
+
from robot_interface.models.exceptions.robot_exceptions import ErrorMessage
|
|
7
|
+
from robot_interface.models.mission.status import MissionStatus, TaskStatus
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from isar.state_machine.state_machine import StateMachine
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class StoppingGoToLockdown(EventHandlerBase):
|
|
14
|
+
|
|
15
|
+
def __init__(self, state_machine: "StateMachine"):
|
|
16
|
+
events = state_machine.events
|
|
17
|
+
|
|
18
|
+
def _stop_mission_cleanup() -> None:
|
|
19
|
+
if state_machine.current_mission is None:
|
|
20
|
+
state_machine._queue_empty_response()
|
|
21
|
+
state_machine.reset_state_machine()
|
|
22
|
+
return None
|
|
23
|
+
|
|
24
|
+
state_machine.current_mission.status = MissionStatus.Cancelled
|
|
25
|
+
|
|
26
|
+
for task in state_machine.current_mission.tasks:
|
|
27
|
+
if task.status in [
|
|
28
|
+
TaskStatus.NotStarted,
|
|
29
|
+
TaskStatus.InProgress,
|
|
30
|
+
TaskStatus.Paused,
|
|
31
|
+
]:
|
|
32
|
+
task.status = TaskStatus.Cancelled
|
|
33
|
+
|
|
34
|
+
state_machine.publish_task_status(task=state_machine.current_task)
|
|
35
|
+
return None
|
|
36
|
+
|
|
37
|
+
def _failed_stop_event_handler(
|
|
38
|
+
event: Event[ErrorMessage],
|
|
39
|
+
) -> Optional[Callable]:
|
|
40
|
+
error_message: Optional[ErrorMessage] = event.consume_event()
|
|
41
|
+
if error_message is not None:
|
|
42
|
+
events.api_requests.send_to_lockdown.response.trigger_event(
|
|
43
|
+
LockdownResponse(
|
|
44
|
+
lockdown_started=False,
|
|
45
|
+
failure_reason="Failed to stop ongoing mission",
|
|
46
|
+
)
|
|
47
|
+
)
|
|
48
|
+
return state_machine.mission_stopping_failed # type: ignore
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
def _successful_stop_event_handler(event: Event[bool]) -> Optional[Callable]:
|
|
52
|
+
if event.consume_event():
|
|
53
|
+
state_machine.publish_mission_aborted(
|
|
54
|
+
"Robot being sent to lockdown", True
|
|
55
|
+
)
|
|
56
|
+
_stop_mission_cleanup()
|
|
57
|
+
events.api_requests.send_to_lockdown.response.trigger_event(
|
|
58
|
+
LockdownResponse(lockdown_started=True)
|
|
59
|
+
)
|
|
60
|
+
return state_machine.request_lockdown_mission # type: ignore
|
|
61
|
+
return None
|
|
62
|
+
|
|
63
|
+
event_handlers: List[EventHandlerMapping] = [
|
|
64
|
+
EventHandlerMapping(
|
|
65
|
+
name="failed_stop_event",
|
|
66
|
+
event=events.robot_service_events.mission_failed_to_stop,
|
|
67
|
+
handler=_failed_stop_event_handler,
|
|
68
|
+
),
|
|
69
|
+
EventHandlerMapping(
|
|
70
|
+
name="successful_stop_event",
|
|
71
|
+
event=events.robot_service_events.mission_successfully_stopped,
|
|
72
|
+
handler=_successful_stop_event_handler,
|
|
73
|
+
),
|
|
74
|
+
]
|
|
75
|
+
super().__init__(
|
|
76
|
+
state_name="stopping_go_to_lockdown",
|
|
77
|
+
state_machine=state_machine,
|
|
78
|
+
event_handler_mappings=event_handlers,
|
|
79
|
+
)
|
|
@@ -7,6 +7,8 @@ class States(str, Enum):
|
|
|
7
7
|
Stopping = "stopping"
|
|
8
8
|
StoppingReturnHome = "stopping_return_home"
|
|
9
9
|
Paused = "paused"
|
|
10
|
+
Pausing = "pausing"
|
|
11
|
+
PausingReturnHome = "pausing_return_home"
|
|
10
12
|
ReturnHomePaused = "return_home_paused"
|
|
11
13
|
AwaitNextMission = "await_next_mission"
|
|
12
14
|
Home = "home"
|
|
@@ -15,6 +17,9 @@ class States(str, Enum):
|
|
|
15
17
|
UnknownStatus = "unknown_status"
|
|
16
18
|
InterventionNeeded = "intervention_needed"
|
|
17
19
|
Recharging = "recharging"
|
|
20
|
+
StoppingGoToLockdown = "stopping_go_to_lockdown"
|
|
21
|
+
GoingToLockdown = "going_to_lockdown"
|
|
22
|
+
Lockdown = "lockdown"
|
|
18
23
|
|
|
19
24
|
def __repr__(self):
|
|
20
25
|
return self.value
|
|
@@ -18,3 +18,10 @@ def report_failed_return_home_and_intervention_needed(
|
|
|
18
18
|
) -> None:
|
|
19
19
|
error_message: str = "Return home failed."
|
|
20
20
|
state_machine.publish_intervention_needed(error_message=error_message)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def report_failed_lockdown_and_intervention_needed(
|
|
24
|
+
state_machine: "StateMachine",
|
|
25
|
+
) -> None:
|
|
26
|
+
error_message: str = "Lockdown mission failed."
|
|
27
|
+
state_machine.publish_intervention_needed(error_message=error_message)
|
|
@@ -1,91 +1,31 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING
|
|
2
2
|
|
|
3
|
-
if TYPE_CHECKING:
|
|
4
|
-
from isar.state_machine.state_machine import StateMachine
|
|
5
|
-
|
|
6
|
-
import time
|
|
7
|
-
|
|
8
3
|
from isar.apis.models.models import ControlMissionResponse
|
|
9
|
-
from isar.config.settings import settings
|
|
10
|
-
from robot_interface.models.exceptions.robot_exceptions import (
|
|
11
|
-
RobotActionException,
|
|
12
|
-
RobotException,
|
|
13
|
-
)
|
|
14
|
-
from robot_interface.models.mission.status import MissionStatus, TaskStatus
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def pause_mission(state_machine: "StateMachine") -> bool:
|
|
18
|
-
state_machine.logger.info("Pausing mission: %s", state_machine.current_mission.id)
|
|
19
|
-
|
|
20
|
-
max_retries = settings.STATE_TRANSITION_NUM_RETIRES
|
|
21
|
-
retry_interval = settings.STATE_TRANSITION_RETRY_INTERVAL_SEC
|
|
22
|
-
|
|
23
|
-
for attempt in range(max_retries):
|
|
24
|
-
try:
|
|
25
|
-
state_machine.robot.pause()
|
|
26
|
-
state_machine.current_mission.status = MissionStatus.Paused
|
|
27
|
-
state_machine.current_task.status = TaskStatus.Paused
|
|
28
|
-
|
|
29
|
-
paused_mission_response: ControlMissionResponse = (
|
|
30
|
-
state_machine._make_control_mission_response()
|
|
31
|
-
)
|
|
32
|
-
state_machine.events.api_requests.pause_mission.response.trigger_event(
|
|
33
|
-
paused_mission_response
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
state_machine.publish_mission_status()
|
|
37
|
-
state_machine.publish_task_status(task=state_machine.current_task)
|
|
38
|
-
|
|
39
|
-
state_machine.logger.info("Mission paused successfully.")
|
|
40
|
-
return True
|
|
41
|
-
except RobotActionException as e:
|
|
42
|
-
state_machine.logger.warning(
|
|
43
|
-
f"Attempt {attempt + 1} to pause mission failed: {e.error_description}"
|
|
44
|
-
)
|
|
45
|
-
time.sleep(retry_interval)
|
|
46
|
-
except RobotException as e:
|
|
47
|
-
state_machine.logger.warning(
|
|
48
|
-
f"Attempt {attempt + 1} to pause mission raised a RobotException: {e.error_description}"
|
|
49
|
-
)
|
|
50
|
-
time.sleep(retry_interval)
|
|
51
|
-
|
|
52
|
-
state_machine.logger.error("Failed to pause mission after multiple attempts.")
|
|
53
|
-
return False
|
|
54
4
|
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from isar.state_machine.state_machine import StateMachine
|
|
55
7
|
|
|
56
|
-
def pause_return_home_mission(state_machine: "StateMachine") -> bool:
|
|
57
|
-
state_machine.logger.info("Pausing return home misson")
|
|
58
8
|
|
|
59
|
-
|
|
60
|
-
|
|
9
|
+
def trigger_pause_mission_event(state_machine: "StateMachine") -> bool:
|
|
10
|
+
state_machine.events.state_machine_events.pause_mission.trigger_event(True)
|
|
11
|
+
return True
|
|
61
12
|
|
|
62
|
-
for attempt in range(max_retries):
|
|
63
|
-
try:
|
|
64
|
-
state_machine.robot.pause()
|
|
65
|
-
state_machine.current_mission.status = MissionStatus.Paused
|
|
66
|
-
state_machine.current_task.status = TaskStatus.Paused
|
|
67
13
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
14
|
+
def pause_mission_failed(state_machine: "StateMachine") -> bool:
|
|
15
|
+
paused_mission_response: ControlMissionResponse = (
|
|
16
|
+
state_machine._make_control_mission_response()
|
|
17
|
+
)
|
|
18
|
+
state_machine.events.api_requests.pause_mission.response.trigger_event(
|
|
19
|
+
paused_mission_response
|
|
20
|
+
)
|
|
21
|
+
return True
|
|
74
22
|
|
|
75
|
-
state_machine.logger.info("Return home mission paused successfully.")
|
|
76
|
-
return True
|
|
77
|
-
except RobotActionException as e:
|
|
78
|
-
state_machine.logger.warning(
|
|
79
|
-
f"Attempt {attempt + 1} to pause return home mission failed: {e.error_description}"
|
|
80
|
-
)
|
|
81
|
-
time.sleep(retry_interval)
|
|
82
|
-
except RobotException as e:
|
|
83
|
-
state_machine.logger.warning(
|
|
84
|
-
f"Attempt {attempt + 1} to pause return home mission raised a RobotException: {e.error_description}"
|
|
85
|
-
)
|
|
86
|
-
time.sleep(retry_interval)
|
|
87
23
|
|
|
88
|
-
|
|
89
|
-
|
|
24
|
+
def stop_return_home_mission_failed(state_machine: "StateMachine") -> bool:
|
|
25
|
+
paused_mission_response: ControlMissionResponse = (
|
|
26
|
+
state_machine._make_control_mission_response()
|
|
27
|
+
)
|
|
28
|
+
state_machine.events.api_requests.pause_mission.response.trigger_event(
|
|
29
|
+
paused_mission_response
|
|
90
30
|
)
|
|
91
|
-
return
|
|
31
|
+
return True
|
|
@@ -5,8 +5,8 @@ from isar.state_machine.transitions.functions.fail_mission import (
|
|
|
5
5
|
)
|
|
6
6
|
from isar.state_machine.transitions.functions.finish_mission import finish_mission
|
|
7
7
|
from isar.state_machine.transitions.functions.pause import (
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
pause_mission_failed,
|
|
9
|
+
trigger_pause_mission_event,
|
|
10
10
|
)
|
|
11
11
|
from isar.state_machine.transitions.functions.resume import resume_mission
|
|
12
12
|
from isar.state_machine.transitions.functions.return_home import (
|
|
@@ -36,24 +36,39 @@ def get_mission_transitions(state_machine: "StateMachine") -> List[dict]:
|
|
|
36
36
|
{
|
|
37
37
|
"trigger": "pause",
|
|
38
38
|
"source": state_machine.monitor_state,
|
|
39
|
+
"dest": state_machine.pausing_state,
|
|
40
|
+
"conditions": def_transition(state_machine, trigger_pause_mission_event),
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"trigger": "mission_paused",
|
|
44
|
+
"source": state_machine.pausing_state,
|
|
39
45
|
"dest": state_machine.paused_state,
|
|
40
|
-
"conditions": def_transition(state_machine, pause_mission),
|
|
41
46
|
},
|
|
42
47
|
{
|
|
43
|
-
"trigger": "
|
|
44
|
-
"source": state_machine.
|
|
48
|
+
"trigger": "mission_pausing_failed",
|
|
49
|
+
"source": state_machine.pausing_state,
|
|
45
50
|
"dest": state_machine.monitor_state,
|
|
51
|
+
"before": def_transition(state_machine, pause_mission_failed),
|
|
46
52
|
},
|
|
47
53
|
{
|
|
48
|
-
"trigger": "
|
|
54
|
+
"trigger": "pause_return_home",
|
|
49
55
|
"source": state_machine.returning_home_state,
|
|
50
|
-
"dest": state_machine.
|
|
51
|
-
"
|
|
56
|
+
"dest": state_machine.pausing_return_home_state,
|
|
57
|
+
"before": [
|
|
58
|
+
def_transition(state_machine, trigger_pause_mission_event),
|
|
59
|
+
def_transition(state_machine, reset_return_home_failure_counter),
|
|
60
|
+
],
|
|
52
61
|
},
|
|
53
62
|
{
|
|
54
|
-
"trigger": "
|
|
55
|
-
"source": state_machine.
|
|
63
|
+
"trigger": "return_home_mission_pausing_failed",
|
|
64
|
+
"source": state_machine.pausing_return_home_state,
|
|
56
65
|
"dest": state_machine.returning_home_state,
|
|
66
|
+
"before": def_transition(state_machine, stop_return_home_mission_failed),
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"trigger": "return_home_mission_paused",
|
|
70
|
+
"source": state_machine.pausing_return_home_state,
|
|
71
|
+
"dest": state_machine.return_home_paused_state,
|
|
57
72
|
},
|
|
58
73
|
{
|
|
59
74
|
"trigger": "resume",
|
|
@@ -77,6 +92,12 @@ def get_mission_transitions(state_machine: "StateMachine") -> List[dict]:
|
|
|
77
92
|
"source": state_machine.return_home_paused_state,
|
|
78
93
|
"dest": state_machine.return_home_paused_state,
|
|
79
94
|
},
|
|
95
|
+
{
|
|
96
|
+
"trigger": "resume_lockdown",
|
|
97
|
+
"source": state_machine.return_home_paused_state,
|
|
98
|
+
"dest": state_machine.going_to_lockdown_state,
|
|
99
|
+
"conditions": def_transition(state_machine, resume_mission),
|
|
100
|
+
},
|
|
80
101
|
{
|
|
81
102
|
"trigger": "stop",
|
|
82
103
|
"source": [
|
|
@@ -87,6 +108,14 @@ def get_mission_transitions(state_machine: "StateMachine") -> List[dict]:
|
|
|
87
108
|
"dest": state_machine.stopping_state,
|
|
88
109
|
"before": def_transition(state_machine, trigger_stop_mission_event),
|
|
89
110
|
},
|
|
111
|
+
{
|
|
112
|
+
"trigger": "stop_go_to_lockdown",
|
|
113
|
+
"source": [
|
|
114
|
+
state_machine.monitor_state,
|
|
115
|
+
],
|
|
116
|
+
"dest": state_machine.stopping_go_to_lockdown_state,
|
|
117
|
+
"before": def_transition(state_machine, trigger_stop_mission_event),
|
|
118
|
+
},
|
|
90
119
|
{
|
|
91
120
|
"trigger": "stop_return_home",
|
|
92
121
|
"source": [
|
|
@@ -105,12 +134,22 @@ def get_mission_transitions(state_machine: "StateMachine") -> List[dict]:
|
|
|
105
134
|
"source": state_machine.stopping_state,
|
|
106
135
|
"dest": state_machine.await_next_mission_state,
|
|
107
136
|
},
|
|
137
|
+
{
|
|
138
|
+
"trigger": "mission_stopped",
|
|
139
|
+
"source": state_machine.stopping_go_to_lockdown_state,
|
|
140
|
+
"dest": state_machine.going_to_lockdown_state,
|
|
141
|
+
},
|
|
108
142
|
{
|
|
109
143
|
"trigger": "mission_stopping_failed",
|
|
110
144
|
"source": state_machine.stopping_state,
|
|
111
145
|
"dest": state_machine.monitor_state,
|
|
112
146
|
"before": def_transition(state_machine, stop_mission_failed),
|
|
113
147
|
},
|
|
148
|
+
{
|
|
149
|
+
"trigger": "mission_stopping_failed",
|
|
150
|
+
"source": state_machine.stopping_go_to_lockdown_state,
|
|
151
|
+
"dest": state_machine.monitor_state,
|
|
152
|
+
},
|
|
114
153
|
{
|
|
115
154
|
"trigger": "return_home_mission_stopping_failed",
|
|
116
155
|
"source": state_machine.stopping_return_home_state,
|
|
@@ -159,5 +198,11 @@ def get_mission_transitions(state_machine: "StateMachine") -> List[dict]:
|
|
|
159
198
|
"dest": state_machine.await_next_mission_state,
|
|
160
199
|
"before": def_transition(state_machine, finish_mission),
|
|
161
200
|
},
|
|
201
|
+
{
|
|
202
|
+
"trigger": "lock_down_successful",
|
|
203
|
+
"source": state_machine.going_to_lockdown_state,
|
|
204
|
+
"dest": state_machine.lockdown_state,
|
|
205
|
+
"before": def_transition(state_machine, finish_mission),
|
|
206
|
+
},
|
|
162
207
|
]
|
|
163
208
|
return mission_transitions
|