isar 1.33.9__py3-none-any.whl → 1.34.1__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/models/models.py +2 -5
- isar/config/settings.py +0 -7
- isar/models/events.py +9 -10
- isar/modules.py +5 -11
- isar/robot/robot.py +109 -24
- isar/robot/robot_monitor_mission.py +399 -0
- isar/robot/robot_status.py +0 -10
- isar/robot/robot_stop_mission.py +7 -7
- isar/robot/robot_upload_inspection.py +80 -0
- isar/services/utilities/scheduling_utilities.py +30 -10
- isar/state_machine/state_machine.py +7 -223
- isar/state_machine/states/going_to_lockdown.py +23 -34
- isar/state_machine/states/home.py +4 -9
- isar/state_machine/states/monitor.py +20 -38
- isar/state_machine/states/paused.py +2 -2
- isar/state_machine/states/pausing.py +6 -22
- isar/state_machine/states/pausing_return_home.py +6 -22
- isar/state_machine/states/returning_home.py +40 -37
- isar/state_machine/states/stopping.py +2 -22
- isar/state_machine/states/stopping_go_to_lockdown.py +1 -21
- isar/state_machine/states/stopping_return_home.py +0 -2
- isar/state_machine/transitions/functions/fail_mission.py +1 -9
- isar/state_machine/transitions/functions/finish_mission.py +2 -32
- isar/state_machine/transitions/functions/pause.py +8 -7
- isar/state_machine/transitions/functions/resume.py +3 -12
- isar/state_machine/transitions/functions/return_home.py +1 -16
- isar/state_machine/transitions/functions/robot_status.py +7 -12
- isar/state_machine/transitions/functions/start_mission.py +2 -44
- isar/state_machine/transitions/functions/stop.py +4 -33
- isar/state_machine/transitions/mission.py +2 -17
- isar/state_machine/transitions/return_home.py +3 -24
- isar/state_machine/transitions/robot_status.py +9 -0
- isar/state_machine/utils/common_event_handlers.py +4 -96
- {isar-1.33.9.dist-info → isar-1.34.1.dist-info}/METADATA +1 -63
- {isar-1.33.9.dist-info → isar-1.34.1.dist-info}/RECORD +41 -42
- robot_interface/models/mission/task.py +0 -10
- robot_interface/robot_interface.py +25 -1
- isar/mission_planner/sequential_task_selector.py +0 -23
- isar/mission_planner/task_selector_interface.py +0 -31
- isar/robot/robot_task_status.py +0 -87
- {isar-1.33.9.dist-info → isar-1.34.1.dist-info}/WHEEL +0 -0
- {isar-1.33.9.dist-info → isar-1.34.1.dist-info}/entry_points.txt +0 -0
- {isar-1.33.9.dist-info → isar-1.34.1.dist-info}/licenses/LICENSE +0 -0
- {isar-1.33.9.dist-info → isar-1.34.1.dist-info}/top_level.txt +0 -0
|
@@ -3,15 +3,10 @@ from typing import TYPE_CHECKING, Callable, List, Optional
|
|
|
3
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
|
-
from isar.state_machine.utils.common_event_handlers import
|
|
7
|
-
|
|
8
|
-
mission_started_event_handler,
|
|
9
|
-
task_status_event_handler,
|
|
10
|
-
task_status_failed_event_handler,
|
|
11
|
-
)
|
|
12
|
-
from robot_interface.models.exceptions.robot_exceptions import ErrorMessage, ErrorReason
|
|
6
|
+
from isar.state_machine.utils.common_event_handlers import mission_started_event_handler
|
|
7
|
+
from robot_interface.models.exceptions.robot_exceptions import ErrorMessage
|
|
13
8
|
from robot_interface.models.mission.mission import Mission
|
|
14
|
-
from robot_interface.models.mission.status import
|
|
9
|
+
from robot_interface.models.mission.status import MissionStatus
|
|
15
10
|
|
|
16
11
|
if TYPE_CHECKING:
|
|
17
12
|
from isar.state_machine.state_machine import StateMachine
|
|
@@ -29,20 +24,6 @@ class ReturningHome(EventHandlerBase):
|
|
|
29
24
|
|
|
30
25
|
return state_machine.pause_return_home # type: ignore
|
|
31
26
|
|
|
32
|
-
def _handle_task_completed(status: TaskStatus):
|
|
33
|
-
if status != TaskStatus.Successful:
|
|
34
|
-
state_machine.current_mission.error_message = ErrorMessage(
|
|
35
|
-
error_reason=ErrorReason.RobotActionException,
|
|
36
|
-
error_description="Return home failed.",
|
|
37
|
-
)
|
|
38
|
-
self.failed_return_home_attemps += 1
|
|
39
|
-
return state_machine.return_home_failed # type: ignore
|
|
40
|
-
|
|
41
|
-
if not state_machine.battery_level_is_above_mission_start_threshold():
|
|
42
|
-
return state_machine.starting_recharging # type: ignore
|
|
43
|
-
else:
|
|
44
|
-
return state_machine.returned_home # type: ignore
|
|
45
|
-
|
|
46
27
|
def _start_mission_event_handler(
|
|
47
28
|
event: Event[Mission],
|
|
48
29
|
) -> Optional[Callable]:
|
|
@@ -63,6 +44,27 @@ class ReturningHome(EventHandlerBase):
|
|
|
63
44
|
|
|
64
45
|
return state_machine.stop_return_home # type: ignore
|
|
65
46
|
|
|
47
|
+
def _mission_status_event_handler(
|
|
48
|
+
event: Event[MissionStatus],
|
|
49
|
+
) -> Optional[Callable]:
|
|
50
|
+
mission_status: Optional[MissionStatus] = event.consume_event()
|
|
51
|
+
|
|
52
|
+
if mission_status and mission_status not in [
|
|
53
|
+
MissionStatus.InProgress,
|
|
54
|
+
MissionStatus.NotStarted,
|
|
55
|
+
MissionStatus.Paused,
|
|
56
|
+
]:
|
|
57
|
+
if mission_status != MissionStatus.Successful:
|
|
58
|
+
self.failed_return_home_attemps += 1
|
|
59
|
+
return state_machine.return_home_failed # type: ignore
|
|
60
|
+
|
|
61
|
+
self.failed_return_home_attemps = 0
|
|
62
|
+
if not state_machine.battery_level_is_above_mission_start_threshold():
|
|
63
|
+
return state_machine.starting_recharging # type: ignore
|
|
64
|
+
else:
|
|
65
|
+
return state_machine.returned_home # type: ignore
|
|
66
|
+
return None
|
|
67
|
+
|
|
66
68
|
def _send_to_lockdown_event_handler(
|
|
67
69
|
event: Event[bool],
|
|
68
70
|
) -> Optional[Callable]:
|
|
@@ -75,6 +77,18 @@ class ReturningHome(EventHandlerBase):
|
|
|
75
77
|
)
|
|
76
78
|
return state_machine.go_to_lockdown # type: ignore
|
|
77
79
|
|
|
80
|
+
def _mission_failed_event_handler(
|
|
81
|
+
event: Event[Optional[ErrorMessage]],
|
|
82
|
+
) -> Optional[Callable]:
|
|
83
|
+
mission_failed: Optional[ErrorMessage] = event.consume_event()
|
|
84
|
+
if mission_failed is not None:
|
|
85
|
+
state_machine.logger.warning(
|
|
86
|
+
f"Failed to initiate return home because: "
|
|
87
|
+
f"{mission_failed.error_description}"
|
|
88
|
+
)
|
|
89
|
+
return state_machine.return_home_failed # type: ignore
|
|
90
|
+
return None
|
|
91
|
+
|
|
78
92
|
event_handlers: List[EventHandlerMapping] = [
|
|
79
93
|
EventHandlerMapping(
|
|
80
94
|
name="pause_mission_event",
|
|
@@ -91,9 +105,7 @@ class ReturningHome(EventHandlerBase):
|
|
|
91
105
|
EventHandlerMapping(
|
|
92
106
|
name="mission_failed_event",
|
|
93
107
|
event=events.robot_service_events.mission_failed,
|
|
94
|
-
handler=
|
|
95
|
-
state_machine, event
|
|
96
|
-
),
|
|
108
|
+
handler=_mission_failed_event_handler,
|
|
97
109
|
),
|
|
98
110
|
EventHandlerMapping(
|
|
99
111
|
name="start_mission_event",
|
|
@@ -101,18 +113,9 @@ class ReturningHome(EventHandlerBase):
|
|
|
101
113
|
handler=_start_mission_event_handler,
|
|
102
114
|
),
|
|
103
115
|
EventHandlerMapping(
|
|
104
|
-
name="
|
|
105
|
-
event=events.robot_service_events.
|
|
106
|
-
handler=
|
|
107
|
-
state_machine, _handle_task_completed, event
|
|
108
|
-
),
|
|
109
|
-
),
|
|
110
|
-
EventHandlerMapping(
|
|
111
|
-
name="task_status_event",
|
|
112
|
-
event=events.robot_service_events.task_status_updated,
|
|
113
|
-
handler=lambda event: task_status_event_handler(
|
|
114
|
-
state_machine, _handle_task_completed, event
|
|
115
|
-
),
|
|
116
|
+
name="mission_status_event",
|
|
117
|
+
event=events.robot_service_events.mission_status_updated,
|
|
118
|
+
handler=_mission_status_event_handler,
|
|
116
119
|
),
|
|
117
120
|
EventHandlerMapping(
|
|
118
121
|
name="send_to_lockdown_event",
|
|
@@ -4,7 +4,6 @@ from isar.apis.models.models import ControlMissionResponse
|
|
|
4
4
|
from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
|
|
5
5
|
from isar.models.events import Event
|
|
6
6
|
from robot_interface.models.exceptions.robot_exceptions import ErrorMessage
|
|
7
|
-
from robot_interface.models.mission.status import MissionStatus, TaskStatus
|
|
8
7
|
|
|
9
8
|
if TYPE_CHECKING:
|
|
10
9
|
from isar.state_machine.state_machine import StateMachine
|
|
@@ -16,29 +15,10 @@ class Stopping(EventHandlerBase):
|
|
|
16
15
|
events = state_machine.events
|
|
17
16
|
|
|
18
17
|
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
|
-
stopped_mission_response: ControlMissionResponse = (
|
|
35
|
-
state_machine._make_control_mission_response()
|
|
36
|
-
)
|
|
37
18
|
state_machine.events.api_requests.stop_mission.response.trigger_event(
|
|
38
|
-
|
|
19
|
+
ControlMissionResponse(success=True)
|
|
39
20
|
)
|
|
40
|
-
state_machine.
|
|
41
|
-
state_machine._finalize()
|
|
21
|
+
state_machine.print_transitions()
|
|
42
22
|
return None
|
|
43
23
|
|
|
44
24
|
def _failed_stop_event_handler(
|
|
@@ -4,7 +4,6 @@ from isar.apis.models.models import LockdownResponse
|
|
|
4
4
|
from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
|
|
5
5
|
from isar.models.events import Event
|
|
6
6
|
from robot_interface.models.exceptions.robot_exceptions import ErrorMessage
|
|
7
|
-
from robot_interface.models.mission.status import MissionStatus, TaskStatus
|
|
8
7
|
|
|
9
8
|
if TYPE_CHECKING:
|
|
10
9
|
from isar.state_machine.state_machine import StateMachine
|
|
@@ -15,25 +14,6 @@ class StoppingGoToLockdown(EventHandlerBase):
|
|
|
15
14
|
def __init__(self, state_machine: "StateMachine"):
|
|
16
15
|
events = state_machine.events
|
|
17
16
|
|
|
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
17
|
def _failed_stop_event_handler(
|
|
38
18
|
event: Event[ErrorMessage],
|
|
39
19
|
) -> Optional[Callable]:
|
|
@@ -54,7 +34,7 @@ class StoppingGoToLockdown(EventHandlerBase):
|
|
|
54
34
|
return None
|
|
55
35
|
|
|
56
36
|
state_machine.publish_mission_aborted("Robot being sent to lockdown", True)
|
|
57
|
-
|
|
37
|
+
|
|
58
38
|
events.api_requests.send_to_lockdown.response.trigger_event(
|
|
59
39
|
LockdownResponse(lockdown_started=True)
|
|
60
40
|
)
|
|
@@ -45,8 +45,6 @@ class StoppingReturnHome(EventHandlerBase):
|
|
|
45
45
|
state_machine.events.api_requests.start_mission.request.consume_event()
|
|
46
46
|
)
|
|
47
47
|
|
|
48
|
-
state_machine.reset_state_machine()
|
|
49
|
-
|
|
50
48
|
if mission:
|
|
51
49
|
state_machine.start_mission(mission=mission)
|
|
52
50
|
return state_machine.request_mission_start # type: ignore
|
|
@@ -3,21 +3,13 @@ from typing import TYPE_CHECKING
|
|
|
3
3
|
if TYPE_CHECKING:
|
|
4
4
|
from isar.state_machine.state_machine import StateMachine
|
|
5
5
|
|
|
6
|
-
from robot_interface.models.mission.status import MissionStatus, TaskStatus
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def report_failed_mission_and_finalize(state_machine: "StateMachine") -> None:
|
|
10
|
-
state_machine.current_task.status = TaskStatus.Failed
|
|
11
|
-
state_machine.current_mission.status = MissionStatus.Failed
|
|
12
|
-
state_machine.publish_task_status(task=state_machine.current_task)
|
|
13
|
-
state_machine._finalize()
|
|
14
|
-
|
|
15
6
|
|
|
16
7
|
def report_failed_return_home_and_intervention_needed(
|
|
17
8
|
state_machine: "StateMachine",
|
|
18
9
|
) -> None:
|
|
19
10
|
error_message: str = "Return home failed."
|
|
20
11
|
state_machine.publish_intervention_needed(error_message=error_message)
|
|
12
|
+
state_machine.print_transitions()
|
|
21
13
|
|
|
22
14
|
|
|
23
15
|
def report_failed_lockdown_and_intervention_needed(
|
|
@@ -1,39 +1,9 @@
|
|
|
1
|
-
from typing import TYPE_CHECKING
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
2
2
|
|
|
3
3
|
if TYPE_CHECKING:
|
|
4
4
|
from isar.state_machine.state_machine import StateMachine
|
|
5
5
|
|
|
6
|
-
from robot_interface.models.exceptions.robot_exceptions import ErrorMessage
|
|
7
|
-
from robot_interface.models.mission.status import MissionStatus, TaskStatus
|
|
8
|
-
|
|
9
6
|
|
|
10
7
|
def finish_mission(state_machine: "StateMachine") -> bool:
|
|
11
|
-
|
|
12
|
-
TaskStatus.Cancelled,
|
|
13
|
-
TaskStatus.Failed,
|
|
14
|
-
]
|
|
15
|
-
partially_fail_statuses = fail_statuses + [TaskStatus.PartiallySuccessful]
|
|
16
|
-
|
|
17
|
-
if len(state_machine.current_mission.tasks) == 0:
|
|
18
|
-
state_machine.current_mission.status = MissionStatus.Successful
|
|
19
|
-
elif all(
|
|
20
|
-
task.status in fail_statuses for task in state_machine.current_mission.tasks
|
|
21
|
-
):
|
|
22
|
-
state_machine.current_mission.error_message = ErrorMessage(
|
|
23
|
-
error_reason=None,
|
|
24
|
-
error_description="The mission failed because all tasks in the mission "
|
|
25
|
-
"failed",
|
|
26
|
-
)
|
|
27
|
-
state_machine.current_mission.status = MissionStatus.Failed
|
|
28
|
-
elif any(
|
|
29
|
-
task.status in partially_fail_statuses
|
|
30
|
-
for task in state_machine.current_mission.tasks
|
|
31
|
-
):
|
|
32
|
-
state_machine.current_mission.status = MissionStatus.PartiallySuccessful
|
|
33
|
-
else:
|
|
34
|
-
state_machine.current_mission.status = MissionStatus.Successful
|
|
35
|
-
state_machine._finalize()
|
|
36
|
-
|
|
37
|
-
state_machine.current_task = None
|
|
38
|
-
state_machine.send_task_status()
|
|
8
|
+
state_machine.print_transitions()
|
|
39
9
|
return True
|
|
@@ -12,18 +12,19 @@ def trigger_pause_mission_event(state_machine: "StateMachine") -> bool:
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
def pause_mission_failed(state_machine: "StateMachine") -> bool:
|
|
15
|
-
paused_mission_response: ControlMissionResponse = (
|
|
16
|
-
state_machine._make_control_mission_response()
|
|
17
|
-
)
|
|
18
15
|
state_machine.events.api_requests.pause_mission.response.trigger_event(
|
|
19
|
-
|
|
16
|
+
ControlMissionResponse(
|
|
17
|
+
success=False, failure_reason="Failed to pause mission in ISAR"
|
|
18
|
+
)
|
|
20
19
|
)
|
|
21
20
|
return True
|
|
22
21
|
|
|
23
22
|
|
|
24
|
-
def
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
def pause_return_home_mission_failed(state_machine: "StateMachine") -> bool:
|
|
24
|
+
if state_machine.events.api_requests.start_mission.request.has_event():
|
|
25
|
+
return True
|
|
26
|
+
paused_mission_response: ControlMissionResponse = ControlMissionResponse(
|
|
27
|
+
success=False, failure_reason="ISAR failed to pause return home"
|
|
27
28
|
)
|
|
28
29
|
state_machine.events.api_requests.pause_mission.response.trigger_event(
|
|
29
30
|
paused_mission_response
|
|
@@ -11,11 +11,10 @@ from robot_interface.models.exceptions.robot_exceptions import (
|
|
|
11
11
|
RobotActionException,
|
|
12
12
|
RobotException,
|
|
13
13
|
)
|
|
14
|
-
from robot_interface.models.mission.status import MissionStatus, TaskStatus
|
|
15
14
|
|
|
16
15
|
|
|
17
16
|
def resume_mission(state_machine: "StateMachine") -> bool:
|
|
18
|
-
state_machine.logger.info("Resuming mission
|
|
17
|
+
state_machine.logger.info("Resuming mission")
|
|
19
18
|
|
|
20
19
|
max_retries = settings.STATE_TRANSITION_NUM_RETIRES
|
|
21
20
|
retry_interval = settings.STATE_TRANSITION_RETRY_INTERVAL_SEC
|
|
@@ -23,17 +22,9 @@ def resume_mission(state_machine: "StateMachine") -> bool:
|
|
|
23
22
|
for attempt in range(max_retries):
|
|
24
23
|
try:
|
|
25
24
|
state_machine.robot.resume()
|
|
26
|
-
state_machine.current_mission.status = MissionStatus.InProgress
|
|
27
|
-
state_machine.current_mission.error_message = None
|
|
28
|
-
state_machine.current_task.status = TaskStatus.InProgress
|
|
29
25
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
state_machine.publish_mission_status()
|
|
33
|
-
state_machine.publish_task_status(task=state_machine.current_task)
|
|
34
|
-
|
|
35
|
-
resume_mission_response: ControlMissionResponse = (
|
|
36
|
-
state_machine._make_control_mission_response()
|
|
26
|
+
resume_mission_response: ControlMissionResponse = ControlMissionResponse(
|
|
27
|
+
success=True
|
|
37
28
|
)
|
|
38
29
|
state_machine.events.api_requests.resume_mission.response.trigger_event(
|
|
39
30
|
resume_mission_response
|
|
@@ -7,7 +7,7 @@ from typing import TYPE_CHECKING
|
|
|
7
7
|
|
|
8
8
|
from isar.config.settings import settings
|
|
9
9
|
from robot_interface.models.mission.mission import Mission
|
|
10
|
-
from robot_interface.models.mission.status import
|
|
10
|
+
from robot_interface.models.mission.status import RobotStatus
|
|
11
11
|
from robot_interface.models.mission.task import ReturnToHome
|
|
12
12
|
|
|
13
13
|
if TYPE_CHECKING:
|
|
@@ -37,18 +37,3 @@ def should_retry_return_home(state_machine: "StateMachine") -> bool:
|
|
|
37
37
|
def reset_return_home_failure_counter(state_machine: "StateMachine") -> bool:
|
|
38
38
|
state_machine.returning_home_state.failed_return_home_attemps = 0
|
|
39
39
|
return True
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def set_return_home_status(state_machine: "StateMachine") -> bool:
|
|
43
|
-
state_machine.log_mission_overview(mission=state_machine.current_mission)
|
|
44
|
-
state_machine.current_mission.status = MissionStatus.InProgress
|
|
45
|
-
|
|
46
|
-
state_machine.current_task = state_machine.task_selector.next_task()
|
|
47
|
-
state_machine.current_task.status = TaskStatus.InProgress
|
|
48
|
-
|
|
49
|
-
return True
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
def return_home_finished(state_machine: "StateMachine") -> bool:
|
|
53
|
-
state_machine.reset_state_machine()
|
|
54
|
-
return True
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import time
|
|
2
1
|
from typing import TYPE_CHECKING
|
|
3
2
|
|
|
4
|
-
from isar.config.settings import settings
|
|
5
3
|
from robot_interface.models.mission.status import RobotStatus
|
|
6
4
|
|
|
7
5
|
if TYPE_CHECKING:
|
|
@@ -13,6 +11,11 @@ def is_offline(state_machine: "StateMachine") -> bool:
|
|
|
13
11
|
return robot_status == RobotStatus.Offline
|
|
14
12
|
|
|
15
13
|
|
|
14
|
+
def is_available(state_machine: "StateMachine") -> bool:
|
|
15
|
+
robot_status = state_machine.shared_state.robot_status.check()
|
|
16
|
+
return robot_status == RobotStatus.Available
|
|
17
|
+
|
|
18
|
+
|
|
16
19
|
def is_available_or_home(state_machine: "StateMachine") -> bool:
|
|
17
20
|
robot_status = state_machine.shared_state.robot_status.check()
|
|
18
21
|
return robot_status == RobotStatus.Available or robot_status == RobotStatus.Home
|
|
@@ -24,13 +27,5 @@ def is_blocked_protective_stop(state_machine: "StateMachine") -> bool:
|
|
|
24
27
|
|
|
25
28
|
|
|
26
29
|
def clear_robot_status(state_machine: "StateMachine") -> bool:
|
|
27
|
-
state_machine.events.
|
|
28
|
-
|
|
29
|
-
while time.time() - start_time < settings.CLEAR_ROBOT_STATUS_TIMEOUT:
|
|
30
|
-
if (
|
|
31
|
-
state_machine.events.robot_service_events.robot_status_cleared.consume_event()
|
|
32
|
-
):
|
|
33
|
-
return True
|
|
34
|
-
time.sleep(settings.FSM_SLEEP_TIME)
|
|
35
|
-
state_machine.logger.error("Timed out waiting for robot status to be cleared")
|
|
36
|
-
return False
|
|
30
|
+
state_machine.events.robot_service_events.robot_status_changed.clear_event()
|
|
31
|
+
return True
|
|
@@ -5,11 +5,9 @@ if TYPE_CHECKING:
|
|
|
5
5
|
|
|
6
6
|
from isar.apis.models.models import MissionStartResponse
|
|
7
7
|
from robot_interface.models.exceptions.robot_exceptions import (
|
|
8
|
-
ErrorMessage,
|
|
9
8
|
RobotException,
|
|
10
9
|
RobotInitializeException,
|
|
11
10
|
)
|
|
12
|
-
from robot_interface.models.mission.status import MissionStatus, TaskStatus
|
|
13
11
|
|
|
14
12
|
|
|
15
13
|
def acknowledge_mission(state_machine: "StateMachine") -> bool:
|
|
@@ -19,59 +17,19 @@ def acknowledge_mission(state_machine: "StateMachine") -> bool:
|
|
|
19
17
|
return True
|
|
20
18
|
|
|
21
19
|
|
|
22
|
-
def prepare_state_machine_before_mission(state_machine: "StateMachine") -> bool:
|
|
23
|
-
state_machine.logger.info(
|
|
24
|
-
"Initiating mission:\n"
|
|
25
|
-
f" Mission ID: {state_machine.current_mission.id}\n"
|
|
26
|
-
f" Mission Name: {state_machine.current_mission.name}\n"
|
|
27
|
-
f" Number of Tasks: {len(state_machine.current_mission.tasks)}"
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
state_machine.current_mission.status = MissionStatus.InProgress
|
|
31
|
-
state_machine.publish_mission_status()
|
|
32
|
-
state_machine.current_task = state_machine.task_selector.next_task()
|
|
33
|
-
state_machine.send_task_status()
|
|
34
|
-
if state_machine.current_task is None:
|
|
35
|
-
return False
|
|
36
|
-
|
|
37
|
-
state_machine.current_task.status = TaskStatus.InProgress
|
|
38
|
-
state_machine.publish_task_status(task=state_machine.current_task)
|
|
39
|
-
return True
|
|
40
|
-
|
|
41
|
-
|
|
42
20
|
def initialize_robot(state_machine: "StateMachine") -> bool:
|
|
43
21
|
try:
|
|
44
22
|
state_machine.robot.initialize()
|
|
45
23
|
except (RobotInitializeException, RobotException) as e:
|
|
46
|
-
state_machine.current_task.error_message = ErrorMessage(
|
|
47
|
-
error_reason=e.error_reason, error_description=e.error_description
|
|
48
|
-
)
|
|
49
24
|
state_machine.logger.error(
|
|
50
25
|
f"Failed to initialize robot because: {e.error_description}"
|
|
51
26
|
)
|
|
52
27
|
_initialization_failed(state_machine)
|
|
28
|
+
state_machine.print_transitions()
|
|
53
29
|
return False
|
|
54
30
|
return True
|
|
55
31
|
|
|
56
32
|
|
|
57
|
-
def set_mission_to_in_progress(state_machine: "StateMachine") -> bool:
|
|
58
|
-
state_machine.current_mission.status = MissionStatus.InProgress
|
|
59
|
-
state_machine.publish_task_status(task=state_machine.current_task)
|
|
60
|
-
state_machine.logger.info(
|
|
61
|
-
f"Successfully initiated "
|
|
62
|
-
f"{type(state_machine.current_task).__name__} "
|
|
63
|
-
f"task: {str(state_machine.current_task.id)[:8]}"
|
|
64
|
-
)
|
|
65
|
-
return True
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def trigger_start_mission_event(state_machine: "StateMachine") -> bool:
|
|
69
|
-
state_machine.events.state_machine_events.start_mission.trigger_event(
|
|
70
|
-
state_machine.current_mission
|
|
71
|
-
)
|
|
72
|
-
return True
|
|
73
|
-
|
|
74
|
-
|
|
75
33
|
def _initialization_failed(state_machine: "StateMachine") -> None:
|
|
76
34
|
state_machine.events.api_requests.start_mission.response.trigger_event(
|
|
77
35
|
MissionStartResponse(
|
|
@@ -79,4 +37,4 @@ def _initialization_failed(state_machine: "StateMachine") -> None:
|
|
|
79
37
|
mission_not_started_reason="Failed to initialize robot",
|
|
80
38
|
)
|
|
81
39
|
)
|
|
82
|
-
state_machine.
|
|
40
|
+
state_machine.print_transitions()
|
|
@@ -4,7 +4,6 @@ if TYPE_CHECKING:
|
|
|
4
4
|
from isar.state_machine.state_machine import StateMachine
|
|
5
5
|
|
|
6
6
|
from isar.apis.models.models import ControlMissionResponse
|
|
7
|
-
from robot_interface.models.mission.status import MissionStatus, TaskStatus
|
|
8
7
|
|
|
9
8
|
|
|
10
9
|
def trigger_stop_mission_event(state_machine: "StateMachine") -> bool:
|
|
@@ -13,8 +12,8 @@ def trigger_stop_mission_event(state_machine: "StateMachine") -> bool:
|
|
|
13
12
|
|
|
14
13
|
|
|
15
14
|
def stop_mission_failed(state_machine: "StateMachine") -> bool:
|
|
16
|
-
stopped_mission_response: ControlMissionResponse = (
|
|
17
|
-
|
|
15
|
+
stopped_mission_response: ControlMissionResponse = ControlMissionResponse(
|
|
16
|
+
success=False, failure_reason="ISAR failed to stop mission"
|
|
18
17
|
)
|
|
19
18
|
state_machine.events.api_requests.stop_mission.response.trigger_event(
|
|
20
19
|
stopped_mission_response
|
|
@@ -22,39 +21,11 @@ def stop_mission_failed(state_machine: "StateMachine") -> bool:
|
|
|
22
21
|
return True
|
|
23
22
|
|
|
24
23
|
|
|
25
|
-
def stop_return_home_mission_cleanup(state_machine: "StateMachine") -> bool:
|
|
26
|
-
if state_machine.current_mission is None:
|
|
27
|
-
state_machine._queue_empty_response()
|
|
28
|
-
state_machine.reset_state_machine()
|
|
29
|
-
return True
|
|
30
|
-
|
|
31
|
-
if not state_machine.events.api_requests.start_mission.request.has_event():
|
|
32
|
-
state_machine.current_mission.status = MissionStatus.Cancelled
|
|
33
|
-
|
|
34
|
-
for task in state_machine.current_mission.tasks:
|
|
35
|
-
if task.status in [
|
|
36
|
-
TaskStatus.NotStarted,
|
|
37
|
-
TaskStatus.InProgress,
|
|
38
|
-
TaskStatus.Paused,
|
|
39
|
-
]:
|
|
40
|
-
task.status = TaskStatus.Cancelled
|
|
41
|
-
|
|
42
|
-
stopped_mission_response: ControlMissionResponse = (
|
|
43
|
-
state_machine._make_control_mission_response()
|
|
44
|
-
)
|
|
45
|
-
state_machine.events.api_requests.stop_mission.response.trigger_event(
|
|
46
|
-
stopped_mission_response
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
state_machine._finalize()
|
|
50
|
-
return True
|
|
51
|
-
|
|
52
|
-
|
|
53
24
|
def stop_return_home_mission_failed(state_machine: "StateMachine") -> bool:
|
|
54
25
|
if state_machine.events.api_requests.start_mission.request.has_event():
|
|
55
26
|
return True
|
|
56
|
-
stopped_mission_response: ControlMissionResponse = (
|
|
57
|
-
|
|
27
|
+
stopped_mission_response: ControlMissionResponse = ControlMissionResponse(
|
|
28
|
+
success=False, failure_reason="ISAR failed to stop return home"
|
|
58
29
|
)
|
|
59
30
|
state_machine.events.api_requests.stop_mission.response.trigger_event(
|
|
60
31
|
stopped_mission_response
|
|
@@ -1,24 +1,18 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING, List
|
|
2
2
|
|
|
3
|
-
from isar.state_machine.transitions.functions.fail_mission import (
|
|
4
|
-
report_failed_mission_and_finalize,
|
|
5
|
-
)
|
|
6
3
|
from isar.state_machine.transitions.functions.finish_mission import finish_mission
|
|
7
4
|
from isar.state_machine.transitions.functions.pause import (
|
|
8
5
|
pause_mission_failed,
|
|
6
|
+
pause_return_home_mission_failed,
|
|
9
7
|
trigger_pause_mission_event,
|
|
10
8
|
)
|
|
11
9
|
from isar.state_machine.transitions.functions.resume import resume_mission
|
|
12
10
|
from isar.state_machine.transitions.functions.return_home import (
|
|
13
11
|
reset_return_home_failure_counter,
|
|
14
|
-
return_home_finished,
|
|
15
12
|
)
|
|
16
13
|
from isar.state_machine.transitions.functions.start_mission import (
|
|
17
14
|
acknowledge_mission,
|
|
18
15
|
initialize_robot,
|
|
19
|
-
prepare_state_machine_before_mission,
|
|
20
|
-
set_mission_to_in_progress,
|
|
21
|
-
trigger_start_mission_event,
|
|
22
16
|
)
|
|
23
17
|
from isar.state_machine.transitions.functions.stop import (
|
|
24
18
|
stop_mission_failed,
|
|
@@ -63,7 +57,7 @@ def get_mission_transitions(state_machine: "StateMachine") -> List[dict]:
|
|
|
63
57
|
"trigger": "return_home_mission_pausing_failed",
|
|
64
58
|
"source": state_machine.pausing_return_home_state,
|
|
65
59
|
"dest": state_machine.returning_home_state,
|
|
66
|
-
"before": def_transition(state_machine,
|
|
60
|
+
"before": def_transition(state_machine, pause_return_home_mission_failed),
|
|
67
61
|
},
|
|
68
62
|
{
|
|
69
63
|
"trigger": "return_home_mission_paused",
|
|
@@ -126,7 +120,6 @@ def get_mission_transitions(state_machine: "StateMachine") -> List[dict]:
|
|
|
126
120
|
"before": [
|
|
127
121
|
def_transition(state_machine, trigger_stop_mission_event),
|
|
128
122
|
def_transition(state_machine, reset_return_home_failure_counter),
|
|
129
|
-
def_transition(state_machine, return_home_finished),
|
|
130
123
|
],
|
|
131
124
|
},
|
|
132
125
|
{
|
|
@@ -166,31 +159,23 @@ def get_mission_transitions(state_machine: "StateMachine") -> List[dict]:
|
|
|
166
159
|
"dest": state_machine.monitor_state,
|
|
167
160
|
"prepare": def_transition(state_machine, acknowledge_mission),
|
|
168
161
|
"conditions": [
|
|
169
|
-
def_transition(state_machine, prepare_state_machine_before_mission),
|
|
170
162
|
def_transition(state_machine, initialize_robot),
|
|
171
163
|
],
|
|
172
|
-
"before": [
|
|
173
|
-
def_transition(state_machine, set_mission_to_in_progress),
|
|
174
|
-
def_transition(state_machine, trigger_start_mission_event),
|
|
175
|
-
],
|
|
176
164
|
},
|
|
177
165
|
{
|
|
178
166
|
"trigger": "request_mission_start",
|
|
179
167
|
"source": state_machine.await_next_mission_state,
|
|
180
168
|
"dest": state_machine.await_next_mission_state,
|
|
181
|
-
"before": def_transition(state_machine, report_failed_mission_and_finalize),
|
|
182
169
|
},
|
|
183
170
|
{
|
|
184
171
|
"trigger": "request_mission_start",
|
|
185
172
|
"source": state_machine.home_state,
|
|
186
173
|
"dest": state_machine.home_state,
|
|
187
|
-
"before": def_transition(state_machine, report_failed_mission_and_finalize),
|
|
188
174
|
},
|
|
189
175
|
{
|
|
190
176
|
"trigger": "mission_failed_to_start",
|
|
191
177
|
"source": [state_machine.monitor_state, state_machine.returning_home_state],
|
|
192
178
|
"dest": state_machine.await_next_mission_state,
|
|
193
|
-
"before": def_transition(state_machine, report_failed_mission_and_finalize),
|
|
194
179
|
},
|
|
195
180
|
{
|
|
196
181
|
"trigger": "mission_finished",
|