isar 1.30.2__py3-none-any.whl → 1.30.3__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/config/settings.py +1 -0
- isar/robot/robot_start_mission.py +12 -0
- isar/robot/robot_status.py +5 -3
- isar/state_machine/generic_states/idle.py +133 -0
- isar/state_machine/generic_states/ongoing_mission.py +294 -0
- isar/state_machine/generic_states/robot_unavailable.py +61 -0
- isar/state_machine/state_machine.py +9 -0
- isar/state_machine/states/await_next_mission.py +11 -83
- isar/state_machine/states/blocked_protective_stop.py +13 -39
- isar/state_machine/states/home.py +10 -78
- isar/state_machine/states/monitor.py +10 -242
- isar/state_machine/states/offline.py +11 -36
- isar/state_machine/states/paused.py +1 -1
- isar/state_machine/states/returning_home.py +14 -177
- isar/state_machine/states/robot_standing_still.py +11 -91
- isar/state_machine/transitions/mission.py +1 -1
- {isar-1.30.2.dist-info → isar-1.30.3.dist-info}/METADATA +1 -1
- {isar-1.30.2.dist-info → isar-1.30.3.dist-info}/RECORD +23 -20
- robot_interface/robot_interface.py +15 -7
- {isar-1.30.2.dist-info → isar-1.30.3.dist-info}/WHEEL +0 -0
- {isar-1.30.2.dist-info → isar-1.30.3.dist-info}/entry_points.txt +0 -0
- {isar-1.30.2.dist-info → isar-1.30.3.dist-info}/licenses/LICENSE +0 -0
- {isar-1.30.2.dist-info → isar-1.30.3.dist-info}/top_level.txt +0 -0
|
@@ -1,50 +1,24 @@
|
|
|
1
|
-
import
|
|
2
|
-
import time
|
|
3
|
-
from typing import TYPE_CHECKING, Optional
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
4
2
|
|
|
5
3
|
from transitions import State
|
|
6
4
|
|
|
7
|
-
from isar.
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
from isar.state_machine.generic_states.robot_unavailable import (
|
|
6
|
+
RobotUnavailable,
|
|
7
|
+
RobotUnavailableStates,
|
|
8
|
+
)
|
|
10
9
|
|
|
11
10
|
if TYPE_CHECKING:
|
|
12
11
|
from isar.state_machine.state_machine import StateMachine
|
|
13
12
|
|
|
14
13
|
|
|
15
|
-
class BlockedProtectiveStop(State):
|
|
14
|
+
class BlockedProtectiveStop(State, RobotUnavailable):
|
|
16
15
|
def __init__(self, state_machine: "StateMachine") -> None:
|
|
17
|
-
|
|
18
|
-
name="blocked_protective_stop", on_enter=self.start, on_exit=self.stop
|
|
16
|
+
State.__init__(
|
|
17
|
+
self, name="blocked_protective_stop", on_enter=self.start, on_exit=self.stop
|
|
19
18
|
)
|
|
20
|
-
self.state_machine: "StateMachine" = state_machine
|
|
21
|
-
self.logger = logging.getLogger("state_machine")
|
|
22
|
-
self.robot_status_thread: Optional[ThreadedRequest] = None
|
|
23
|
-
self.shared_state = self.state_machine.shared_state
|
|
24
|
-
self.signal_state_machine_to_stop = state_machine.signal_state_machine_to_stop
|
|
25
19
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return
|
|
32
|
-
|
|
33
|
-
def _run(self) -> None:
|
|
34
|
-
while True:
|
|
35
|
-
if self.signal_state_machine_to_stop.is_set():
|
|
36
|
-
self.logger.info(
|
|
37
|
-
"Stopping state machine from %s state", self.__class__.__name__
|
|
38
|
-
)
|
|
39
|
-
break
|
|
40
|
-
|
|
41
|
-
robot_status: RobotStatus = check_shared_state(
|
|
42
|
-
self.shared_state.robot_status
|
|
43
|
-
)
|
|
44
|
-
if robot_status != RobotStatus.BlockedProtectiveStop:
|
|
45
|
-
transition = self.state_machine.robot_status_changed # type: ignore
|
|
46
|
-
break
|
|
47
|
-
|
|
48
|
-
time.sleep(self.state_machine.sleep_time)
|
|
49
|
-
|
|
50
|
-
transition()
|
|
20
|
+
RobotUnavailable.__init__(
|
|
21
|
+
self,
|
|
22
|
+
state_machine=state_machine,
|
|
23
|
+
state=RobotUnavailableStates.BlockedProtectiveStop,
|
|
24
|
+
)
|
|
@@ -1,87 +1,19 @@
|
|
|
1
|
-
import
|
|
2
|
-
import time
|
|
3
|
-
from queue import Queue
|
|
4
|
-
from typing import TYPE_CHECKING, Optional
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
5
2
|
|
|
6
3
|
from transitions import State
|
|
7
4
|
|
|
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
5
|
if TYPE_CHECKING:
|
|
18
6
|
from isar.state_machine.state_machine import StateMachine
|
|
19
7
|
|
|
8
|
+
from isar.state_machine.generic_states.idle import Idle, IdleStates
|
|
20
9
|
|
|
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
10
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
|
11
|
+
class Home(State, Idle):
|
|
12
|
+
def __init__(self, state_machine: "StateMachine") -> None:
|
|
13
|
+
State.__init__(self, name="home", on_enter=self.start, on_exit=self.stop)
|
|
86
14
|
|
|
87
|
-
|
|
15
|
+
Idle.__init__(
|
|
16
|
+
self,
|
|
17
|
+
state_machine=state_machine,
|
|
18
|
+
state=IdleStates.Home,
|
|
19
|
+
)
|
|
@@ -1,256 +1,24 @@
|
|
|
1
|
-
import
|
|
2
|
-
import time
|
|
3
|
-
from copy import deepcopy
|
|
4
|
-
from queue import Queue
|
|
5
|
-
from threading import Event
|
|
6
|
-
from typing import TYPE_CHECKING, Optional, Tuple
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
7
2
|
|
|
8
3
|
from dependency_injector.wiring import inject
|
|
9
4
|
from transitions import State
|
|
10
5
|
|
|
11
|
-
from isar.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
from robot_interface.models.exceptions.robot_exceptions import (
|
|
15
|
-
ErrorMessage,
|
|
16
|
-
RobotException,
|
|
17
|
-
RobotRetrieveInspectionException,
|
|
6
|
+
from isar.state_machine.generic_states.ongoing_mission import (
|
|
7
|
+
OngoingMission,
|
|
8
|
+
OngoingMissionStates,
|
|
18
9
|
)
|
|
19
|
-
from robot_interface.models.inspection.inspection import Inspection
|
|
20
|
-
from robot_interface.models.mission.mission import Mission
|
|
21
|
-
from robot_interface.models.mission.status import TaskStatus
|
|
22
|
-
from robot_interface.models.mission.task import InspectionTask, Task
|
|
23
10
|
|
|
24
11
|
if TYPE_CHECKING:
|
|
25
12
|
from isar.state_machine.state_machine import StateMachine
|
|
26
13
|
|
|
27
14
|
|
|
28
|
-
class Monitor(State):
|
|
15
|
+
class Monitor(State, OngoingMission):
|
|
29
16
|
@inject
|
|
30
17
|
def __init__(self, state_machine: "StateMachine") -> None:
|
|
31
|
-
|
|
32
|
-
self.state_machine: "StateMachine" = state_machine
|
|
18
|
+
State.__init__(self, name="monitor", on_enter=self.start, on_exit=self.stop)
|
|
33
19
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
self.signal_state_machine_to_stop: Event = (
|
|
40
|
-
state_machine.signal_state_machine_to_stop
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
def start(self) -> None:
|
|
44
|
-
self.state_machine.update_state()
|
|
45
|
-
self._run()
|
|
46
|
-
|
|
47
|
-
def stop(self) -> None:
|
|
48
|
-
self.state_machine.mission_ongoing = False
|
|
49
|
-
return
|
|
50
|
-
|
|
51
|
-
def _check_and_handle_stop_mission_event(self, event: Queue) -> bool:
|
|
52
|
-
if check_for_event(event):
|
|
53
|
-
self.state_machine.stop() # type: ignore
|
|
54
|
-
return True
|
|
55
|
-
return False
|
|
56
|
-
|
|
57
|
-
def _check_and_handle_pause_mission_event(self, event: Queue) -> bool:
|
|
58
|
-
if check_for_event(event):
|
|
59
|
-
self.state_machine.pause() # type: ignore
|
|
60
|
-
return True
|
|
61
|
-
return False
|
|
62
|
-
|
|
63
|
-
def _check_and_handle_mission_started_event(self, event: Queue) -> None:
|
|
64
|
-
if check_for_event(event):
|
|
65
|
-
self.state_machine.mission_ongoing = True
|
|
66
|
-
|
|
67
|
-
def _check_and_handle_mission_failed_event(self, event: Queue) -> bool:
|
|
68
|
-
mission_failed: Optional[ErrorMessage] = check_for_event(event)
|
|
69
|
-
if mission_failed is not None:
|
|
70
|
-
self.state_machine.logger.warning(
|
|
71
|
-
f"Failed to initiate mission "
|
|
72
|
-
f"{str(self.state_machine.current_mission.id)[:8]} because: "
|
|
73
|
-
f"{mission_failed.error_description}"
|
|
74
|
-
)
|
|
75
|
-
self.state_machine.current_mission.error_message = ErrorMessage(
|
|
76
|
-
error_reason=mission_failed.error_reason,
|
|
77
|
-
error_description=mission_failed.error_description,
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
self.state_machine.mission_failed_to_start() # type: ignore
|
|
81
|
-
return True
|
|
82
|
-
return False
|
|
83
|
-
|
|
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
|
-
|
|
88
|
-
task_failure: Optional[ErrorMessage] = check_for_event(event)
|
|
89
|
-
if task_failure is not None:
|
|
90
|
-
self.awaiting_task_status = False
|
|
91
|
-
self.state_machine.current_task.error_message = task_failure
|
|
92
|
-
self.logger.error(
|
|
93
|
-
f"Monitoring task {self.state_machine.current_task.id[:8]} failed "
|
|
94
|
-
f"because: {task_failure.error_description}"
|
|
95
|
-
)
|
|
96
|
-
return self._handle_new_task_status(TaskStatus.Failed)
|
|
97
|
-
elif not self.awaiting_task_status:
|
|
98
|
-
trigger_event(
|
|
99
|
-
self.events.state_machine_events.task_status_request,
|
|
100
|
-
self.state_machine.current_task.id,
|
|
101
|
-
)
|
|
102
|
-
self.awaiting_task_status = True
|
|
103
|
-
return False
|
|
104
|
-
|
|
105
|
-
def _check_and_handle_task_status_event(self, event: Queue) -> bool:
|
|
106
|
-
if not self.state_machine.mission_ongoing:
|
|
107
|
-
return False
|
|
108
|
-
|
|
109
|
-
status: Optional[TaskStatus] = check_for_event(event)
|
|
110
|
-
if status is not None:
|
|
111
|
-
self.awaiting_task_status = False
|
|
112
|
-
return self._handle_new_task_status(status)
|
|
113
|
-
elif not self.awaiting_task_status:
|
|
114
|
-
trigger_event(
|
|
115
|
-
self.events.state_machine_events.task_status_request,
|
|
116
|
-
self.state_machine.current_task.id,
|
|
117
|
-
)
|
|
118
|
-
self.awaiting_task_status = True
|
|
119
|
-
return False
|
|
120
|
-
|
|
121
|
-
def _handle_new_task_status(self, status: TaskStatus) -> bool:
|
|
122
|
-
if self.state_machine.current_task is None:
|
|
123
|
-
self.state_machine.iterate_current_task()
|
|
124
|
-
|
|
125
|
-
self.state_machine.current_task.status = status
|
|
126
|
-
|
|
127
|
-
if self._should_upload_inspections():
|
|
128
|
-
get_inspection_thread = ThreadedRequest(self._queue_inspections_for_upload)
|
|
129
|
-
get_inspection_thread.start_thread(
|
|
130
|
-
deepcopy(self.state_machine.current_mission),
|
|
131
|
-
deepcopy(self.state_machine.current_task),
|
|
132
|
-
name="State Machine Get Inspections",
|
|
133
|
-
)
|
|
134
|
-
|
|
135
|
-
if self.state_machine.current_task.is_finished():
|
|
136
|
-
self._report_task_status(self.state_machine.current_task)
|
|
137
|
-
self.state_machine.publish_task_status(task=self.state_machine.current_task)
|
|
138
|
-
|
|
139
|
-
self.state_machine.iterate_current_task()
|
|
140
|
-
if self.state_machine.current_task is None:
|
|
141
|
-
self.state_machine.mission_finished() # type: ignore
|
|
142
|
-
return True
|
|
143
|
-
|
|
144
|
-
# Report and update next task
|
|
145
|
-
self.state_machine.current_task.update_task_status()
|
|
146
|
-
self.state_machine.publish_task_status(task=self.state_machine.current_task)
|
|
147
|
-
return False
|
|
148
|
-
|
|
149
|
-
def _run(self) -> None:
|
|
150
|
-
self.awaiting_task_status = False
|
|
151
|
-
while True:
|
|
152
|
-
if self.signal_state_machine_to_stop.is_set():
|
|
153
|
-
self.logger.info(
|
|
154
|
-
"Stopping state machine from %s state", self.__class__.__name__
|
|
155
|
-
)
|
|
156
|
-
break
|
|
157
|
-
|
|
158
|
-
if self._check_and_handle_stop_mission_event(
|
|
159
|
-
self.events.api_requests.stop_mission.input
|
|
160
|
-
):
|
|
161
|
-
break
|
|
162
|
-
|
|
163
|
-
if self._check_and_handle_pause_mission_event(
|
|
164
|
-
self.events.api_requests.pause_mission.input
|
|
165
|
-
):
|
|
166
|
-
break
|
|
167
|
-
|
|
168
|
-
self._check_and_handle_mission_started_event(
|
|
169
|
-
self.events.robot_service_events.mission_started
|
|
170
|
-
)
|
|
171
|
-
|
|
172
|
-
if self._check_and_handle_mission_failed_event(
|
|
173
|
-
self.events.robot_service_events.mission_failed
|
|
174
|
-
):
|
|
175
|
-
break
|
|
176
|
-
|
|
177
|
-
if self._check_and_handle_task_status_failed_event(
|
|
178
|
-
self.events.robot_service_events.task_status_failed
|
|
179
|
-
):
|
|
180
|
-
break
|
|
181
|
-
|
|
182
|
-
if self._check_and_handle_task_status_event(
|
|
183
|
-
self.events.robot_service_events.task_status_updated
|
|
184
|
-
):
|
|
185
|
-
break
|
|
186
|
-
|
|
187
|
-
time.sleep(settings.FSM_SLEEP_TIME)
|
|
188
|
-
|
|
189
|
-
def _queue_inspections_for_upload(
|
|
190
|
-
self, mission: Mission, current_task: InspectionTask
|
|
191
|
-
) -> None:
|
|
192
|
-
try:
|
|
193
|
-
inspection: Inspection = self.state_machine.robot.get_inspection(
|
|
194
|
-
task=current_task
|
|
195
|
-
)
|
|
196
|
-
if current_task.inspection_id != inspection.id:
|
|
197
|
-
self.logger.warning(
|
|
198
|
-
f"The inspection_id of task ({current_task.inspection_id}) "
|
|
199
|
-
f"and result ({inspection.id}) is not matching. "
|
|
200
|
-
f"This may lead to confusions when accessing the inspection later"
|
|
201
|
-
)
|
|
202
|
-
|
|
203
|
-
except (RobotRetrieveInspectionException, RobotException) as e:
|
|
204
|
-
self._set_error_message(e)
|
|
205
|
-
self.logger.error(
|
|
206
|
-
f"Failed to retrieve inspections because: {e.error_description}"
|
|
207
|
-
)
|
|
208
|
-
return
|
|
209
|
-
|
|
210
|
-
except Exception as e:
|
|
211
|
-
self.logger.error(
|
|
212
|
-
f"Failed to retrieve inspections because of unexpected error: {e}"
|
|
213
|
-
)
|
|
214
|
-
return
|
|
215
|
-
|
|
216
|
-
if not inspection:
|
|
217
|
-
self.logger.warning(
|
|
218
|
-
f"No inspection result data retrieved for task {str(current_task.id)[:8]}"
|
|
219
|
-
)
|
|
220
|
-
|
|
221
|
-
inspection.metadata.tag_id = current_task.tag_id
|
|
222
|
-
|
|
223
|
-
message: Tuple[Inspection, Mission] = (
|
|
224
|
-
inspection,
|
|
225
|
-
mission,
|
|
226
|
-
)
|
|
227
|
-
self.state_machine.events.upload_queue.put(message)
|
|
228
|
-
self.logger.info(
|
|
229
|
-
f"Inspection result: {str(inspection.id)[:8]} queued for upload"
|
|
230
|
-
)
|
|
231
|
-
|
|
232
|
-
def _report_task_status(self, task: Task) -> None:
|
|
233
|
-
if task.status == TaskStatus.Failed:
|
|
234
|
-
self.logger.warning(
|
|
235
|
-
f"Task: {str(task.id)[:8]} was reported as failed by the robot"
|
|
236
|
-
)
|
|
237
|
-
elif task.status == TaskStatus.Successful:
|
|
238
|
-
self.logger.info(
|
|
239
|
-
f"{type(task).__name__} task: {str(task.id)[:8]} completed"
|
|
240
|
-
)
|
|
241
|
-
|
|
242
|
-
def _should_upload_inspections(self) -> bool:
|
|
243
|
-
if settings.UPLOAD_INSPECTIONS_ASYNC:
|
|
244
|
-
return False
|
|
245
|
-
|
|
246
|
-
return (
|
|
247
|
-
self.state_machine.current_task.is_finished()
|
|
248
|
-
and self.state_machine.current_task.status == TaskStatus.Successful
|
|
249
|
-
and isinstance(self.state_machine.current_task, InspectionTask)
|
|
250
|
-
)
|
|
251
|
-
|
|
252
|
-
def _set_error_message(self, e: RobotException) -> None:
|
|
253
|
-
error_message: ErrorMessage = ErrorMessage(
|
|
254
|
-
error_reason=e.error_reason, error_description=e.error_description
|
|
20
|
+
OngoingMission.__init__(
|
|
21
|
+
self,
|
|
22
|
+
state_machine=state_machine,
|
|
23
|
+
state=OngoingMissionStates.Monitor,
|
|
255
24
|
)
|
|
256
|
-
self.state_machine.current_task.error_message = error_message
|
|
@@ -1,47 +1,22 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
import time
|
|
3
1
|
from typing import TYPE_CHECKING
|
|
4
2
|
|
|
5
3
|
from transitions import State
|
|
6
4
|
|
|
7
|
-
from isar.
|
|
8
|
-
|
|
5
|
+
from isar.state_machine.generic_states.robot_unavailable import (
|
|
6
|
+
RobotUnavailable,
|
|
7
|
+
RobotUnavailableStates,
|
|
8
|
+
)
|
|
9
9
|
|
|
10
10
|
if TYPE_CHECKING:
|
|
11
11
|
from isar.state_machine.state_machine import StateMachine
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
class Offline(State):
|
|
14
|
+
class Offline(State, RobotUnavailable):
|
|
15
15
|
def __init__(self, state_machine: "StateMachine") -> None:
|
|
16
|
-
|
|
17
|
-
self.state_machine: "StateMachine" = state_machine
|
|
18
|
-
self.logger = logging.getLogger("state_machine")
|
|
19
|
-
self.shared_state = self.state_machine.shared_state
|
|
20
|
-
self.signal_state_machine_to_stop = state_machine.signal_state_machine_to_stop
|
|
16
|
+
State.__init__(self, name="offline", on_enter=self.start, on_exit=self.stop)
|
|
21
17
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return
|
|
28
|
-
|
|
29
|
-
def _run(self) -> None:
|
|
30
|
-
while True:
|
|
31
|
-
if self.signal_state_machine_to_stop.is_set():
|
|
32
|
-
self.logger.info(
|
|
33
|
-
"Stopping state machine from %s state", self.__class__.__name__
|
|
34
|
-
)
|
|
35
|
-
break
|
|
36
|
-
|
|
37
|
-
robot_status: RobotStatus = check_shared_state(
|
|
38
|
-
self.shared_state.robot_status
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
if robot_status != RobotStatus.Offline:
|
|
42
|
-
transition = self.state_machine.robot_status_changed # type: ignore
|
|
43
|
-
break
|
|
44
|
-
|
|
45
|
-
time.sleep(self.state_machine.sleep_time)
|
|
46
|
-
|
|
47
|
-
transition()
|
|
18
|
+
RobotUnavailable.__init__(
|
|
19
|
+
self,
|
|
20
|
+
state_machine=state_machine,
|
|
21
|
+
state=RobotUnavailableStates.Offline,
|
|
22
|
+
)
|