isar 1.26.4__py3-none-any.whl → 1.27.0__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.

Files changed (44) hide show
  1. isar/apis/api.py +25 -0
  2. isar/apis/models/start_mission_definition.py +1 -7
  3. isar/apis/schedule/scheduling_controller.py +17 -1
  4. isar/config/settings.py +4 -1
  5. isar/models/communication/queues/events.py +1 -0
  6. isar/models/communication/queues/queue_utils.py +6 -0
  7. isar/modules.py +13 -6
  8. isar/robot/robot.py +10 -1
  9. isar/robot/robot_status.py +11 -5
  10. isar/services/utilities/scheduling_utilities.py +60 -7
  11. isar/state_machine/state_machine.py +51 -121
  12. isar/state_machine/states/await_next_mission.py +92 -0
  13. isar/state_machine/states/blocked_protective_stop.py +2 -5
  14. isar/state_machine/states/home.py +87 -0
  15. isar/state_machine/states/monitor.py +8 -3
  16. isar/state_machine/states/offline.py +3 -5
  17. isar/state_machine/states/returning_home.py +186 -0
  18. isar/state_machine/states/{idle.py → robot_standing_still.py} +20 -8
  19. isar/state_machine/states/{stop.py → stopping.py} +16 -4
  20. isar/state_machine/states/unknown_status.py +74 -0
  21. isar/state_machine/states_enum.py +6 -3
  22. isar/state_machine/transitions/functions/return_home.py +38 -0
  23. isar/state_machine/transitions/functions/robot_status.py +27 -0
  24. isar/state_machine/transitions/{start_mission.py → functions/start_mission.py} +1 -1
  25. isar/state_machine/transitions/mission.py +119 -0
  26. isar/state_machine/transitions/return_home.py +69 -0
  27. isar/state_machine/transitions/robot_status.py +73 -0
  28. {isar-1.26.4.dist-info → isar-1.27.0.dist-info}/METADATA +14 -7
  29. {isar-1.26.4.dist-info → isar-1.27.0.dist-info}/RECORD +43 -35
  30. {isar-1.26.4.dist-info → isar-1.27.0.dist-info}/WHEEL +1 -1
  31. robot_interface/models/exceptions/robot_exceptions.py +14 -0
  32. robot_interface/models/mission/mission.py +8 -1
  33. robot_interface/models/mission/status.py +2 -0
  34. robot_interface/models/mission/task.py +0 -1
  35. isar/state_machine/states/off.py +0 -18
  36. /isar/state_machine/transitions/{fail_mission.py → functions/fail_mission.py} +0 -0
  37. /isar/state_machine/transitions/{finish_mission.py → functions/finish_mission.py} +0 -0
  38. /isar/state_machine/transitions/{pause.py → functions/pause.py} +0 -0
  39. /isar/state_machine/transitions/{resume.py → functions/resume.py} +0 -0
  40. /isar/state_machine/transitions/{stop.py → functions/stop.py} +0 -0
  41. /isar/state_machine/transitions/{utils.py → functions/utils.py} +0 -0
  42. {isar-1.26.4.dist-info → isar-1.27.0.dist-info}/entry_points.txt +0 -0
  43. {isar-1.26.4.dist-info → isar-1.27.0.dist-info}/licenses/LICENSE +0 -0
  44. {isar-1.26.4.dist-info → isar-1.27.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,87 @@
1
+ import logging
2
+ import time
3
+ from queue import Queue
4
+ from typing import TYPE_CHECKING, Optional
5
+
6
+ from transitions import State
7
+
8
+ from isar.models.communication.message import StartMissionMessage
9
+ from isar.models.communication.queues.queue_io import QueueIO
10
+ from isar.models.communication.queues.queue_utils import (
11
+ check_for_event,
12
+ check_shared_state,
13
+ )
14
+ from isar.models.communication.queues.status_queue import StatusQueue
15
+ from robot_interface.models.mission.status import RobotStatus
16
+
17
+ if TYPE_CHECKING:
18
+ from isar.state_machine.state_machine import StateMachine
19
+
20
+
21
+ class Home(State):
22
+ def __init__(self, state_machine: "StateMachine") -> None:
23
+ super().__init__(name="home", on_enter=self.start, on_exit=self.stop)
24
+ self.state_machine: "StateMachine" = state_machine
25
+ self.logger = logging.getLogger("state_machine")
26
+ self.events = self.state_machine.events
27
+ self.shared_state = self.state_machine.shared_state
28
+ self.signal_state_machine_to_stop = state_machine.signal_state_machine_to_stop
29
+
30
+ def start(self) -> None:
31
+ self.state_machine.update_state()
32
+ self._run()
33
+
34
+ def stop(self) -> None:
35
+ return
36
+
37
+ def _check_and_handle_start_mission_event(
38
+ self, event: Queue[StartMissionMessage]
39
+ ) -> bool:
40
+ start_mission: Optional[StartMissionMessage] = check_for_event(event)
41
+ if start_mission:
42
+ self.state_machine.start_mission(mission=start_mission.mission)
43
+ self.state_machine.request_mission_start() # type: ignore
44
+ return True
45
+ return False
46
+
47
+ def _check_and_handle_return_home_event(self, event: QueueIO) -> bool:
48
+ if check_for_event(event.input):
49
+ event.output.put(True)
50
+ self.state_machine.request_return_home() # type: ignore
51
+ return True
52
+ return False
53
+
54
+ def _check_and_handle_robot_status_event(
55
+ self, event: StatusQueue[RobotStatus]
56
+ ) -> bool:
57
+ robot_status: RobotStatus = check_shared_state(event)
58
+ if robot_status != RobotStatus.Home:
59
+ self.state_machine.robot_status_changed() # type: ignore
60
+ return True
61
+
62
+ return False
63
+
64
+ def _run(self) -> None:
65
+ while True:
66
+ if self.signal_state_machine_to_stop.is_set():
67
+ self.logger.info(
68
+ "Stopping state machine from %s state", self.__class__.__name__
69
+ )
70
+ break
71
+
72
+ if self._check_and_handle_start_mission_event(
73
+ self.events.api_requests.start_mission.input
74
+ ):
75
+ break
76
+
77
+ if self._check_and_handle_return_home_event(
78
+ self.events.api_requests.return_home
79
+ ):
80
+ break
81
+
82
+ if self._check_and_handle_robot_status_event(
83
+ self.shared_state.robot_status
84
+ ):
85
+ break
86
+
87
+ time.sleep(self.state_machine.sleep_time)
@@ -61,9 +61,8 @@ class Monitor(State):
61
61
  return False
62
62
 
63
63
  def _check_and_handle_mission_started_event(self, event: Queue) -> None:
64
- if not self.state_machine.mission_ongoing:
65
- if check_for_event(event):
66
- self.state_machine.mission_ongoing = True
64
+ if check_for_event(event):
65
+ self.state_machine.mission_ongoing = True
67
66
 
68
67
  def _check_and_handle_mission_failed_event(self, event: Queue) -> bool:
69
68
  mission_failed: Optional[ErrorMessage] = check_for_event(event)
@@ -83,6 +82,9 @@ class Monitor(State):
83
82
  return False
84
83
 
85
84
  def _check_and_handle_task_status_failed_event(self, event: Queue) -> bool:
85
+ if not self.state_machine.mission_ongoing:
86
+ return False
87
+
86
88
  task_failure: Optional[ErrorMessage] = check_for_event(event)
87
89
  if task_failure is not None:
88
90
  self.awaiting_task_status = False
@@ -101,6 +103,9 @@ class Monitor(State):
101
103
  return False
102
104
 
103
105
  def _check_and_handle_task_status_event(self, event: Queue) -> bool:
106
+ if not self.state_machine.mission_ongoing:
107
+ return False
108
+
104
109
  status: Optional[TaskStatus] = check_for_event(event)
105
110
  if status is not None:
106
111
  self.awaiting_task_status = False
@@ -37,11 +37,9 @@ class Offline(State):
37
37
  robot_status: RobotStatus = check_shared_state(
38
38
  self.shared_state.robot_status
39
39
  )
40
- if robot_status == RobotStatus.BlockedProtectiveStop:
41
- transition = self.state_machine.robot_protective_stop_engaged # type: ignore
42
- break
43
- elif robot_status != RobotStatus.Offline:
44
- transition = self.state_machine.robot_turned_online # type: ignore
40
+
41
+ if robot_status != RobotStatus.Offline:
42
+ transition = self.state_machine.robot_status_changed # type: ignore
45
43
  break
46
44
 
47
45
  time.sleep(self.state_machine.sleep_time)
@@ -0,0 +1,186 @@
1
+ import logging
2
+ from queue import Queue
3
+ from typing import TYPE_CHECKING, Optional
4
+
5
+ from transitions import State
6
+
7
+ from isar.models.communication.message import StartMissionMessage
8
+ from isar.models.communication.queues.queue_utils import (
9
+ check_for_event,
10
+ check_for_event_without_consumption,
11
+ trigger_event,
12
+ )
13
+ from robot_interface.models.exceptions.robot_exceptions import ErrorMessage
14
+ from robot_interface.models.mission.status import TaskStatus
15
+ from robot_interface.models.mission.task import Task
16
+
17
+ if TYPE_CHECKING:
18
+ from isar.state_machine.state_machine import StateMachine
19
+
20
+
21
+ class ReturningHome(State):
22
+ def __init__(self, state_machine: "StateMachine") -> None:
23
+ super().__init__(name="returning_home", on_enter=self.start, on_exit=self.stop)
24
+ self.state_machine: "StateMachine" = state_machine
25
+
26
+ self.logger = logging.getLogger("state_machine")
27
+ self.events = self.state_machine.events
28
+
29
+ self.awaiting_task_status: bool = False
30
+ self.signal_state_machine_to_stop = state_machine.signal_state_machine_to_stop
31
+
32
+ def start(self) -> None:
33
+ self.state_machine.update_state()
34
+ self._run()
35
+
36
+ def stop(self) -> None:
37
+ self.state_machine.mission_ongoing = False
38
+ return
39
+
40
+ def _check_and_handle_stop_mission_event(self, event: Queue) -> bool:
41
+ if check_for_event(event):
42
+ self.state_machine.stop() # type: ignore
43
+ return True
44
+ return False
45
+
46
+ def _check_and_handle_mission_started_event(self, event: Queue) -> bool:
47
+ if self.state_machine.mission_ongoing:
48
+ return False
49
+
50
+ if check_for_event(event):
51
+ self.state_machine.mission_ongoing = True
52
+ return False
53
+
54
+ return True
55
+
56
+ def _check_and_handle_mission_failed_event(self, event: Queue) -> bool:
57
+ mission_failed: Optional[ErrorMessage] = check_for_event(event)
58
+ if mission_failed is not None:
59
+ self.state_machine.logger.warning(
60
+ f"Failed to initiate mission "
61
+ f"{str(self.state_machine.current_mission.id)[:8]} because: "
62
+ f"{mission_failed.error_description}"
63
+ )
64
+ self.state_machine.current_mission.error_message = ErrorMessage(
65
+ error_reason=mission_failed.error_reason,
66
+ error_description=mission_failed.error_description,
67
+ )
68
+
69
+ self.state_machine.mission_failed_to_start() # type: ignore
70
+ return True
71
+ return False
72
+
73
+ def _check_and_handle_task_status_failed_event(self, event: Queue) -> bool:
74
+ task_failure: Optional[ErrorMessage] = check_for_event(event)
75
+ if task_failure is not None:
76
+ self.awaiting_task_status = False
77
+ self.state_machine.current_task.error_message = task_failure
78
+ self.logger.error(
79
+ f"Monitoring task {self.state_machine.current_task.id[:8]} failed "
80
+ f"because: {task_failure.error_description}"
81
+ )
82
+ return self._handle_new_task_status(TaskStatus.Failed)
83
+ elif not self.awaiting_task_status:
84
+ trigger_event(
85
+ self.events.state_machine_events.task_status_request,
86
+ self.state_machine.current_task.id,
87
+ )
88
+ self.awaiting_task_status = True
89
+ return False
90
+
91
+ def _check_and_handle_task_status_event(self, event: Queue) -> bool:
92
+ status: Optional[TaskStatus] = check_for_event(event)
93
+ if status is not None:
94
+ self.awaiting_task_status = False
95
+ return self._handle_new_task_status(status)
96
+ elif not self.awaiting_task_status:
97
+ trigger_event(
98
+ self.events.state_machine_events.task_status_request,
99
+ self.state_machine.current_task.id,
100
+ )
101
+ self.awaiting_task_status = True
102
+ return False
103
+
104
+ def _handle_new_task_status(self, status: TaskStatus) -> bool:
105
+ if self.state_machine.current_task is None:
106
+ self.state_machine.iterate_current_task()
107
+
108
+ self.state_machine.current_task.status = status
109
+
110
+ if self.state_machine.current_task.is_finished():
111
+ self._report_task_status(self.state_machine.current_task)
112
+ self.state_machine.publish_task_status(task=self.state_machine.current_task)
113
+
114
+ self.state_machine.iterate_current_task()
115
+ if self.state_machine.current_task is None:
116
+ if status != TaskStatus.Successful:
117
+ self.state_machine.return_home_failed() # type: ignore
118
+ self.state_machine.returned_home() # type: ignore
119
+ return True
120
+
121
+ # Report and update next task
122
+ self.state_machine.current_task.update_task_status()
123
+ self.state_machine.publish_task_status(task=self.state_machine.current_task)
124
+ return False
125
+
126
+ def _check_and_handle_start_mission_event(
127
+ self, event: Queue[StartMissionMessage]
128
+ ) -> bool:
129
+ if check_for_event_without_consumption(event):
130
+ self.state_machine.stop() # type: ignore
131
+ return True
132
+
133
+ return False
134
+
135
+ def _run(self) -> None:
136
+ while True:
137
+ if self.signal_state_machine_to_stop.is_set():
138
+ self.logger.info(
139
+ "Stopping state machine from %s state", self.__class__.__name__
140
+ )
141
+ break
142
+
143
+ if self._check_and_handle_stop_mission_event(
144
+ self.events.api_requests.stop_mission.input
145
+ ):
146
+ break
147
+
148
+ if self._check_and_handle_mission_started_event(
149
+ self.events.robot_service_events.mission_started
150
+ ):
151
+ continue
152
+
153
+ if self._check_and_handle_task_status_event(
154
+ self.events.robot_service_events.task_status_updated
155
+ ):
156
+ break
157
+
158
+ if self._check_and_handle_start_mission_event(
159
+ self.events.api_requests.start_mission.input
160
+ ):
161
+ break
162
+
163
+ if self._check_and_handle_mission_failed_event(
164
+ self.events.robot_service_events.mission_failed
165
+ ):
166
+ break
167
+
168
+ if self._check_and_handle_task_status_failed_event(
169
+ self.events.robot_service_events.task_status_failed
170
+ ):
171
+ break
172
+
173
+ if self._check_and_handle_task_status_event(
174
+ self.events.robot_service_events.task_status_updated
175
+ ):
176
+ break
177
+
178
+ def _report_task_status(self, task: Task) -> None:
179
+ if task.status == TaskStatus.Failed:
180
+ self.logger.warning(
181
+ f"Task: {str(task.id)[:8]} was reported as failed by the robot"
182
+ )
183
+ elif task.status == TaskStatus.Successful:
184
+ self.logger.info(
185
+ f"{type(task).__name__} task: {str(task.id)[:8]} completed"
186
+ )
@@ -6,6 +6,7 @@ from typing import TYPE_CHECKING, Optional
6
6
  from transitions import State
7
7
 
8
8
  from isar.models.communication.message import StartMissionMessage
9
+ from isar.models.communication.queues.queue_io import QueueIO
9
10
  from isar.models.communication.queues.queue_utils import (
10
11
  check_for_event,
11
12
  check_shared_state,
@@ -17,12 +18,13 @@ if TYPE_CHECKING:
17
18
  from isar.state_machine.state_machine import StateMachine
18
19
 
19
20
 
20
- class Idle(State):
21
+ class RobotStandingStill(State):
21
22
  def __init__(self, state_machine: "StateMachine") -> None:
22
- super().__init__(name="idle", on_enter=self.start, on_exit=self.stop)
23
+ super().__init__(
24
+ name="robot_standing_still", on_enter=self.start, on_exit=self.stop
25
+ )
23
26
  self.state_machine: "StateMachine" = state_machine
24
27
  self.logger = logging.getLogger("state_machine")
25
- self.last_robot_status_poll_time: float = time.time()
26
28
  self.events = self.state_machine.events
27
29
  self.shared_state = self.state_machine.shared_state
28
30
  self.signal_state_machine_to_stop = state_machine.signal_state_machine_to_stop
@@ -50,16 +52,21 @@ class Idle(State):
50
52
  return True
51
53
  return False
52
54
 
55
+ def _check_and_handle_return_home_event(self, event: QueueIO) -> bool:
56
+ if check_for_event(event.input):
57
+ event.output.put(True)
58
+ self.state_machine.request_return_home() # type: ignore
59
+ return True
60
+ return False
61
+
53
62
  def _check_and_handle_robot_status_event(
54
63
  self, event: StatusQueue[RobotStatus]
55
64
  ) -> bool:
56
65
  robot_status: RobotStatus = check_shared_state(event)
57
- if robot_status == RobotStatus.Offline:
58
- self.state_machine.robot_turned_offline() # type: ignore
59
- return True
60
- elif robot_status == RobotStatus.BlockedProtectiveStop:
61
- self.state_machine.robot_protective_stop_engaged() # type: ignore
66
+ if robot_status != RobotStatus.Available:
67
+ self.state_machine.robot_status_changed() # type: ignore
62
68
  return True
69
+
63
70
  return False
64
71
 
65
72
  def _run(self) -> None:
@@ -80,6 +87,11 @@ class Idle(State):
80
87
  ):
81
88
  break
82
89
 
90
+ if self._check_and_handle_return_home_event(
91
+ self.events.api_requests.return_home
92
+ ):
93
+ break
94
+
83
95
  if self._check_and_handle_robot_status_event(
84
96
  self.shared_state.robot_status
85
97
  ):
@@ -13,18 +13,23 @@ if TYPE_CHECKING:
13
13
  from isar.state_machine.state_machine import StateMachine
14
14
 
15
15
 
16
- class Stop(State):
16
+ class Stopping(State):
17
17
  def __init__(self, state_machine: "StateMachine") -> None:
18
- super().__init__(name="stop", on_enter=self.start, on_exit=self.stop)
18
+ super().__init__(name="stopping", on_enter=self.start, on_exit=self.stop)
19
19
  self.state_machine: "StateMachine" = state_machine
20
20
  self.logger = logging.getLogger("state_machine")
21
21
  self.events = self.state_machine.events
22
22
  self.stop_thread: Optional[ThreadedRequest] = None
23
23
  self._count_number_retries: int = 0
24
24
  self.signal_state_machine_to_stop = state_machine.signal_state_machine_to_stop
25
+ self.stopping_return_home_mission: bool = False
25
26
 
26
27
  def start(self) -> None:
27
28
  self.state_machine.update_state()
29
+ if self.state_machine.current_mission is not None:
30
+ self.stopping_return_home_mission = (
31
+ self.state_machine.current_mission._is_return_to_home_mission()
32
+ )
28
33
  self._run()
29
34
 
30
35
  def stop(self) -> None:
@@ -32,18 +37,25 @@ class Stop(State):
32
37
  self.stop_thread.wait_for_thread()
33
38
  self.stop_thread = None
34
39
  self._count_number_retries = 0
40
+ self.stopping_return_home_mission = False
35
41
 
36
42
  def _check_and_handle_failed_stop(self, event: Queue[ErrorMessage]) -> bool:
37
43
  error_message: Optional[ErrorMessage] = check_for_event(event)
38
44
  if error_message is not None:
39
45
  self.logger.warning(error_message.error_description)
40
- self.state_machine.mission_stopped() # type: ignore
46
+ if self.stopping_return_home_mission:
47
+ self.state_machine.return_home_mission_stopped() # type: ignore
48
+ else:
49
+ self.state_machine.mission_stopped() # type: ignore
41
50
  return True
42
51
  return False
43
52
 
44
53
  def _check_and_handle_successful_stop(self, event: Queue[bool]) -> bool:
45
54
  if check_for_event(event):
46
- self.state_machine.mission_stopped() # type: ignore
55
+ if self.stopping_return_home_mission:
56
+ self.state_machine.return_home_mission_stopped() # type: ignore
57
+ else:
58
+ self.state_machine.mission_stopped() # type: ignore
47
59
  return True
48
60
  return False
49
61
 
@@ -0,0 +1,74 @@
1
+ import logging
2
+ import time
3
+ from queue import Queue
4
+ from typing import TYPE_CHECKING
5
+
6
+ from transitions import State
7
+
8
+ from isar.models.communication.queues.queue_utils import (
9
+ check_for_event,
10
+ check_shared_state,
11
+ )
12
+ from isar.models.communication.queues.status_queue import StatusQueue
13
+ from robot_interface.models.mission.status import RobotStatus
14
+
15
+ if TYPE_CHECKING:
16
+ from isar.state_machine.state_machine import StateMachine
17
+
18
+
19
+ class UnknownStatus(State):
20
+ def __init__(self, state_machine: "StateMachine") -> None:
21
+ super().__init__(name="unknown_status", on_enter=self.start, on_exit=self.stop)
22
+ self.state_machine: "StateMachine" = state_machine
23
+ self.logger = logging.getLogger("state_machine")
24
+ self.events = self.state_machine.events
25
+ self.shared_state = self.state_machine.shared_state
26
+ self.signal_state_machine_to_stop = state_machine.signal_state_machine_to_stop
27
+
28
+ def start(self) -> None:
29
+ self.state_machine.update_state()
30
+ self._run()
31
+
32
+ def stop(self) -> None:
33
+ return
34
+
35
+ def _check_and_handle_stop_mission_event(self, event: Queue) -> bool:
36
+ if check_for_event(event):
37
+ self.state_machine.stop() # type: ignore
38
+ return True
39
+ return False
40
+
41
+ def _check_and_handle_robot_status_event(
42
+ self, event: StatusQueue[RobotStatus]
43
+ ) -> bool:
44
+ robot_status: RobotStatus = check_shared_state(event)
45
+ if (
46
+ robot_status == RobotStatus.Home
47
+ or robot_status == RobotStatus.Offline
48
+ or robot_status == RobotStatus.BlockedProtectiveStop
49
+ or robot_status == RobotStatus.Available
50
+ ):
51
+ self.state_machine.robot_status_changed() # type: ignore
52
+ return True
53
+
54
+ return False
55
+
56
+ def _run(self) -> None:
57
+ while True:
58
+ if self.signal_state_machine_to_stop.is_set():
59
+ self.logger.info(
60
+ "Stopping state machine from %s state", self.__class__.__name__
61
+ )
62
+ break
63
+
64
+ if self._check_and_handle_stop_mission_event(
65
+ self.events.api_requests.stop_mission.input
66
+ ):
67
+ break
68
+
69
+ if self._check_and_handle_robot_status_event(
70
+ self.shared_state.robot_status
71
+ ):
72
+ break
73
+
74
+ time.sleep(self.state_machine.sleep_time)
@@ -2,13 +2,16 @@ from enum import Enum
2
2
 
3
3
 
4
4
  class States(str, Enum):
5
- Off = "off"
6
- Idle = "idle"
7
5
  Monitor = "monitor"
6
+ ReturningHome = "returning_home"
7
+ Stopping = "stopping"
8
8
  Paused = "paused"
9
- Stop = "stop"
9
+ AwaitNextMission = "await_next_mission"
10
+ Home = "home"
11
+ RobotStandingStill = "robot_standing_still"
10
12
  Offline = "offline"
11
13
  BlockedProtectiveStop = "blocked_protective_stop"
14
+ UnknownStatus = "unknown_status"
12
15
 
13
16
  def __repr__(self):
14
17
  return self.value
@@ -0,0 +1,38 @@
1
+ from typing import TYPE_CHECKING
2
+
3
+ if TYPE_CHECKING:
4
+ from isar.state_machine.state_machine import StateMachine
5
+
6
+ from typing import TYPE_CHECKING
7
+
8
+ from robot_interface.models.mission.mission import Mission
9
+ from robot_interface.models.mission.status import MissionStatus, TaskStatus
10
+ from robot_interface.models.mission.task import ReturnToHome
11
+
12
+ if TYPE_CHECKING:
13
+ from isar.state_machine.state_machine import StateMachine
14
+
15
+
16
+ def start_return_home_mission(state_machine: "StateMachine") -> bool:
17
+ state_machine.start_mission(
18
+ Mission(
19
+ tasks=[ReturnToHome()],
20
+ name="Return Home",
21
+ )
22
+ )
23
+ return True
24
+
25
+
26
+ def set_return_home_status(state_machine: "StateMachine") -> bool:
27
+ state_machine.log_mission_overview(mission=state_machine.current_mission)
28
+ state_machine.current_mission.status = MissionStatus.InProgress
29
+
30
+ state_machine.current_task = state_machine.task_selector.next_task()
31
+ state_machine.current_task.status = TaskStatus.InProgress
32
+
33
+ return True
34
+
35
+
36
+ def return_home_finished(state_machine: "StateMachine") -> bool:
37
+ state_machine.reset_state_machine()
38
+ return True
@@ -0,0 +1,27 @@
1
+ from typing import TYPE_CHECKING
2
+
3
+ from isar.models.communication.queues.queue_utils import check_shared_state
4
+ from robot_interface.models.mission.status import RobotStatus
5
+
6
+ if TYPE_CHECKING:
7
+ from isar.state_machine.state_machine import StateMachine
8
+
9
+
10
+ def is_offline(state_machine: "StateMachine") -> bool:
11
+ robot_status = check_shared_state(state_machine.shared_state.robot_status)
12
+ return robot_status == RobotStatus.Offline
13
+
14
+
15
+ def is_available(state_machine: "StateMachine") -> bool:
16
+ robot_status = check_shared_state(state_machine.shared_state.robot_status)
17
+ return robot_status == RobotStatus.Available
18
+
19
+
20
+ def is_home(state_machine: "StateMachine") -> bool:
21
+ robot_status = check_shared_state(state_machine.shared_state.robot_status)
22
+ return robot_status == RobotStatus.Home
23
+
24
+
25
+ def is_blocked_protective_stop(state_machine: "StateMachine") -> bool:
26
+ robot_status = check_shared_state(state_machine.shared_state.robot_status)
27
+ return robot_status == RobotStatus.BlockedProtectiveStop
@@ -61,7 +61,7 @@ def set_mission_to_in_progress(state_machine: "StateMachine") -> bool:
61
61
  return True
62
62
 
63
63
 
64
- def trigger_start_mission_or_task_event(state_machine: "StateMachine") -> bool:
64
+ def trigger_start_mission_event(state_machine: "StateMachine") -> bool:
65
65
  state_machine.events.state_machine_events.start_mission.put(
66
66
  state_machine.current_mission
67
67
  )