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
|
@@ -2,21 +2,15 @@ from typing import TYPE_CHECKING, List
|
|
|
2
2
|
|
|
3
3
|
from isar.state_machine.transitions.functions.fail_mission import (
|
|
4
4
|
report_failed_lockdown_and_intervention_needed,
|
|
5
|
-
report_failed_mission_and_finalize,
|
|
6
5
|
report_failed_return_home_and_intervention_needed,
|
|
7
6
|
)
|
|
8
7
|
from isar.state_machine.transitions.functions.return_home import (
|
|
9
8
|
reset_return_home_failure_counter,
|
|
10
|
-
return_home_finished,
|
|
11
|
-
set_return_home_status,
|
|
12
9
|
should_retry_return_home,
|
|
13
10
|
start_return_home_mission,
|
|
14
11
|
)
|
|
15
12
|
from isar.state_machine.transitions.functions.robot_status import clear_robot_status
|
|
16
|
-
from isar.state_machine.transitions.functions.start_mission import
|
|
17
|
-
initialize_robot,
|
|
18
|
-
trigger_start_mission_event,
|
|
19
|
-
)
|
|
13
|
+
from isar.state_machine.transitions.functions.start_mission import initialize_robot
|
|
20
14
|
from isar.state_machine.transitions.functions.utils import def_transition
|
|
21
15
|
|
|
22
16
|
if TYPE_CHECKING:
|
|
@@ -36,35 +30,28 @@ def get_return_home_transitions(state_machine: "StateMachine") -> List[dict]:
|
|
|
36
30
|
state_machine.stopping_return_home_state,
|
|
37
31
|
],
|
|
38
32
|
"dest": state_machine.returning_home_state,
|
|
33
|
+
"before": def_transition(state_machine, start_return_home_mission),
|
|
39
34
|
"conditions": [
|
|
40
|
-
def_transition(state_machine, start_return_home_mission),
|
|
41
|
-
def_transition(state_machine, set_return_home_status),
|
|
42
35
|
def_transition(state_machine, initialize_robot),
|
|
43
36
|
],
|
|
44
|
-
"before": def_transition(state_machine, trigger_start_mission_event),
|
|
45
37
|
},
|
|
46
38
|
{
|
|
47
39
|
"trigger": "request_return_home",
|
|
48
40
|
"source": state_machine.await_next_mission_state,
|
|
49
41
|
"dest": state_machine.await_next_mission_state,
|
|
50
|
-
"before": def_transition(state_machine, report_failed_mission_and_finalize),
|
|
51
42
|
},
|
|
52
43
|
{
|
|
53
44
|
"trigger": "request_return_home",
|
|
54
45
|
"source": state_machine.home_state,
|
|
55
46
|
"dest": state_machine.home_state,
|
|
56
|
-
"before": def_transition(state_machine, report_failed_mission_and_finalize),
|
|
57
47
|
},
|
|
58
48
|
{
|
|
59
49
|
"trigger": "returned_home",
|
|
60
50
|
"source": state_machine.returning_home_state,
|
|
61
51
|
"dest": state_machine.home_state,
|
|
62
|
-
"conditions": [
|
|
63
|
-
def_transition(state_machine, clear_robot_status),
|
|
64
|
-
],
|
|
65
52
|
"before": [
|
|
53
|
+
def_transition(state_machine, clear_robot_status),
|
|
66
54
|
def_transition(state_machine, reset_return_home_failure_counter),
|
|
67
|
-
def_transition(state_machine, return_home_finished),
|
|
68
55
|
],
|
|
69
56
|
},
|
|
70
57
|
{
|
|
@@ -78,7 +65,6 @@ def get_return_home_transitions(state_machine: "StateMachine") -> List[dict]:
|
|
|
78
65
|
"dest": state_machine.recharging_state,
|
|
79
66
|
"before": [
|
|
80
67
|
def_transition(state_machine, reset_return_home_failure_counter),
|
|
81
|
-
def_transition(state_machine, return_home_finished),
|
|
82
68
|
],
|
|
83
69
|
},
|
|
84
70
|
{
|
|
@@ -94,11 +80,8 @@ def get_return_home_transitions(state_machine: "StateMachine") -> List[dict]:
|
|
|
94
80
|
def_transition(state_machine, should_retry_return_home),
|
|
95
81
|
],
|
|
96
82
|
"before": [
|
|
97
|
-
def_transition(state_machine, report_failed_mission_and_finalize),
|
|
98
83
|
def_transition(state_machine, start_return_home_mission),
|
|
99
|
-
def_transition(state_machine, set_return_home_status),
|
|
100
84
|
def_transition(state_machine, initialize_robot),
|
|
101
|
-
def_transition(state_machine, trigger_start_mission_event),
|
|
102
85
|
],
|
|
103
86
|
},
|
|
104
87
|
{
|
|
@@ -110,7 +93,6 @@ def get_return_home_transitions(state_machine: "StateMachine") -> List[dict]:
|
|
|
110
93
|
state_machine, report_failed_return_home_and_intervention_needed
|
|
111
94
|
),
|
|
112
95
|
def_transition(state_machine, reset_return_home_failure_counter),
|
|
113
|
-
def_transition(state_machine, report_failed_mission_and_finalize),
|
|
114
96
|
],
|
|
115
97
|
},
|
|
116
98
|
{
|
|
@@ -127,10 +109,8 @@ def get_return_home_transitions(state_machine: "StateMachine") -> List[dict]:
|
|
|
127
109
|
"dest": state_machine.going_to_lockdown_state,
|
|
128
110
|
"conditions": [
|
|
129
111
|
def_transition(state_machine, start_return_home_mission),
|
|
130
|
-
def_transition(state_machine, set_return_home_status),
|
|
131
112
|
def_transition(state_machine, initialize_robot),
|
|
132
113
|
],
|
|
133
|
-
"before": def_transition(state_machine, trigger_start_mission_event),
|
|
134
114
|
},
|
|
135
115
|
{
|
|
136
116
|
"trigger": "go_to_lockdown",
|
|
@@ -157,7 +137,6 @@ def get_return_home_transitions(state_machine: "StateMachine") -> List[dict]:
|
|
|
157
137
|
def_transition(
|
|
158
138
|
state_machine, report_failed_lockdown_and_intervention_needed
|
|
159
139
|
),
|
|
160
|
-
def_transition(state_machine, report_failed_mission_and_finalize),
|
|
161
140
|
],
|
|
162
141
|
},
|
|
163
142
|
{
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING, List
|
|
2
2
|
|
|
3
3
|
from isar.state_machine.transitions.functions.robot_status import (
|
|
4
|
+
is_available,
|
|
4
5
|
is_available_or_home,
|
|
5
6
|
is_blocked_protective_stop,
|
|
6
7
|
is_offline,
|
|
@@ -13,6 +14,14 @@ if TYPE_CHECKING:
|
|
|
13
14
|
|
|
14
15
|
def get_robot_status_transitions(state_machine: "StateMachine") -> List[dict]:
|
|
15
16
|
robot_status_transitions: List[dict] = [
|
|
17
|
+
{
|
|
18
|
+
"trigger": "robot_status_changed",
|
|
19
|
+
"source": [
|
|
20
|
+
state_machine.unknown_status_state,
|
|
21
|
+
],
|
|
22
|
+
"dest": state_machine.await_next_mission_state,
|
|
23
|
+
"conditions": def_transition(state_machine, is_available),
|
|
24
|
+
},
|
|
16
25
|
{
|
|
17
26
|
"trigger": "robot_status_changed",
|
|
18
27
|
"source": [
|
|
@@ -4,7 +4,7 @@ from isar.apis.models.models import ControlMissionResponse, MissionStartResponse
|
|
|
4
4
|
from isar.models.events import Event
|
|
5
5
|
from robot_interface.models.exceptions.robot_exceptions import ErrorMessage
|
|
6
6
|
from robot_interface.models.mission.mission import Mission
|
|
7
|
-
from robot_interface.models.mission.status import RobotStatus
|
|
7
|
+
from robot_interface.models.mission.status import RobotStatus
|
|
8
8
|
|
|
9
9
|
if TYPE_CHECKING:
|
|
10
10
|
from isar.state_machine.state_machine import StateMachine
|
|
@@ -64,17 +64,11 @@ def stop_mission_event_handler(
|
|
|
64
64
|
if mission_id is None:
|
|
65
65
|
return None
|
|
66
66
|
|
|
67
|
-
if state_machine.
|
|
67
|
+
if state_machine.shared_state.mission_id.check() == mission_id or mission_id == "":
|
|
68
68
|
return state_machine.stop # type: ignore
|
|
69
69
|
else:
|
|
70
70
|
state_machine.events.api_requests.stop_mission.response.trigger_event(
|
|
71
|
-
ControlMissionResponse(
|
|
72
|
-
mission_id=mission_id,
|
|
73
|
-
mission_status=state_machine.current_mission.status,
|
|
74
|
-
mission_not_found=True,
|
|
75
|
-
task_id=state_machine.current_task.id,
|
|
76
|
-
task_status=state_machine.current_task.status,
|
|
77
|
-
)
|
|
71
|
+
ControlMissionResponse(success=False, failure_reason="Mission not found")
|
|
78
72
|
)
|
|
79
73
|
return None
|
|
80
74
|
|
|
@@ -87,7 +81,6 @@ def mission_started_event_handler(
|
|
|
87
81
|
return None
|
|
88
82
|
|
|
89
83
|
state_machine.logger.info("Received confirmation that mission has started")
|
|
90
|
-
state_machine.mission_ongoing = True
|
|
91
84
|
return None
|
|
92
85
|
|
|
93
86
|
|
|
@@ -100,91 +93,6 @@ def mission_failed_event_handler(
|
|
|
100
93
|
return None
|
|
101
94
|
|
|
102
95
|
state_machine.logger.warning(
|
|
103
|
-
f"Failed to initiate mission "
|
|
104
|
-
f"{str(state_machine.current_mission.id)[:8]} because: "
|
|
105
|
-
f"{mission_failed.error_description}"
|
|
106
|
-
)
|
|
107
|
-
state_machine.current_mission.error_message = ErrorMessage(
|
|
108
|
-
error_reason=mission_failed.error_reason,
|
|
109
|
-
error_description=mission_failed.error_description,
|
|
96
|
+
f"Failed to initiate mission because: " f"{mission_failed.error_description}"
|
|
110
97
|
)
|
|
111
98
|
return state_machine.mission_failed_to_start # type: ignore
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
def task_status_failed_event_handler(
|
|
115
|
-
state_machine: "StateMachine",
|
|
116
|
-
handle_task_completed: Callable[[TaskStatus], Callable],
|
|
117
|
-
event: Event[Optional[ErrorMessage]],
|
|
118
|
-
) -> Optional[Callable]:
|
|
119
|
-
if not state_machine.mission_ongoing:
|
|
120
|
-
return None
|
|
121
|
-
|
|
122
|
-
task_failure: Optional[ErrorMessage] = event.consume_event()
|
|
123
|
-
if task_failure is not None:
|
|
124
|
-
if state_machine.current_task is None:
|
|
125
|
-
state_machine.logger.warning(
|
|
126
|
-
"Received task status failed event when no task was running"
|
|
127
|
-
)
|
|
128
|
-
return None
|
|
129
|
-
state_machine.awaiting_task_status = False
|
|
130
|
-
state_machine.current_task.error_message = task_failure
|
|
131
|
-
state_machine.logger.error(
|
|
132
|
-
f"Monitoring task {state_machine.current_task.id[:8]} failed "
|
|
133
|
-
f"because: {task_failure.error_description}"
|
|
134
|
-
)
|
|
135
|
-
return _handle_new_task_status(
|
|
136
|
-
state_machine, handle_task_completed, TaskStatus.Failed
|
|
137
|
-
)
|
|
138
|
-
|
|
139
|
-
elif (
|
|
140
|
-
not state_machine.awaiting_task_status
|
|
141
|
-
and state_machine.current_task is not None
|
|
142
|
-
):
|
|
143
|
-
state_machine.events.state_machine_events.task_status_request.trigger_event(
|
|
144
|
-
state_machine.current_task.id,
|
|
145
|
-
)
|
|
146
|
-
state_machine.awaiting_task_status = True
|
|
147
|
-
return None
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
def task_status_event_handler(
|
|
151
|
-
state_machine: "StateMachine",
|
|
152
|
-
handle_task_completed: Callable[[TaskStatus], Callable],
|
|
153
|
-
event: Event[Optional[TaskStatus]],
|
|
154
|
-
) -> Optional[Callable]:
|
|
155
|
-
if not state_machine.mission_ongoing:
|
|
156
|
-
return None
|
|
157
|
-
|
|
158
|
-
status: Optional[TaskStatus] = event.consume_event()
|
|
159
|
-
if status is not None:
|
|
160
|
-
state_machine.awaiting_task_status = False
|
|
161
|
-
return _handle_new_task_status(state_machine, handle_task_completed, status)
|
|
162
|
-
|
|
163
|
-
elif (
|
|
164
|
-
not state_machine.awaiting_task_status
|
|
165
|
-
and state_machine.current_task is not None
|
|
166
|
-
):
|
|
167
|
-
state_machine.events.state_machine_events.task_status_request.trigger_event(
|
|
168
|
-
state_machine.current_task.id,
|
|
169
|
-
)
|
|
170
|
-
state_machine.awaiting_task_status = True
|
|
171
|
-
return None
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
def _handle_new_task_status(
|
|
175
|
-
state_machine: "StateMachine",
|
|
176
|
-
handle_task_completed: Callable[[TaskStatus], Callable],
|
|
177
|
-
status: TaskStatus,
|
|
178
|
-
) -> Optional[Callable]:
|
|
179
|
-
if state_machine.current_task is None:
|
|
180
|
-
state_machine.iterate_current_task()
|
|
181
|
-
|
|
182
|
-
state_machine.current_task.status = status
|
|
183
|
-
|
|
184
|
-
if not state_machine.current_task.is_finished():
|
|
185
|
-
return None
|
|
186
|
-
|
|
187
|
-
state_machine.report_task_status(state_machine.current_task)
|
|
188
|
-
state_machine.publish_task_status(task=state_machine.current_task)
|
|
189
|
-
|
|
190
|
-
return handle_task_completed(status)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: isar
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.34.1
|
|
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
|
|
@@ -402,68 +402,6 @@ You can create your own storage module by implementing the [storage interface](.
|
|
|
402
402
|
and adding your storage module to the selection [here](./src/isar/modules.py). Note that you must add your module as an
|
|
403
403
|
option in the dictionary.
|
|
404
404
|
|
|
405
|
-
## Task selection
|
|
406
|
-
|
|
407
|
-
The tasks of a mission are selected based on a task selector module, defined by the `TASK_SELECTOR` configuration variable. The default task selector is `sequential`. When using the default module, tasks are executed in sequential order defined by the current input mission.
|
|
408
|
-
|
|
409
|
-
### Implement you own task selector module
|
|
410
|
-
|
|
411
|
-
Custom task selector modules may be added by implementing additional versions of the [task selector interface](./src/isar/mission_planner/task_selector_interface.py).
|
|
412
|
-
|
|
413
|
-
For every custom module, the interface function `next_task()` must be implemented. All interface implementations by default have access to the list of tasks in the current mission through the member `self.tasks`, however additional variables may be supplied by adding arguments to `next_task()`. To comply with the interface definition, the function should return the next task upon every call, and raise the `TaskSelectorStop` exception when all tasks in the current mission have been completed:
|
|
414
|
-
|
|
415
|
-
```python
|
|
416
|
-
class CustomTaskSelector(TaskSelectorInterface):
|
|
417
|
-
...
|
|
418
|
-
def next_task(...) -> Task:
|
|
419
|
-
|
|
420
|
-
# Add code here
|
|
421
|
-
...
|
|
422
|
-
|
|
423
|
-
# Raise `TaskSelectorStop` when all tasks have been completed
|
|
424
|
-
...
|
|
425
|
-
```
|
|
426
|
-
|
|
427
|
-
Optionally, the `initialize()` function may be extended by supplementing the parameter list or function body:
|
|
428
|
-
|
|
429
|
-
```python
|
|
430
|
-
class CustomTaskSelector(TaskSelectorInterface):
|
|
431
|
-
...
|
|
432
|
-
def initialize(self, tasks: List[Task], ...) -> None:
|
|
433
|
-
super.initialize(tasks=tasks)
|
|
434
|
-
|
|
435
|
-
# Add supplementary code here
|
|
436
|
-
...
|
|
437
|
-
```
|
|
438
|
-
|
|
439
|
-
A custom task selector may be made available during [module selection](./src/isar/modules.py) by adding it to the series of options in the dictionary of injector modules. It can then be activated by overriding the task selector configuration variable:
|
|
440
|
-
|
|
441
|
-
```python
|
|
442
|
-
# Add custom task selector module to `modules.py`
|
|
443
|
-
|
|
444
|
-
class CustomTaskSelectorModule(Module):
|
|
445
|
-
@provider
|
|
446
|
-
@singleton
|
|
447
|
-
def provide_task_selector(self) -> TaskSelectorInterface:
|
|
448
|
-
return CustomTaskSelector()
|
|
449
|
-
|
|
450
|
-
...
|
|
451
|
-
|
|
452
|
-
# Make it available to select during injector instantiation
|
|
453
|
-
|
|
454
|
-
modules: dict[str, tuple[Module, Union[str, bool]]] = {
|
|
455
|
-
...
|
|
456
|
-
"task_selector": (
|
|
457
|
-
{
|
|
458
|
-
"sequential": SequentialTaskSelectorModule,
|
|
459
|
-
"custom": CustomTaskSelectorModule
|
|
460
|
-
}
|
|
461
|
-
...
|
|
462
|
-
)
|
|
463
|
-
...
|
|
464
|
-
}
|
|
465
|
-
```
|
|
466
|
-
|
|
467
405
|
## API authentication
|
|
468
406
|
|
|
469
407
|
The API has an option to include user authentication. This can be enabled by setting the environment variable
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
isar/__init__.py,sha256=cH8p8bVveu3FUL6kBhldcSlLaoHgD82Kd0-SwSNfGXw,87
|
|
2
|
-
isar/modules.py,sha256=
|
|
2
|
+
isar/modules.py,sha256=2bo4Z4H2n4vl9BVwV5V5twOUevsLIuXsPiRPICjCB3k,4404
|
|
3
3
|
isar/script.py,sha256=LCb7CHvNyZhQz1OaQ-BUX8w7RDmu975zA0kL6FPwfzk,5912
|
|
4
4
|
isar/apis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
5
|
isar/apis/api.py,sha256=iqCaDDXpSfqfZp0nWg2-A_ujAOh-U0eXwXRRCu49Gk4,15694
|
|
6
6
|
isar/apis/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
-
isar/apis/models/models.py,sha256=
|
|
7
|
+
isar/apis/models/models.py,sha256=c5n2sazvE7atwFhSqQJQSZd-M58l9Kqh0jC4_MAte00,1988
|
|
8
8
|
isar/apis/models/start_mission_definition.py,sha256=v-wt1XDd53Sw7DCdFAkxBBut-xd_uGJa7qMJnE3VI9k,6364
|
|
9
9
|
isar/apis/robot_control/robot_controller.py,sha256=RSVlxbw9D668tHWItVLtyjvAnsJkCs2yUSkU3iqeAcY,1393
|
|
10
10
|
isar/apis/schedule/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -16,7 +16,7 @@ isar/config/configuration_error.py,sha256=rO6WOhafX6xvVib8WxV-eY483Z0PpN-9PxGsq5
|
|
|
16
16
|
isar/config/log.py,sha256=f_mLLz5RSa0kZkdpi1m0iMdwwDc4RQp12mnT6gu2exE,1303
|
|
17
17
|
isar/config/logging.conf,sha256=a7ZBvZkrMDaPU3eRGAjL_eZz6hZsa6BaRJOfx8mbnnM,629
|
|
18
18
|
isar/config/open_telemetry.py,sha256=Lgu0lbRQA-zz6ZDoBKKk0whQex5w18jl1wjqWzHUGdg,3634
|
|
19
|
-
isar/config/settings.py,sha256=
|
|
19
|
+
isar/config/settings.py,sha256=QzdYe8tanBOBJJkJGz7p21loXGwRlbXhQY9PnKNAOdw,14146
|
|
20
20
|
isar/config/certs/ca-cert.pem,sha256=qoNljfad_qcMxhXJIUMLd7nT-Qwf_d4dYSdoOFEOE8I,2179
|
|
21
21
|
isar/config/keyvault/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
22
|
isar/config/keyvault/keyvault_error.py,sha256=zvPCsZLjboxsxthYkxpRERCTFxYV8R5WmACewAUQLwk,41
|
|
@@ -39,18 +39,17 @@ isar/eventhandlers/eventhandler.py,sha256=Wu4IsJA-k0I1F41q7qDT_QJl_OaUHNeGgzPufv
|
|
|
39
39
|
isar/mission_planner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
40
40
|
isar/mission_planner/local_planner.py,sha256=Mkg3vvUBF1jImfQnaFvXLNpKVadR21X4mwDd_wHqJ2w,2520
|
|
41
41
|
isar/mission_planner/mission_planner_interface.py,sha256=UgpPIM4FbrWOD7fGY3Ul64k3uYb8wo0FwSWGewYoVbc,485
|
|
42
|
-
isar/mission_planner/sequential_task_selector.py,sha256=66agRPHuJnEa1vArPyty4muTasAZ50XPjjrSaTdY_Cc,643
|
|
43
|
-
isar/mission_planner/task_selector_interface.py,sha256=pnLeaGPIuyXThcflZ_A7YL2b2xQjFT88hAZidkMomxU,707
|
|
44
42
|
isar/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
45
|
-
isar/models/events.py,sha256=
|
|
43
|
+
isar/models/events.py,sha256=lwjq745VWJLRLdqNke58sWMRt8zz75hUt7t0QkbLsFU,5602
|
|
46
44
|
isar/models/status.py,sha256=RCsf0p6FEsOFr4FGA6wekRdJIPrCOHMYuteXs2Mwwhk,430
|
|
47
|
-
isar/robot/robot.py,sha256=
|
|
45
|
+
isar/robot/robot.py,sha256=gppNNm_4yjjU3fqWrgBP1VaMcQqHXw8eJk2H41mhLco,10703
|
|
48
46
|
isar/robot/robot_battery.py,sha256=goLdgmn61QCgE2Ja3YuiwE_sqJzIhCkS3u90sz1kdug,2089
|
|
47
|
+
isar/robot/robot_monitor_mission.py,sha256=M-_ryHrLSThtHcit6EBVxGgNQI5u3wLlGMC5cXLE5Js,15312
|
|
49
48
|
isar/robot/robot_pause_mission.py,sha256=BFTLVFOnCeuLlyz1Lu12_6EgYBhk8frsviCs-kGq7AA,2277
|
|
50
49
|
isar/robot/robot_start_mission.py,sha256=RPYH9VtXDFdPqhOpt6kSbT17RHkJQPKkQ6d4784_pFE,3210
|
|
51
|
-
isar/robot/robot_status.py,sha256=
|
|
52
|
-
isar/robot/robot_stop_mission.py,sha256=
|
|
53
|
-
isar/robot/
|
|
50
|
+
isar/robot/robot_status.py,sha256=dfAls3s8_Vha7ZMLSYngELqsdpaEpcweAWRHanQj8u8,2361
|
|
51
|
+
isar/robot/robot_stop_mission.py,sha256=noLqg7zdd0TMOOIqj-60tOQ_1wLOKOuUSkPIxZ3j1Ks,2211
|
|
52
|
+
isar/robot/robot_upload_inspection.py,sha256=CFPz6JNinLO5M2MQG6AzYK0jl1hhwi8zaqITeB5A9EU,2659
|
|
54
53
|
isar/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
55
54
|
isar/services/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
56
55
|
isar/services/auth/azure_credentials.py,sha256=9PlwGe5FrPRbW2dp0go7LMp8_l_FRvL8xOXotXwzRDo,364
|
|
@@ -62,52 +61,52 @@ isar/services/service_connections/mqtt/robot_heartbeat_publisher.py,sha256=SKPvY
|
|
|
62
61
|
isar/services/service_connections/mqtt/robot_info_publisher.py,sha256=AxokGk51hRPTxxD2r0P9braPJCMrf1InaCxrUBKkF4g,1402
|
|
63
62
|
isar/services/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
64
63
|
isar/services/utilities/robot_utilities.py,sha256=4zCigsLXfqDC8POHchktSq81zr1_pTaRve_LQsVr6Mk,514
|
|
65
|
-
isar/services/utilities/scheduling_utilities.py,sha256=
|
|
64
|
+
isar/services/utilities/scheduling_utilities.py,sha256=AcoMWpNfNJ-IRu5ulLNtriLTKIVgog47im0yQ_ECanQ,20442
|
|
66
65
|
isar/services/utilities/threaded_request.py,sha256=py4G-_RjnIdHljmKFAcQ6ddqMmp-ZYV39Ece-dqRqjs,1874
|
|
67
66
|
isar/state_machine/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
68
|
-
isar/state_machine/state_machine.py,sha256=
|
|
67
|
+
isar/state_machine/state_machine.py,sha256=lUT-lvtH2r0_ZKLs9AaXx80RWRDJv209w443LpF0G8o,11527
|
|
69
68
|
isar/state_machine/states_enum.py,sha256=EzqLHsNbR7KBMIY5Fa_CDaHm9v6g8UFzq9DJs4x0OU8,746
|
|
70
69
|
isar/state_machine/states/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
71
70
|
isar/state_machine/states/await_next_mission.py,sha256=H1QN62S6iUYzLgyzK8UVG-0PEWGiCDdsIOjWC7BWD_Q,2742
|
|
72
71
|
isar/state_machine/states/blocked_protective_stop.py,sha256=HJr_jH8OdHMuX8zhjlF5jtNAfMCxkA1X7nOGmkAz-RY,1263
|
|
73
|
-
isar/state_machine/states/going_to_lockdown.py,sha256=
|
|
74
|
-
isar/state_machine/states/home.py,sha256=
|
|
72
|
+
isar/state_machine/states/going_to_lockdown.py,sha256=qOmJt5V51_fhJobIzzFyFW-sxfoktG8_Vt9a4N-EmWs,2725
|
|
73
|
+
isar/state_machine/states/home.py,sha256=nIuHVDEYkMuoGTdf0nTUlOaNblYVDoZdl_njeE2sFNQ,3161
|
|
75
74
|
isar/state_machine/states/intervention_needed.py,sha256=nv7054e9gBJQ4-Mshs8cczqnD0IN-N-_5qvUR-cNcUM,1633
|
|
76
75
|
isar/state_machine/states/lockdown.py,sha256=ZFw9XMDENECuH3lh89RKeU_3CTzW0ZBvqCKptFJG5xo,1364
|
|
77
|
-
isar/state_machine/states/monitor.py,sha256=
|
|
76
|
+
isar/state_machine/states/monitor.py,sha256=UIvqU2uNashm-ZCYuGr3GkpuwWbmuGC7ipG_XSHgO34,4514
|
|
78
77
|
isar/state_machine/states/offline.py,sha256=k1UdcRWLd6lJiL5cnpHKBkvMY4xZMt_x7XIauy-Rgww,1219
|
|
79
|
-
isar/state_machine/states/paused.py,sha256=
|
|
80
|
-
isar/state_machine/states/pausing.py,sha256=
|
|
81
|
-
isar/state_machine/states/pausing_return_home.py,sha256=
|
|
78
|
+
isar/state_machine/states/paused.py,sha256=F5XIzIcnR7_BvIDyMu8CWEdsmXRukUFTYy0-H1ldWeo,2849
|
|
79
|
+
isar/state_machine/states/pausing.py,sha256=CJf_wqpajizv-UY3gL8ctHbPbVP-jXkLsaQiCgfCod4,2138
|
|
80
|
+
isar/state_machine/states/pausing_return_home.py,sha256=bQjNp8cC90x7yoTLccrx3oIdaj9at-34p9ez1OqKrmE,2184
|
|
82
81
|
isar/state_machine/states/recharging.py,sha256=TSCZuWhDKBW47peeP73k7aBD4_SEMOOdD1GgOdAq6lk,2447
|
|
83
82
|
isar/state_machine/states/return_home_paused.py,sha256=rr5iy8u6zaTMZAGtlf1HlroVShjytxKjE6t-wGym8nU,3355
|
|
84
|
-
isar/state_machine/states/returning_home.py,sha256=
|
|
85
|
-
isar/state_machine/states/stopping.py,sha256=
|
|
86
|
-
isar/state_machine/states/stopping_go_to_lockdown.py,sha256=
|
|
87
|
-
isar/state_machine/states/stopping_return_home.py,sha256=
|
|
83
|
+
isar/state_machine/states/returning_home.py,sha256=7bWLE2HU0rObPzM2evY8Wzl9hmerJMS0xaRt4vs3tFQ,5318
|
|
84
|
+
isar/state_machine/states/stopping.py,sha256=MhIU1kZCjOQpZBZ5EQ299zdvBWNaDNVdksh7Zw4Hk68,2208
|
|
85
|
+
isar/state_machine/states/stopping_go_to_lockdown.py,sha256=yl0HFxIBKFCWGQixTULuYb_Z-dwrPeI8TioZ9AQf1Lk,2264
|
|
86
|
+
isar/state_machine/states/stopping_return_home.py,sha256=HtoZfSXWLGCRChITZCKjOufowwZzQaJLCZGaYsjP1mE,2854
|
|
88
87
|
isar/state_machine/states/unknown_status.py,sha256=Vu07Sk90zFVInf3XdzFl5IaYrdrYaGO7Na7qAOGwjIk,1871
|
|
89
|
-
isar/state_machine/transitions/mission.py,sha256=
|
|
90
|
-
isar/state_machine/transitions/return_home.py,sha256=
|
|
91
|
-
isar/state_machine/transitions/robot_status.py,sha256=
|
|
92
|
-
isar/state_machine/transitions/functions/fail_mission.py,sha256=
|
|
93
|
-
isar/state_machine/transitions/functions/finish_mission.py,sha256=
|
|
94
|
-
isar/state_machine/transitions/functions/pause.py,sha256=
|
|
95
|
-
isar/state_machine/transitions/functions/resume.py,sha256=
|
|
96
|
-
isar/state_machine/transitions/functions/return_home.py,sha256=
|
|
97
|
-
isar/state_machine/transitions/functions/robot_status.py,sha256=
|
|
98
|
-
isar/state_machine/transitions/functions/start_mission.py,sha256=
|
|
99
|
-
isar/state_machine/transitions/functions/stop.py,sha256=
|
|
88
|
+
isar/state_machine/transitions/mission.py,sha256=o3UG9klPqZnWTYVjTFOXYiMFxfbrWIxRvcaTfcqYW_0,7396
|
|
89
|
+
isar/state_machine/transitions/return_home.py,sha256=aLOK7t7Us_TrDhtxhwW4XaIGxB_gU3Drg2uJFuOjS54,5558
|
|
90
|
+
isar/state_machine/transitions/robot_status.py,sha256=7fEXHBBo8A6z8eUeNXs01xQ87l26siPB3kyTSbcnPcc,2738
|
|
91
|
+
isar/state_machine/transitions/functions/fail_mission.py,sha256=NFPGIPE0EtefUETbf8Z8plBWghcRQBrbup5xaxF3h6Y,604
|
|
92
|
+
isar/state_machine/transitions/functions/finish_mission.py,sha256=K9paNVz0wbWSkCWvVBaKTM54vdHBH-TNuqG1EstEI8w,229
|
|
93
|
+
isar/state_machine/transitions/functions/pause.py,sha256=8cQIvXDb1hKS-K6-a0fmcqJHde0FRzS-n4N8_EBSA3w,1089
|
|
94
|
+
isar/state_machine/transitions/functions/resume.py,sha256=HWmM1T4jvMPq3by4rns9G0lKUtWMegkFkGtbILvzfKE,1600
|
|
95
|
+
isar/state_machine/transitions/functions/return_home.py,sha256=UBXOfYKlvsmpnmUeKFkc2483fdY9pX70F4pmndjCs8Y,1148
|
|
96
|
+
isar/state_machine/transitions/functions/robot_status.py,sha256=dVh0cY6KLt0xcZ2jBQWt4GbR_CPJvrQZWhP3GEpDCZY,1105
|
|
97
|
+
isar/state_machine/transitions/functions/start_mission.py,sha256=1Op-Dutfmbc6kH1bHHu7obQ5I1G5jnYoH4wx5qSXoI0,1254
|
|
98
|
+
isar/state_machine/transitions/functions/stop.py,sha256=Oukmv0ZAjIP6xVThnCinacXU5U2fzyOVoZULkrS8OIU,1152
|
|
100
99
|
isar/state_machine/transitions/functions/utils.py,sha256=Wa72Ocq4QT1E6qkpEJZQ3h5o33pGvx7Tlkt2JZ2Grbk,314
|
|
101
|
-
isar/state_machine/utils/common_event_handlers.py,sha256=
|
|
100
|
+
isar/state_machine/utils/common_event_handlers.py,sha256=u0e9sWWjuNC5uCGUGD-oe2fRKdAnslVZJcyz7SuxHhs,3188
|
|
102
101
|
isar/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
103
102
|
isar/storage/blob_storage.py,sha256=d44z3XpZDUbiKwN8Av2gytTJxnefMXrp5VhiGm4PWxU,3703
|
|
104
103
|
isar/storage/local_storage.py,sha256=Rn-iiiz9DI7PzIhevOMshPIaqzJaqBXeVJMQRhVSl2M,2191
|
|
105
104
|
isar/storage/storage_interface.py,sha256=x-imVeQTdL6dCaTaPTHpXwCR6N4e27WxK_Vpumg0x-Y,1230
|
|
106
105
|
isar/storage/uploader.py,sha256=0BBrxyZGGRkNxGeZeoREucegs4yKUow2523oLEie07o,10841
|
|
107
106
|
isar/storage/utilities.py,sha256=oLH0Rp7UtrQQdilfITnmXO1Z0ExdeDhBImYHid55vBA,3449
|
|
108
|
-
isar-1.
|
|
107
|
+
isar-1.34.1.dist-info/licenses/LICENSE,sha256=3fc2-ebLwHWwzfQbulGNRdcNob3SBQeCfEVUDYxsuqw,14058
|
|
109
108
|
robot_interface/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
110
|
-
robot_interface/robot_interface.py,sha256=
|
|
109
|
+
robot_interface/robot_interface.py,sha256=3JAVCzg4WV4gYgDxGfdmXPPlVETmwyoqLh7QZJMerKU,9886
|
|
111
110
|
robot_interface/test_robot_interface.py,sha256=FV1urn7SbsMyWBIcTKjsBwAG4IsXeZ6pLHE0mA9EGGs,692
|
|
112
111
|
robot_interface/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
113
112
|
robot_interface/models/exceptions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -118,7 +117,7 @@ robot_interface/models/inspection/inspection.py,sha256=cjAvekL8r82s7bgukWeXpYylH
|
|
|
118
117
|
robot_interface/models/mission/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
119
118
|
robot_interface/models/mission/mission.py,sha256=MQ9p5cuclLXexaZu9bkDh5-aN99eunvYC0vP-Z_kUwI,960
|
|
120
119
|
robot_interface/models/mission/status.py,sha256=3KHA02Jer-HSOwFmUhRkE6cr81H1zPgbwB3p4IjchEY,702
|
|
121
|
-
robot_interface/models/mission/task.py,sha256=
|
|
120
|
+
robot_interface/models/mission/task.py,sha256=3GSrq4TQu7Ztz6GfWaT-ONwF8HE23SRztOSH3cj7qJ0,4430
|
|
122
121
|
robot_interface/models/robots/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
123
122
|
robot_interface/models/robots/battery_state.py,sha256=ktOtJ8ltdK0k_i7BoqYfhc5dbOzIG6Oo-uWC67fCWio,98
|
|
124
123
|
robot_interface/models/robots/media.py,sha256=8A-CuuubfngzPprs6zWB9hSaqe3jzgsE8rcCzRX2Uto,227
|
|
@@ -129,8 +128,8 @@ robot_interface/telemetry/payloads.py,sha256=A0SWiG609k6o6-Y3vhDWE6an2-_m7D_ND85
|
|
|
129
128
|
robot_interface/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
130
129
|
robot_interface/utilities/json_service.py,sha256=9N1zijW7K4d3WFR2autpaS8U9o1ibymiOX-6stTKCyk,1243
|
|
131
130
|
robot_interface/utilities/uuid_string_factory.py,sha256=_NQIbBQ56w0qqO0MUDP6aPpHbxW7ATRhK8HnQiBSLkc,76
|
|
132
|
-
isar-1.
|
|
133
|
-
isar-1.
|
|
134
|
-
isar-1.
|
|
135
|
-
isar-1.
|
|
136
|
-
isar-1.
|
|
131
|
+
isar-1.34.1.dist-info/METADATA,sha256=ZKzgxhCE_6t1-2uRDKSWqqSXOF8xrSxdg41pBcpLP8E,28866
|
|
132
|
+
isar-1.34.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
133
|
+
isar-1.34.1.dist-info/entry_points.txt,sha256=TFam7uNNw7J0iiDYzsH2gfG0u1eV1wh3JTw_HkhgKLk,49
|
|
134
|
+
isar-1.34.1.dist-info/top_level.txt,sha256=UwIML2RtuQKCyJJkatcSnyp6-ldDjboB9k9JgKipO-U,21
|
|
135
|
+
isar-1.34.1.dist-info/RECORD,,
|
|
@@ -40,16 +40,6 @@ class Task(BaseModel):
|
|
|
40
40
|
tag_id: Optional[str] = Field(default=None)
|
|
41
41
|
id: str = Field(default_factory=uuid4_string, frozen=True)
|
|
42
42
|
|
|
43
|
-
def is_finished(self) -> bool:
|
|
44
|
-
if (
|
|
45
|
-
self.status == TaskStatus.Successful
|
|
46
|
-
or self.status == TaskStatus.PartiallySuccessful
|
|
47
|
-
or self.status == TaskStatus.Cancelled
|
|
48
|
-
or self.status == TaskStatus.Failed
|
|
49
|
-
):
|
|
50
|
-
return True
|
|
51
|
-
return False
|
|
52
|
-
|
|
53
43
|
|
|
54
44
|
class InspectionTask(Task):
|
|
55
45
|
"""
|
|
@@ -5,7 +5,7 @@ from typing import Callable, List, Optional
|
|
|
5
5
|
|
|
6
6
|
from robot_interface.models.inspection.inspection import Inspection
|
|
7
7
|
from robot_interface.models.mission.mission import Mission
|
|
8
|
-
from robot_interface.models.mission.status import RobotStatus, TaskStatus
|
|
8
|
+
from robot_interface.models.mission.status import MissionStatus, RobotStatus, TaskStatus
|
|
9
9
|
from robot_interface.models.mission.task import InspectionTask
|
|
10
10
|
from robot_interface.models.robots.media import MediaConfig
|
|
11
11
|
|
|
@@ -51,12 +51,36 @@ class RobotInterface(metaclass=ABCMeta):
|
|
|
51
51
|
RobotCommunicationTimeoutException or RobotCommunicationException
|
|
52
52
|
If the robot package is unable to communicate with the robot API the fetching
|
|
53
53
|
of task status will be attempted again until a certain number of retries
|
|
54
|
+
RobotTaskStatusException
|
|
55
|
+
If there was an error when retrieving the task status
|
|
54
56
|
RobotException
|
|
55
57
|
If the task status could not be retrieved.
|
|
56
58
|
|
|
57
59
|
"""
|
|
58
60
|
raise NotImplementedError
|
|
59
61
|
|
|
62
|
+
@abstractmethod
|
|
63
|
+
def mission_status(self, mission_id: str) -> MissionStatus:
|
|
64
|
+
"""Gets the status of the mission with ID mission_id on robot.
|
|
65
|
+
|
|
66
|
+
Returns
|
|
67
|
+
-------
|
|
68
|
+
MissionStatus
|
|
69
|
+
Status of the execution of mission.
|
|
70
|
+
|
|
71
|
+
Raises
|
|
72
|
+
------
|
|
73
|
+
RobotCommunicationTimeoutException or RobotCommunicationException
|
|
74
|
+
If the robot package is unable to communicate with the robot API the fetching
|
|
75
|
+
of mission status will be attempted again until a certain number of retries
|
|
76
|
+
RobotMissionStatusException
|
|
77
|
+
If there was an error when retrieving the mission status
|
|
78
|
+
RobotException
|
|
79
|
+
If the mission status could not be retrieved.
|
|
80
|
+
|
|
81
|
+
"""
|
|
82
|
+
raise NotImplementedError
|
|
83
|
+
|
|
60
84
|
@abstractmethod
|
|
61
85
|
def stop(self) -> None:
|
|
62
86
|
"""Stops the execution of the current task and corresponding mission.
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
from typing import Iterator, List
|
|
2
|
-
|
|
3
|
-
from isar.mission_planner.task_selector_interface import (
|
|
4
|
-
TaskSelectorInterface,
|
|
5
|
-
TaskSelectorStop,
|
|
6
|
-
)
|
|
7
|
-
from robot_interface.models.mission.task import TASKS
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class SequentialTaskSelector(TaskSelectorInterface):
|
|
11
|
-
def __init__(self) -> None:
|
|
12
|
-
super().__init__()
|
|
13
|
-
self._iterator: Iterator = None
|
|
14
|
-
|
|
15
|
-
def initialize(self, tasks: List[TASKS]) -> None:
|
|
16
|
-
super().initialize(tasks=tasks)
|
|
17
|
-
self._iterator = iter(self.tasks)
|
|
18
|
-
|
|
19
|
-
def next_task(self) -> TASKS:
|
|
20
|
-
try:
|
|
21
|
-
return next(self._iterator)
|
|
22
|
-
except StopIteration:
|
|
23
|
-
raise TaskSelectorStop
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
from abc import ABCMeta, abstractmethod
|
|
2
|
-
from typing import List
|
|
3
|
-
|
|
4
|
-
from robot_interface.models.mission.task import TASKS
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class TaskSelectorInterface(metaclass=ABCMeta):
|
|
8
|
-
def __init__(self) -> None:
|
|
9
|
-
self.tasks: List[TASKS] = None
|
|
10
|
-
|
|
11
|
-
def initialize(self, tasks: List[TASKS]) -> None:
|
|
12
|
-
self.tasks = tasks
|
|
13
|
-
|
|
14
|
-
@abstractmethod
|
|
15
|
-
def next_task(self) -> TASKS:
|
|
16
|
-
"""
|
|
17
|
-
Returns
|
|
18
|
-
-------
|
|
19
|
-
Task
|
|
20
|
-
Returns the next task from the list of tasks
|
|
21
|
-
|
|
22
|
-
Raises
|
|
23
|
-
------
|
|
24
|
-
TaskSelectorStop
|
|
25
|
-
If all tasks have been selected, and the task selection process is complete.
|
|
26
|
-
"""
|
|
27
|
-
pass
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
class TaskSelectorStop(Exception):
|
|
31
|
-
pass
|