isar 1.33.8__py3-none-any.whl → 1.34.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 (49) hide show
  1. isar/apis/models/models.py +2 -5
  2. isar/config/settings.py +1 -8
  3. isar/models/events.py +9 -10
  4. isar/modules.py +5 -11
  5. isar/robot/robot.py +109 -24
  6. isar/robot/robot_monitor_mission.py +399 -0
  7. isar/robot/robot_status.py +0 -10
  8. isar/robot/robot_stop_mission.py +7 -7
  9. isar/robot/robot_upload_inspection.py +80 -0
  10. isar/services/utilities/scheduling_utilities.py +30 -10
  11. isar/state_machine/state_machine.py +7 -223
  12. isar/state_machine/states/await_next_mission.py +7 -6
  13. isar/state_machine/states/going_to_lockdown.py +29 -39
  14. isar/state_machine/states/home.py +11 -15
  15. isar/state_machine/states/intervention_needed.py +7 -6
  16. isar/state_machine/states/lockdown.py +8 -7
  17. isar/state_machine/states/monitor.py +39 -53
  18. isar/state_machine/states/paused.py +19 -17
  19. isar/state_machine/states/pausing.py +12 -27
  20. isar/state_machine/states/pausing_return_home.py +12 -27
  21. isar/state_machine/states/recharging.py +17 -11
  22. isar/state_machine/states/return_home_paused.py +27 -23
  23. isar/state_machine/states/returning_home.py +62 -55
  24. isar/state_machine/states/stopping.py +13 -31
  25. isar/state_machine/states/stopping_go_to_lockdown.py +18 -38
  26. isar/state_machine/states/stopping_return_home.py +26 -26
  27. isar/state_machine/states/unknown_status.py +7 -4
  28. isar/state_machine/transitions/functions/fail_mission.py +1 -9
  29. isar/state_machine/transitions/functions/finish_mission.py +2 -32
  30. isar/state_machine/transitions/functions/pause.py +8 -7
  31. isar/state_machine/transitions/functions/resume.py +3 -12
  32. isar/state_machine/transitions/functions/return_home.py +1 -16
  33. isar/state_machine/transitions/functions/robot_status.py +2 -12
  34. isar/state_machine/transitions/functions/start_mission.py +2 -44
  35. isar/state_machine/transitions/functions/stop.py +4 -33
  36. isar/state_machine/transitions/mission.py +2 -17
  37. isar/state_machine/transitions/return_home.py +3 -24
  38. isar/state_machine/utils/common_event_handlers.py +39 -122
  39. {isar-1.33.8.dist-info → isar-1.34.0.dist-info}/METADATA +2 -63
  40. {isar-1.33.8.dist-info → isar-1.34.0.dist-info}/RECORD +46 -47
  41. robot_interface/models/mission/task.py +0 -10
  42. robot_interface/robot_interface.py +25 -1
  43. isar/mission_planner/sequential_task_selector.py +0 -23
  44. isar/mission_planner/task_selector_interface.py +0 -31
  45. isar/robot/robot_task_status.py +0 -87
  46. {isar-1.33.8.dist-info → isar-1.34.0.dist-info}/WHEEL +0 -0
  47. {isar-1.33.8.dist-info → isar-1.34.0.dist-info}/entry_points.txt +0 -0
  48. {isar-1.33.8.dist-info → isar-1.34.0.dist-info}/licenses/LICENSE +0 -0
  49. {isar-1.33.8.dist-info → isar-1.34.0.dist-info}/top_level.txt +0 -0
@@ -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, TaskStatus
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
@@ -16,28 +16,30 @@ def start_mission_event_handler(
16
16
  response: Event[MissionStartResponse],
17
17
  ) -> Optional[Callable]:
18
18
  mission: Optional[Mission] = event.consume_event()
19
- if mission:
20
- if not state_machine.battery_level_is_above_mission_start_threshold():
21
- response.trigger_event(
22
- MissionStartResponse(
23
- mission_id=mission.id,
24
- mission_started=False,
25
- mission_not_started_reason="Robot battery too low",
26
- )
19
+ if not mission:
20
+ return None
21
+
22
+ if not state_machine.battery_level_is_above_mission_start_threshold():
23
+ response.trigger_event(
24
+ MissionStartResponse(
25
+ mission_id=mission.id,
26
+ mission_started=False,
27
+ mission_not_started_reason="Robot battery too low",
27
28
  )
28
- return None
29
- state_machine.start_mission(mission=mission)
30
- return state_machine.request_mission_start # type: ignore
31
- return None
29
+ )
30
+ return None
31
+ state_machine.start_mission(mission=mission)
32
+ return state_machine.request_mission_start # type: ignore
32
33
 
33
34
 
34
35
  def return_home_event_handler(
35
36
  state_machine: "StateMachine", event: Event[bool]
36
37
  ) -> Optional[Callable]:
37
- if event.consume_event():
38
- state_machine.events.api_requests.return_home.response.trigger_event(True)
39
- return state_machine.request_return_home # type: ignore
40
- return None
38
+ if not event.consume_event():
39
+ return None
40
+
41
+ state_machine.events.api_requests.return_home.response.trigger_event(True)
42
+ return state_machine.request_return_home # type: ignore
41
43
 
42
44
 
43
45
  def robot_status_event_handler(
@@ -48,6 +50,7 @@ def robot_status_event_handler(
48
50
  ) -> Optional[Callable]:
49
51
  if not status_changed_event.consume_event():
50
52
  return None
53
+
51
54
  robot_status: Optional[RobotStatus] = status_event.check()
52
55
  if robot_status != expected_status:
53
56
  return state_machine.robot_status_changed # type: ignore
@@ -58,29 +61,26 @@ def stop_mission_event_handler(
58
61
  state_machine: "StateMachine", event: Event[str]
59
62
  ) -> Optional[Callable]:
60
63
  mission_id: str = event.consume_event()
61
- if mission_id is not None:
62
- if state_machine.current_mission.id == mission_id or mission_id == "":
63
- return state_machine.stop # type: ignore
64
- else:
65
- state_machine.events.api_requests.stop_mission.response.trigger_event(
66
- ControlMissionResponse(
67
- mission_id=mission_id,
68
- mission_status=state_machine.current_mission.status,
69
- mission_not_found=True,
70
- task_id=state_machine.current_task.id,
71
- task_status=state_machine.current_task.status,
72
- )
73
- )
74
- return None
64
+ if mission_id is None:
65
+ return None
66
+
67
+ if state_machine.shared_state.mission_id.check() == mission_id or mission_id == "":
68
+ return state_machine.stop # type: ignore
69
+ else:
70
+ state_machine.events.api_requests.stop_mission.response.trigger_event(
71
+ ControlMissionResponse(success=False, failure_reason="Mission not found")
72
+ )
73
+ return None
75
74
 
76
75
 
77
76
  def mission_started_event_handler(
78
77
  state_machine: "StateMachine",
79
78
  event: Event[bool],
80
79
  ) -> Optional[Callable]:
81
- if event.consume_event():
82
- state_machine.logger.info("Received confirmation that mission has started")
83
- state_machine.mission_ongoing = True
80
+ if not event.consume_event():
81
+ return None
82
+
83
+ state_machine.logger.info("Received confirmation that mission has started")
84
84
  return None
85
85
 
86
86
 
@@ -89,93 +89,10 @@ def mission_failed_event_handler(
89
89
  event: Event[Optional[ErrorMessage]],
90
90
  ) -> Optional[Callable]:
91
91
  mission_failed: Optional[ErrorMessage] = event.consume_event()
92
- if mission_failed is not None:
93
- state_machine.logger.warning(
94
- f"Failed to initiate mission "
95
- f"{str(state_machine.current_mission.id)[:8]} because: "
96
- f"{mission_failed.error_description}"
97
- )
98
- state_machine.current_mission.error_message = ErrorMessage(
99
- error_reason=mission_failed.error_reason,
100
- error_description=mission_failed.error_description,
101
- )
102
- return state_machine.mission_failed_to_start # type: ignore
103
- return None
104
-
105
-
106
- def task_status_failed_event_handler(
107
- state_machine: "StateMachine",
108
- handle_task_completed: Callable[[TaskStatus], Callable],
109
- event: Event[Optional[ErrorMessage]],
110
- ) -> Optional[Callable]:
111
- if not state_machine.mission_ongoing:
92
+ if mission_failed is None:
112
93
  return None
113
94
 
114
- task_failure: Optional[ErrorMessage] = event.consume_event()
115
- if task_failure is not None:
116
- if state_machine.current_task is None:
117
- state_machine.logger.warning(
118
- "Received task status failed event when no task was running"
119
- )
120
- return None
121
- state_machine.awaiting_task_status = False
122
- state_machine.current_task.error_message = task_failure
123
- state_machine.logger.error(
124
- f"Monitoring task {state_machine.current_task.id[:8]} failed "
125
- f"because: {task_failure.error_description}"
126
- )
127
- return _handle_new_task_status(
128
- state_machine, handle_task_completed, TaskStatus.Failed
129
- )
130
-
131
- elif (
132
- not state_machine.awaiting_task_status
133
- and state_machine.current_task is not None
134
- ):
135
- state_machine.events.state_machine_events.task_status_request.trigger_event(
136
- state_machine.current_task.id,
137
- )
138
- state_machine.awaiting_task_status = True
139
- return None
140
-
141
-
142
- def task_status_event_handler(
143
- state_machine: "StateMachine",
144
- handle_task_completed: Callable[[TaskStatus], Callable],
145
- event: Event[Optional[TaskStatus]],
146
- ) -> Optional[Callable]:
147
- if not state_machine.mission_ongoing:
148
- return None
149
-
150
- status: Optional[TaskStatus] = event.consume_event()
151
- if status is not None:
152
- state_machine.awaiting_task_status = False
153
- return _handle_new_task_status(state_machine, handle_task_completed, status)
154
-
155
- elif (
156
- not state_machine.awaiting_task_status
157
- and state_machine.current_task is not None
158
- ):
159
- state_machine.events.state_machine_events.task_status_request.trigger_event(
160
- state_machine.current_task.id,
161
- )
162
- state_machine.awaiting_task_status = True
163
- return None
164
-
165
-
166
- def _handle_new_task_status(
167
- state_machine: "StateMachine",
168
- handle_task_completed: Callable[[TaskStatus], Callable],
169
- status: TaskStatus,
170
- ) -> Optional[Callable]:
171
- if state_machine.current_task is None:
172
- state_machine.iterate_current_task()
173
-
174
- state_machine.current_task.status = status
175
-
176
- if state_machine.current_task.is_finished():
177
- state_machine.report_task_status(state_machine.current_task)
178
- state_machine.publish_task_status(task=state_machine.current_task)
179
-
180
- return handle_task_completed(status)
181
- return None
95
+ state_machine.logger.warning(
96
+ f"Failed to initiate mission because: " f"{mission_failed.error_description}"
97
+ )
98
+ return state_machine.mission_failed_to_start # type: ignore
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: isar
3
- Version: 1.33.8
3
+ Version: 1.34.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
@@ -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
@@ -480,6 +418,7 @@ Enabling API authentication also requires the same environment variables. The re
480
418
  AZURE_CLIENT_ID
481
419
  AZURE_TENANT_ID
482
420
  AZURE_CLIENT_SECRET
421
+ ISAR_BLOB_STORAGE_ACCOUNT
483
422
  ```
484
423
 
485
424
  ## MQTT communication
@@ -1,10 +1,10 @@
1
1
  isar/__init__.py,sha256=cH8p8bVveu3FUL6kBhldcSlLaoHgD82Kd0-SwSNfGXw,87
2
- isar/modules.py,sha256=1QdULg-9gV5Ds4pMV4IQTlImSgsVwqs-g15ifllF2kg,4757
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=4w8oJIvhnarikCZe6d32GG80RtsyaSWLpOpUiEAMr0Q,2097
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=XMPU4d1V6FspjvMmto5TFmC8Slt8Nrpmn9n_tsyPTYk,14423
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=t3INc7FuoZMzQq65kkJOEVltrQ2Wf4uXXQw8XgcYVrk,5792
43
+ isar/models/events.py,sha256=lwjq745VWJLRLdqNke58sWMRt8zz75hUt7t0QkbLsFU,5602
46
44
  isar/models/status.py,sha256=RCsf0p6FEsOFr4FGA6wekRdJIPrCOHMYuteXs2Mwwhk,430
47
- isar/robot/robot.py,sha256=sn-JfJE6lC6Auo13fdS556Uwq_xZE6VSrR4DhNcgOno,7560
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=8201XW9SmYFLVjys9zk972a8ge9aEgCsdm-V1S2VTjM,2924
52
- isar/robot/robot_stop_mission.py,sha256=lKWY9LsBeeMsBZHJEN-Mfm2h3DYoBQT71TgEKlxw9ng,2269
53
- isar/robot/robot_task_status.py,sha256=jefIDfrbly7vWZztWA2zLmK5Yz1NSEytw2YUmprccNA,3161
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=DOI4K2IRDWiYjAXL891VTDLXWoJnw3Z9FYQF4uKVooM,19782
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=lF25XC6vpNO8Mj3DWnmfPBKjS1atl7GdtGbBs2TkaUs,19887
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
- isar/state_machine/states/await_next_mission.py,sha256=3_KrK7nWu1Dm-VA3Rt1gwVsUbn9WuB7MoqLCfobGJSM,2749
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=RLMOH2lXiT3hQhfUtbBVAUfwKUd33yxbjq4uZDZ_Tkc,3388
74
- isar/state_machine/states/home.py,sha256=mCwXSb9LygNpY4qaKEkEYC3nP-6HdsSGmEyjsENumgM,3396
75
- isar/state_machine/states/intervention_needed.py,sha256=A0QYz1vD1tDKAealihXDuoGuMLtXrRfn_AwFoaUhT_Q,1640
76
- isar/state_machine/states/lockdown.py,sha256=mWjhjtky5GbW6BLjsi2TsS0LXI-yq7l29FaqZ2TbTek,1375
77
- isar/state_machine/states/monitor.py,sha256=wmiJrbKntnNw9ExS6-VdJJuW2Q3Jzl9DozmZmEXJ0Cw,5285
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
74
+ isar/state_machine/states/intervention_needed.py,sha256=nv7054e9gBJQ4-Mshs8cczqnD0IN-N-_5qvUR-cNcUM,1633
75
+ isar/state_machine/states/lockdown.py,sha256=ZFw9XMDENECuH3lh89RKeU_3CTzW0ZBvqCKptFJG5xo,1364
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=1ADoTJ3b137k7dmZYxeyGVhyrRF8qotxoV1NaWCbBUk,2870
80
- isar/state_machine/states/pausing.py,sha256=r0GywI1-JDOJLZEnxhnq_yFKza37eL45qHP0ir8SBsY,2762
81
- isar/state_machine/states/pausing_return_home.py,sha256=USyBLWpJqrsJ2hsdyW6i-gvEsog2l7OMJLdgIj-hq0Y,2808
82
- isar/state_machine/states/recharging.py,sha256=6zRppneGXetMaZVvhqCPcSoQyz08tftNhWHYxLCRGc8,2367
83
- isar/state_machine/states/return_home_paused.py,sha256=eBBFFbkLVfY_5yP2kPZnHHwxcwOcHKAxjkQTMat55HU,3398
84
- isar/state_machine/states/returning_home.py,sha256=47M760nPt1dh1P0C0PmfVLrjsZaWz_pGizuBbWZ0OeI,5211
85
- isar/state_machine/states/stopping.py,sha256=h0x94hVoIUJyml3WMrbJlbxG2dzMCeOL1rJoNCQfzGQ,3057
86
- isar/state_machine/states/stopping_go_to_lockdown.py,sha256=npbz0aFbbCpsEbmBYc8wE9DZXztkLkRB-OD7tslbE0c,3166
87
- isar/state_machine/states/stopping_return_home.py,sha256=ub952Ulas3a0lsV_dI4liBiInADo3zaPAGod2bPe_18,2985
88
- isar/state_machine/states/unknown_status.py,sha256=Y-g9cgme5zriyZ6YUzFRYhOvv9ZylCSwfaY8MJ7xEJ0,1791
89
- isar/state_machine/transitions/mission.py,sha256=lwXdC5Jn19gO-wrSaZp3_77mLnvj-CaBYZk61U-qgoo,8211
90
- isar/state_machine/transitions/return_home.py,sha256=ho4Nae-C5BaxVFciFL546EuoMSDIWLqT58E8bNraW4o,6749
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
81
+ isar/state_machine/states/recharging.py,sha256=TSCZuWhDKBW47peeP73k7aBD4_SEMOOdD1GgOdAq6lk,2447
82
+ isar/state_machine/states/return_home_paused.py,sha256=rr5iy8u6zaTMZAGtlf1HlroVShjytxKjE6t-wGym8nU,3355
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
87
+ isar/state_machine/states/unknown_status.py,sha256=Vu07Sk90zFVInf3XdzFl5IaYrdrYaGO7Na7qAOGwjIk,1871
88
+ isar/state_machine/transitions/mission.py,sha256=o3UG9klPqZnWTYVjTFOXYiMFxfbrWIxRvcaTfcqYW_0,7396
89
+ isar/state_machine/transitions/return_home.py,sha256=aLOK7t7Us_TrDhtxhwW4XaIGxB_gU3Drg2uJFuOjS54,5558
91
90
  isar/state_machine/transitions/robot_status.py,sha256=qJMurCpuficOiXs9us4lZJ5p_kOFSwKxJigiXfB1OS8,2430
92
- isar/state_machine/transitions/functions/fail_mission.py,sha256=fBwLW22d8MyrH4047hb3eXn87yLq4v5SkLSIhV9Ge5k,947
93
- isar/state_machine/transitions/functions/finish_mission.py,sha256=TRQrk7HdllmAkwsp25HRZAFAk46Y1hLx3jmkIAKrHDI,1442
94
- isar/state_machine/transitions/functions/pause.py,sha256=QCIKTpB_CAkUVaSy02i2cpLJAWx3-qGN5RPbK9L2qPY,983
95
- isar/state_machine/transitions/functions/resume.py,sha256=SAu4hWomPlrvO0lnpc6uM3rj79Bwq01acnaTEvNbO9U,2116
96
- isar/state_machine/transitions/functions/return_home.py,sha256=5WPO40MtuRKm9-NtyrS6m0IVEit14MXfMKjgZ2sCXRU,1666
97
- isar/state_machine/transitions/functions/robot_status.py,sha256=bA8G5WtY7TA88MKpdOcR6qftFjW8OttntmptZDXpTKg,1365
98
- isar/state_machine/transitions/functions/start_mission.py,sha256=tIpZzYXCoeC6ZWj18UB4DiZuICpxfzFUK23wfunad7Q,2864
99
- isar/state_machine/transitions/functions/stop.py,sha256=4idsNh7v6CRJivD36oKnVmdKlP7mSugTLCh9n12R1-U,2114
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=LG_FmRPaiEMrAeR7JMmOPTXjo9cB7xlsf_jiJxz8KpU,930
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=LqXPB4qojzz0LqKF14g4pUd0HYBqZiCV83I4UMgy9DY,6450
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.33.8.dist-info/licenses/LICENSE,sha256=3fc2-ebLwHWwzfQbulGNRdcNob3SBQeCfEVUDYxsuqw,14058
107
+ isar-1.34.0.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=A6t19lcNU_6AfkYKY5DaF0sheym_SZEAawbfaj36Kjk,8997
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=YzaqJ_KIIm-3S2Y2-BG4Pdkc8sjFMzMx5jj8FtXSmFg,4744
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.33.8.dist-info/METADATA,sha256=0a9aP_euTxYn_zJaBBvt1LXK8w92gQU2GOLmDr0PJ-Y,31190
133
- isar-1.33.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
134
- isar-1.33.8.dist-info/entry_points.txt,sha256=TFam7uNNw7J0iiDYzsH2gfG0u1eV1wh3JTw_HkhgKLk,49
135
- isar-1.33.8.dist-info/top_level.txt,sha256=UwIML2RtuQKCyJJkatcSnyp6-ldDjboB9k9JgKipO-U,21
136
- isar-1.33.8.dist-info/RECORD,,
131
+ isar-1.34.0.dist-info/METADATA,sha256=vPZbiLLgvF0_tZUPtMEyRRM8eezFEyuLiI5wNToNTY0,28866
132
+ isar-1.34.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
133
+ isar-1.34.0.dist-info/entry_points.txt,sha256=TFam7uNNw7J0iiDYzsH2gfG0u1eV1wh3JTw_HkhgKLk,49
134
+ isar-1.34.0.dist-info/top_level.txt,sha256=UwIML2RtuQKCyJJkatcSnyp6-ldDjboB9k9JgKipO-U,21
135
+ isar-1.34.0.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
@@ -1,87 +0,0 @@
1
- import logging
2
- import time
3
- from threading import Event, Thread
4
- from typing import Optional
5
-
6
- from isar.config.settings import settings
7
- from isar.models.events import RobotServiceEvents
8
- from isar.services.utilities.threaded_request import ThreadedRequest
9
- from robot_interface.models.exceptions.robot_exceptions import (
10
- ErrorMessage,
11
- RobotCommunicationException,
12
- RobotCommunicationTimeoutException,
13
- RobotException,
14
- RobotTaskStatusException,
15
- )
16
- from robot_interface.models.mission.status import TaskStatus
17
- from robot_interface.robot_interface import RobotInterface
18
-
19
-
20
- class RobotTaskStatusThread(Thread):
21
- def __init__(
22
- self,
23
- robot_service_events: RobotServiceEvents,
24
- robot: RobotInterface,
25
- signal_thread_quitting: Event,
26
- task_id: str,
27
- ):
28
- self.logger = logging.getLogger("robot")
29
- self.robot_service_events: RobotServiceEvents = robot_service_events
30
- self.robot: RobotInterface = robot
31
- self.start_mission_thread: Optional[ThreadedRequest] = None
32
- self.signal_thread_quitting: Event = signal_thread_quitting
33
- self.task_id: str = task_id
34
- Thread.__init__(self, name="Robot task status thread")
35
-
36
- def run(self) -> None:
37
- task_status: TaskStatus = TaskStatus.NotStarted
38
- failed_task_error: Optional[ErrorMessage] = None
39
- request_status_failure_counter: int = 0
40
-
41
- while (
42
- request_status_failure_counter
43
- < settings.REQUEST_STATUS_FAILURE_COUNTER_LIMIT
44
- ):
45
- if self.signal_thread_quitting.wait(0):
46
- return
47
- if request_status_failure_counter > 0:
48
- time.sleep(settings.REQUEST_STATUS_COMMUNICATION_RECONNECT_DELAY)
49
-
50
- try:
51
- task_status = self.robot.task_status(self.task_id)
52
- request_status_failure_counter = 0
53
- except (
54
- RobotCommunicationTimeoutException,
55
- RobotCommunicationException,
56
- ) as e:
57
- request_status_failure_counter += 1
58
- self.logger.error(
59
- f"Failed to get task status "
60
- f"{request_status_failure_counter} times because: "
61
- f"{e.error_description}"
62
- )
63
-
64
- failed_task_error = ErrorMessage(
65
- error_reason=e.error_reason,
66
- error_description=e.error_description,
67
- )
68
- continue
69
-
70
- except RobotTaskStatusException as e:
71
- failed_task_error = ErrorMessage(
72
- error_reason=e.error_reason,
73
- error_description=e.error_description,
74
- )
75
- break
76
-
77
- except RobotException as e:
78
- failed_task_error = ErrorMessage(
79
- error_reason=e.error_reason,
80
- error_description=e.error_description,
81
- )
82
- break
83
-
84
- self.robot_service_events.task_status_updated.trigger_event(task_status)
85
- return
86
-
87
- self.robot_service_events.task_status_failed.trigger_event(failed_task_error)
File without changes