isar 1.25.8__py3-none-any.whl → 1.26.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.
- isar/apis/models/start_mission_definition.py +55 -108
- isar/apis/robot_control/robot_controller.py +5 -4
- isar/apis/schedule/scheduling_controller.py +4 -32
- isar/apis/security/authentication.py +2 -2
- isar/config/settings.env +1 -3
- isar/config/settings.py +5 -5
- isar/models/communication/message.py +0 -4
- isar/models/communication/queues/queue_utils.py +27 -0
- isar/models/communication/queues/queues.py +23 -5
- isar/robot/robot.py +91 -0
- isar/robot/robot_start_mission.py +73 -0
- isar/robot/robot_status.py +46 -0
- isar/robot/robot_task_status.py +92 -0
- isar/script.py +7 -0
- isar/services/utilities/scheduling_utilities.py +15 -26
- isar/state_machine/state_machine.py +94 -187
- isar/state_machine/states/blocked_protective_stop.py +7 -19
- isar/state_machine/states/idle.py +12 -54
- isar/state_machine/states/monitor.py +43 -90
- isar/state_machine/states/offline.py +8 -33
- isar/state_machine/states/paused.py +1 -1
- isar/state_machine/states_enum.py +0 -2
- isar/state_machine/transitions/fail_mission.py +13 -0
- isar/state_machine/transitions/finish_mission.py +39 -0
- isar/state_machine/transitions/pause.py +24 -0
- isar/state_machine/transitions/resume.py +27 -0
- isar/state_machine/transitions/start_mission.py +73 -0
- isar/state_machine/transitions/stop.py +33 -0
- isar/state_machine/transitions/utils.py +10 -0
- isar/storage/slimm_storage.py +2 -2
- {isar-1.25.8.dist-info → isar-1.26.0.dist-info}/METADATA +2 -3
- {isar-1.25.8.dist-info → isar-1.26.0.dist-info}/RECORD +42 -33
- robot_interface/models/exceptions/robot_exceptions.py +0 -24
- robot_interface/models/mission/task.py +1 -1
- robot_interface/robot_interface.py +1 -6
- robot_interface/telemetry/mqtt_client.py +0 -1
- robot_interface/telemetry/payloads.py +3 -3
- robot_interface/utilities/json_service.py +1 -1
- isar/state_machine/states/initialize.py +0 -71
- isar/state_machine/states/initiate.py +0 -111
- robot_interface/models/initialize/initialize_params.py +0 -9
- {isar-1.25.8.dist-info → isar-1.26.0.dist-info}/LICENSE +0 -0
- {isar-1.25.8.dist-info → isar-1.26.0.dist-info}/WHEEL +0 -0
- {isar-1.25.8.dist-info → isar-1.26.0.dist-info}/entry_points.txt +0 -0
- {isar-1.25.8.dist-info → isar-1.26.0.dist-info}/top_level.txt +0 -0
|
@@ -1,23 +1,17 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import time
|
|
3
3
|
from copy import deepcopy
|
|
4
|
-
from typing import TYPE_CHECKING, Callable, Optional, Tuple
|
|
4
|
+
from typing import TYPE_CHECKING, Callable, Optional, Tuple
|
|
5
5
|
|
|
6
6
|
from injector import inject
|
|
7
7
|
from transitions import State
|
|
8
8
|
|
|
9
9
|
from isar.config.settings import settings
|
|
10
|
-
from isar.services.utilities.threaded_request import
|
|
11
|
-
ThreadedRequest,
|
|
12
|
-
ThreadedRequestNotFinishedError,
|
|
13
|
-
)
|
|
10
|
+
from isar.services.utilities.threaded_request import ThreadedRequest
|
|
14
11
|
from robot_interface.models.exceptions.robot_exceptions import (
|
|
15
12
|
ErrorMessage,
|
|
16
|
-
RobotCommunicationException,
|
|
17
|
-
RobotCommunicationTimeoutException,
|
|
18
13
|
RobotException,
|
|
19
14
|
RobotRetrieveInspectionException,
|
|
20
|
-
RobotTaskStatusException,
|
|
21
15
|
)
|
|
22
16
|
from robot_interface.models.inspection.inspection import Inspection
|
|
23
17
|
from robot_interface.models.mission.mission import Mission
|
|
@@ -33,24 +27,19 @@ class Monitor(State):
|
|
|
33
27
|
def __init__(self, state_machine: "StateMachine") -> None:
|
|
34
28
|
super().__init__(name="monitor", on_enter=self.start, on_exit=self.stop)
|
|
35
29
|
self.state_machine: "StateMachine" = state_machine
|
|
36
|
-
self.request_status_failure_counter: int = 0
|
|
37
|
-
self.request_status_failure_counter_limit: int = (
|
|
38
|
-
settings.REQUEST_STATUS_FAILURE_COUNTER_LIMIT
|
|
39
|
-
)
|
|
40
30
|
|
|
41
31
|
self.logger = logging.getLogger("state_machine")
|
|
42
|
-
self.task_status_thread: Optional[ThreadedRequest] = None
|
|
43
32
|
|
|
44
33
|
def start(self) -> None:
|
|
45
34
|
self.state_machine.update_state()
|
|
46
35
|
self._run()
|
|
47
36
|
|
|
48
37
|
def stop(self) -> None:
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
self.task_status_thread = None
|
|
38
|
+
self.state_machine.mission_ongoing = False
|
|
39
|
+
return
|
|
52
40
|
|
|
53
41
|
def _run(self) -> None:
|
|
42
|
+
awaiting_task_status: bool = False
|
|
54
43
|
transition: Callable
|
|
55
44
|
while True:
|
|
56
45
|
if self.state_machine.should_stop_mission():
|
|
@@ -61,50 +50,53 @@ class Monitor(State):
|
|
|
61
50
|
transition = self.state_machine.pause # type: ignore
|
|
62
51
|
break
|
|
63
52
|
|
|
64
|
-
if not self.
|
|
65
|
-
self.
|
|
66
|
-
|
|
67
|
-
function_argument=self.state_machine.current_task.id,
|
|
68
|
-
thread_name="State Machine Monitor Get Task Status",
|
|
69
|
-
)
|
|
70
|
-
try:
|
|
71
|
-
status: TaskStatus = self.task_status_thread.get_output()
|
|
72
|
-
self.request_status_failure_counter = 0
|
|
73
|
-
except ThreadedRequestNotFinishedError:
|
|
74
|
-
time.sleep(self.state_machine.sleep_time)
|
|
75
|
-
continue
|
|
76
|
-
except (
|
|
77
|
-
RobotCommunicationTimeoutException,
|
|
78
|
-
RobotCommunicationException,
|
|
79
|
-
) as e:
|
|
80
|
-
retry_limit_exceeded: bool = self._check_if_exceeded_retry_limit(e)
|
|
81
|
-
if retry_limit_exceeded:
|
|
82
|
-
self.logger.error(
|
|
83
|
-
f"Monitoring task {self.state_machine.current_task.id[:8]} failed "
|
|
84
|
-
f"because: {e.error_description}"
|
|
85
|
-
)
|
|
86
|
-
status = TaskStatus.Failed
|
|
53
|
+
if not self.state_machine.mission_ongoing:
|
|
54
|
+
if self.state_machine.get_mission_started_event():
|
|
55
|
+
self.state_machine.mission_ongoing = True
|
|
87
56
|
else:
|
|
88
|
-
time.sleep(settings.
|
|
57
|
+
time.sleep(settings.FSM_SLEEP_TIME)
|
|
89
58
|
continue
|
|
90
59
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
60
|
+
mission_failed = self.state_machine.get_mission_failed_event()
|
|
61
|
+
if mission_failed is not None:
|
|
62
|
+
self.state_machine.logger.warning(
|
|
63
|
+
f"Failed to initiate mission "
|
|
64
|
+
f"{str(self.state_machine.current_mission.id)[:8]} because: "
|
|
65
|
+
f"{mission_failed.error_description}"
|
|
94
66
|
)
|
|
95
|
-
self.
|
|
96
|
-
|
|
97
|
-
|
|
67
|
+
self.state_machine.current_mission.error_message = ErrorMessage(
|
|
68
|
+
error_reason=mission_failed.error_reason,
|
|
69
|
+
error_description=mission_failed.error_description,
|
|
98
70
|
)
|
|
99
|
-
status = TaskStatus.Failed
|
|
100
71
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
status = TaskStatus.Failed
|
|
72
|
+
transition = self.state_machine.mission_failed_to_start # type: ignore
|
|
73
|
+
break
|
|
104
74
|
|
|
75
|
+
status: TaskStatus
|
|
76
|
+
|
|
77
|
+
task_failure: Optional[ErrorMessage] = (
|
|
78
|
+
self.state_machine.get_task_failure_event()
|
|
79
|
+
)
|
|
80
|
+
if task_failure is not None:
|
|
81
|
+
self.state_machine.current_task.error_message = task_failure
|
|
105
82
|
self.logger.error(
|
|
106
|
-
f"
|
|
83
|
+
f"Monitoring task {self.state_machine.current_task.id[:8]} failed "
|
|
84
|
+
f"because: {task_failure.error_description}"
|
|
107
85
|
)
|
|
86
|
+
status = TaskStatus.Failed
|
|
87
|
+
else:
|
|
88
|
+
status = self.state_machine.get_task_status_event()
|
|
89
|
+
|
|
90
|
+
if status is None:
|
|
91
|
+
if not awaiting_task_status:
|
|
92
|
+
self.state_machine.request_task_status(
|
|
93
|
+
self.state_machine.current_task
|
|
94
|
+
)
|
|
95
|
+
awaiting_task_status = True
|
|
96
|
+
time.sleep(settings.FSM_SLEEP_TIME)
|
|
97
|
+
continue
|
|
98
|
+
else:
|
|
99
|
+
awaiting_task_status = False
|
|
108
100
|
|
|
109
101
|
if not isinstance(status, TaskStatus):
|
|
110
102
|
self.logger.error(
|
|
@@ -148,17 +140,8 @@ class Monitor(State):
|
|
|
148
140
|
task=self.state_machine.current_task
|
|
149
141
|
)
|
|
150
142
|
|
|
151
|
-
self.task_status_thread = None
|
|
152
|
-
time.sleep(self.state_machine.sleep_time)
|
|
153
|
-
|
|
154
143
|
transition()
|
|
155
144
|
|
|
156
|
-
def _run_get_status_thread(
|
|
157
|
-
self, status_function: Callable, function_argument: str, thread_name: str
|
|
158
|
-
) -> None:
|
|
159
|
-
self.task_status_thread = ThreadedRequest(request_func=status_function)
|
|
160
|
-
self.task_status_thread.start_thread(function_argument, name=thread_name)
|
|
161
|
-
|
|
162
145
|
def _queue_inspections_for_upload(
|
|
163
146
|
self, mission: Mission, current_task: InspectionTask
|
|
164
147
|
) -> None:
|
|
@@ -218,33 +201,3 @@ class Monitor(State):
|
|
|
218
201
|
error_reason=e.error_reason, error_description=e.error_description
|
|
219
202
|
)
|
|
220
203
|
self.state_machine.current_task.error_message = error_message
|
|
221
|
-
|
|
222
|
-
def _check_if_exceeded_retry_limit(
|
|
223
|
-
self, e: Union[RobotCommunicationTimeoutException, RobotCommunicationException]
|
|
224
|
-
) -> bool:
|
|
225
|
-
self.state_machine.current_mission.error_message = ErrorMessage(
|
|
226
|
-
error_reason=e.error_reason, error_description=e.error_description
|
|
227
|
-
)
|
|
228
|
-
self.task_status_thread = None
|
|
229
|
-
self.request_status_failure_counter += 1
|
|
230
|
-
self.logger.warning(
|
|
231
|
-
f"Monitoring task {self.state_machine.current_task.id} failed #: "
|
|
232
|
-
f"{self.request_status_failure_counter} failed because: {e.error_description}"
|
|
233
|
-
)
|
|
234
|
-
|
|
235
|
-
if (
|
|
236
|
-
self.request_status_failure_counter
|
|
237
|
-
>= self.request_status_failure_counter_limit
|
|
238
|
-
):
|
|
239
|
-
self.state_machine.current_task.error_message = ErrorMessage(
|
|
240
|
-
error_reason=e.error_reason,
|
|
241
|
-
error_description=e.error_description,
|
|
242
|
-
)
|
|
243
|
-
self.logger.error(
|
|
244
|
-
f"Task will be cancelled after failing to get task status "
|
|
245
|
-
f"{self.request_status_failure_counter} times because: "
|
|
246
|
-
f"{e.error_description}"
|
|
247
|
-
)
|
|
248
|
-
return True
|
|
249
|
-
|
|
250
|
-
return False
|
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import time
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
5
|
from transitions import State
|
|
6
6
|
|
|
7
|
-
from isar.config.settings import settings
|
|
8
|
-
from isar.services.utilities.threaded_request import (
|
|
9
|
-
ThreadedRequest,
|
|
10
|
-
ThreadedRequestNotFinishedError,
|
|
11
|
-
)
|
|
12
|
-
from robot_interface.models.exceptions.robot_exceptions import RobotException
|
|
13
7
|
from robot_interface.models.mission.status import RobotStatus
|
|
14
8
|
|
|
15
9
|
if TYPE_CHECKING:
|
|
@@ -21,43 +15,24 @@ class Offline(State):
|
|
|
21
15
|
super().__init__(name="offline", on_enter=self.start, on_exit=self.stop)
|
|
22
16
|
self.state_machine: "StateMachine" = state_machine
|
|
23
17
|
self.logger = logging.getLogger("state_machine")
|
|
24
|
-
self.robot_status_thread: Optional[ThreadedRequest] = None
|
|
25
18
|
|
|
26
19
|
def start(self) -> None:
|
|
27
20
|
self.state_machine.update_state()
|
|
28
21
|
self._run()
|
|
29
22
|
|
|
30
23
|
def stop(self) -> None:
|
|
31
|
-
|
|
32
|
-
self.robot_status_thread.wait_for_thread()
|
|
33
|
-
self.robot_status_thread = None
|
|
24
|
+
return
|
|
34
25
|
|
|
35
26
|
def _run(self) -> None:
|
|
36
27
|
while True:
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
name="State Machine Offline Get Robot Status"
|
|
43
|
-
)
|
|
44
|
-
|
|
45
|
-
try:
|
|
46
|
-
robot_status: RobotStatus = self.robot_status_thread.get_output()
|
|
47
|
-
except ThreadedRequestNotFinishedError:
|
|
48
|
-
time.sleep(self.state_machine.sleep_time)
|
|
49
|
-
continue
|
|
50
|
-
|
|
51
|
-
except RobotException as e:
|
|
52
|
-
self.logger.error(
|
|
53
|
-
f"Failed to get robot status because: {e.error_description}"
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
if robot_status != RobotStatus.Offline:
|
|
28
|
+
robot_status = self.state_machine.get_robot_status()
|
|
29
|
+
if robot_status == RobotStatus.BlockedProtectiveStop:
|
|
30
|
+
transition = self.state_machine.robot_protective_stop_engaged # type: ignore
|
|
31
|
+
break
|
|
32
|
+
elif robot_status != RobotStatus.Offline:
|
|
57
33
|
transition = self.state_machine.robot_turned_online # type: ignore
|
|
58
34
|
break
|
|
59
35
|
|
|
60
|
-
self.
|
|
61
|
-
time.sleep(settings.ROBOT_API_STATUS_POLL_INTERVAL)
|
|
36
|
+
time.sleep(self.state_machine.sleep_time)
|
|
62
37
|
|
|
63
38
|
transition()
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
2
|
+
|
|
3
|
+
if TYPE_CHECKING:
|
|
4
|
+
from isar.state_machine.state_machine import StateMachine
|
|
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()
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, List
|
|
2
|
+
|
|
3
|
+
if TYPE_CHECKING:
|
|
4
|
+
from isar.state_machine.state_machine import StateMachine
|
|
5
|
+
|
|
6
|
+
from robot_interface.models.exceptions.robot_exceptions import ErrorMessage
|
|
7
|
+
from robot_interface.models.mission.status import MissionStatus, TaskStatus
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def finish_mission(state_machine: "StateMachine") -> bool:
|
|
11
|
+
fail_statuses: List[TaskStatus] = [
|
|
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()
|
|
39
|
+
return True
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
2
|
+
|
|
3
|
+
if TYPE_CHECKING:
|
|
4
|
+
from isar.state_machine.state_machine import StateMachine
|
|
5
|
+
|
|
6
|
+
from isar.apis.models.models import ControlMissionResponse
|
|
7
|
+
from robot_interface.models.mission.status import MissionStatus, TaskStatus
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def pause_mission(state_machine: "StateMachine") -> bool:
|
|
11
|
+
state_machine.logger.info(f"Pausing mission: {state_machine.current_mission.id}")
|
|
12
|
+
state_machine.current_mission.status = MissionStatus.Paused
|
|
13
|
+
state_machine.current_task.status = TaskStatus.Paused
|
|
14
|
+
|
|
15
|
+
paused_mission_response: ControlMissionResponse = (
|
|
16
|
+
state_machine._make_control_mission_response()
|
|
17
|
+
)
|
|
18
|
+
state_machine.queues.api_pause_mission.output.put(paused_mission_response)
|
|
19
|
+
|
|
20
|
+
state_machine.publish_mission_status()
|
|
21
|
+
state_machine.publish_task_status(task=state_machine.current_task)
|
|
22
|
+
|
|
23
|
+
state_machine.robot.pause()
|
|
24
|
+
return True
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
2
|
+
|
|
3
|
+
if TYPE_CHECKING:
|
|
4
|
+
from isar.state_machine.state_machine import StateMachine
|
|
5
|
+
|
|
6
|
+
from isar.apis.models.models import ControlMissionResponse
|
|
7
|
+
from robot_interface.models.mission.status import MissionStatus, TaskStatus
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def resume_mission(state_machine: "StateMachine") -> bool:
|
|
11
|
+
state_machine.logger.info(f"Resuming mission: {state_machine.current_mission.id}")
|
|
12
|
+
state_machine.current_mission.status = MissionStatus.InProgress
|
|
13
|
+
state_machine.current_mission.error_message = None
|
|
14
|
+
state_machine.current_task.status = TaskStatus.InProgress
|
|
15
|
+
|
|
16
|
+
state_machine.mission_ongoing = True
|
|
17
|
+
|
|
18
|
+
state_machine.publish_mission_status()
|
|
19
|
+
state_machine.publish_task_status(task=state_machine.current_task)
|
|
20
|
+
|
|
21
|
+
resume_mission_response: ControlMissionResponse = (
|
|
22
|
+
state_machine._make_control_mission_response()
|
|
23
|
+
)
|
|
24
|
+
state_machine.queues.api_resume_mission.output.put(resume_mission_response)
|
|
25
|
+
|
|
26
|
+
state_machine.robot.resume()
|
|
27
|
+
return True
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
2
|
+
|
|
3
|
+
if TYPE_CHECKING:
|
|
4
|
+
from isar.state_machine.state_machine import StateMachine
|
|
5
|
+
|
|
6
|
+
from robot_interface.models.exceptions.robot_exceptions import (
|
|
7
|
+
ErrorMessage,
|
|
8
|
+
RobotException,
|
|
9
|
+
RobotInitializeException,
|
|
10
|
+
)
|
|
11
|
+
from robot_interface.models.mission.status import MissionStatus, TaskStatus
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def put_start_mission_on_queue(state_machine: "StateMachine") -> bool:
|
|
15
|
+
state_machine.queues.api_start_mission.output.put(True)
|
|
16
|
+
return True
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def initiate_mission(state_machine: "StateMachine") -> bool:
|
|
20
|
+
state_machine.logger.info(
|
|
21
|
+
f"Initialization successful. Starting new mission: "
|
|
22
|
+
f"{state_machine.current_mission.id}"
|
|
23
|
+
)
|
|
24
|
+
state_machine.log_mission_overview(mission=state_machine.current_mission)
|
|
25
|
+
|
|
26
|
+
state_machine.current_mission.status = MissionStatus.InProgress
|
|
27
|
+
state_machine.publish_mission_status()
|
|
28
|
+
state_machine.current_task = state_machine.task_selector.next_task()
|
|
29
|
+
state_machine.send_task_status()
|
|
30
|
+
if state_machine.current_task is None:
|
|
31
|
+
return False
|
|
32
|
+
|
|
33
|
+
state_machine.current_task.status = TaskStatus.InProgress
|
|
34
|
+
state_machine.publish_task_status(task=state_machine.current_task)
|
|
35
|
+
return True
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def initialize_robot(state_machine: "StateMachine") -> bool:
|
|
39
|
+
try:
|
|
40
|
+
state_machine.robot.initialize()
|
|
41
|
+
except (RobotInitializeException, RobotException) as e:
|
|
42
|
+
state_machine.current_task.error_message = ErrorMessage(
|
|
43
|
+
error_reason=e.error_reason, error_description=e.error_description
|
|
44
|
+
)
|
|
45
|
+
state_machine.logger.error(
|
|
46
|
+
f"Failed to initialize robot because: {e.error_description}"
|
|
47
|
+
)
|
|
48
|
+
_initialization_failed(state_machine)
|
|
49
|
+
return False
|
|
50
|
+
return True
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def set_mission_to_in_progress(state_machine: "StateMachine") -> bool:
|
|
54
|
+
state_machine.current_mission.status = MissionStatus.InProgress
|
|
55
|
+
state_machine.publish_task_status(task=state_machine.current_task)
|
|
56
|
+
state_machine.logger.info(
|
|
57
|
+
f"Successfully initiated "
|
|
58
|
+
f"{type(state_machine.current_task).__name__} "
|
|
59
|
+
f"task: {str(state_machine.current_task.id)[:8]}"
|
|
60
|
+
)
|
|
61
|
+
return True
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def trigger_start_mission_or_task_event(state_machine: "StateMachine") -> bool:
|
|
65
|
+
state_machine.queues.state_machine_start_mission.input.put(
|
|
66
|
+
state_machine.current_mission
|
|
67
|
+
)
|
|
68
|
+
return True
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _initialization_failed(state_machine: "StateMachine") -> None:
|
|
72
|
+
state_machine.queues.api_start_mission.output.put(False)
|
|
73
|
+
state_machine._finalize()
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
2
|
+
|
|
3
|
+
if TYPE_CHECKING:
|
|
4
|
+
from isar.state_machine.state_machine import StateMachine
|
|
5
|
+
|
|
6
|
+
from isar.apis.models.models import ControlMissionResponse
|
|
7
|
+
from robot_interface.models.mission.status import MissionStatus, TaskStatus
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def stop_mission(state_machine: "StateMachine") -> bool:
|
|
11
|
+
if state_machine.current_mission is None:
|
|
12
|
+
state_machine._queue_empty_response()
|
|
13
|
+
state_machine.reset_state_machine()
|
|
14
|
+
return True
|
|
15
|
+
|
|
16
|
+
state_machine.current_mission.status = MissionStatus.Cancelled
|
|
17
|
+
|
|
18
|
+
for task in state_machine.current_mission.tasks:
|
|
19
|
+
if task.status in [
|
|
20
|
+
TaskStatus.NotStarted,
|
|
21
|
+
TaskStatus.InProgress,
|
|
22
|
+
TaskStatus.Paused,
|
|
23
|
+
]:
|
|
24
|
+
task.status = TaskStatus.Cancelled
|
|
25
|
+
|
|
26
|
+
stopped_mission_response: ControlMissionResponse = (
|
|
27
|
+
state_machine._make_control_mission_response()
|
|
28
|
+
)
|
|
29
|
+
state_machine.queues.api_stop_mission.output.put(stopped_mission_response)
|
|
30
|
+
|
|
31
|
+
state_machine.publish_task_status(task=state_machine.current_task)
|
|
32
|
+
state_machine._finalize()
|
|
33
|
+
return True
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Callable
|
|
2
|
+
|
|
3
|
+
if TYPE_CHECKING:
|
|
4
|
+
from isar.state_machine.state_machine import StateMachine
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def def_transition(
|
|
8
|
+
state_machine: "StateMachine", transition_function: Callable[["StateMachine"], bool]
|
|
9
|
+
) -> Callable[[], bool]:
|
|
10
|
+
return lambda: transition_function(state_machine)
|
isar/storage/slimm_storage.py
CHANGED
|
@@ -100,7 +100,7 @@ class SlimmStorage(StorageInterface):
|
|
|
100
100
|
@staticmethod
|
|
101
101
|
def _construct_multiform_request_image(
|
|
102
102
|
filename: str, inspection: Inspection, mission: Mission
|
|
103
|
-
):
|
|
103
|
+
) -> MultipartEncoder:
|
|
104
104
|
array_of_orientation = (
|
|
105
105
|
inspection.metadata.pose.orientation.to_quat_array().tolist()
|
|
106
106
|
)
|
|
@@ -148,7 +148,7 @@ class SlimmStorage(StorageInterface):
|
|
|
148
148
|
filename: str,
|
|
149
149
|
inspection: Inspection,
|
|
150
150
|
mission: Mission,
|
|
151
|
-
):
|
|
151
|
+
) -> MultipartEncoder:
|
|
152
152
|
array_of_orientation = (
|
|
153
153
|
inspection.metadata.pose.orientation.to_quat_array().tolist()
|
|
154
154
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: isar
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.26.0
|
|
4
4
|
Summary: Integration and Supervisory control of Autonomous Robots
|
|
5
5
|
Author-email: Equinor ASA <fg_robots_dev@equinor.com>
|
|
6
6
|
License: Eclipse Public License version 2.0
|
|
@@ -127,6 +127,7 @@ Requires-Dist: transitions
|
|
|
127
127
|
Requires-Dist: uvicorn
|
|
128
128
|
Provides-Extra: dev
|
|
129
129
|
Requires-Dist: black; extra == "dev"
|
|
130
|
+
Requires-Dist: isort; extra == "dev"
|
|
130
131
|
Requires-Dist: mypy; extra == "dev"
|
|
131
132
|
Requires-Dist: pip-tools; extra == "dev"
|
|
132
133
|
Requires-Dist: pre-commit; extra == "dev"
|
|
@@ -350,8 +351,6 @@ In general the states
|
|
|
350
351
|
|
|
351
352
|
```
|
|
352
353
|
States.Off,
|
|
353
|
-
States.Initialize,
|
|
354
|
-
States.Initiate,
|
|
355
354
|
States.Stop,
|
|
356
355
|
States.Monitor,
|
|
357
356
|
States.Paused,
|