isar 1.20.2__py3-none-any.whl → 1.34.13__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.
Files changed (134) hide show
  1. isar/apis/api.py +135 -86
  2. isar/apis/models/__init__.py +0 -1
  3. isar/apis/models/models.py +21 -11
  4. isar/apis/models/start_mission_definition.py +115 -170
  5. isar/apis/robot_control/robot_controller.py +41 -0
  6. isar/apis/schedule/scheduling_controller.py +123 -187
  7. isar/apis/security/authentication.py +5 -5
  8. isar/config/certs/ca-cert.pem +33 -31
  9. isar/config/keyvault/keyvault_service.py +4 -2
  10. isar/config/log.py +45 -40
  11. isar/config/logging.conf +16 -31
  12. isar/config/open_telemetry.py +102 -0
  13. isar/config/settings.py +74 -117
  14. isar/eventhandlers/eventhandler.py +123 -0
  15. isar/models/events.py +184 -0
  16. isar/models/status.py +22 -0
  17. isar/modules.py +117 -200
  18. isar/robot/robot.py +383 -0
  19. isar/robot/robot_battery.py +60 -0
  20. isar/robot/robot_monitor_mission.py +357 -0
  21. isar/robot/robot_pause_mission.py +74 -0
  22. isar/robot/robot_resume_mission.py +67 -0
  23. isar/robot/robot_start_mission.py +66 -0
  24. isar/robot/robot_status.py +61 -0
  25. isar/robot/robot_stop_mission.py +68 -0
  26. isar/robot/robot_upload_inspection.py +75 -0
  27. isar/script.py +58 -41
  28. isar/services/service_connections/mqtt/mqtt_client.py +47 -11
  29. isar/services/service_connections/mqtt/robot_heartbeat_publisher.py +5 -2
  30. isar/services/service_connections/mqtt/robot_info_publisher.py +3 -3
  31. isar/services/service_connections/persistent_memory.py +69 -0
  32. isar/services/utilities/mqtt_utilities.py +93 -0
  33. isar/services/utilities/robot_utilities.py +20 -0
  34. isar/services/utilities/scheduling_utilities.py +386 -100
  35. isar/state_machine/state_machine.py +242 -539
  36. isar/state_machine/states/__init__.py +0 -8
  37. isar/state_machine/states/await_next_mission.py +114 -0
  38. isar/state_machine/states/blocked_protective_stop.py +60 -0
  39. isar/state_machine/states/going_to_lockdown.py +95 -0
  40. isar/state_machine/states/going_to_recharging.py +92 -0
  41. isar/state_machine/states/home.py +115 -0
  42. isar/state_machine/states/intervention_needed.py +77 -0
  43. isar/state_machine/states/lockdown.py +38 -0
  44. isar/state_machine/states/maintenance.py +43 -0
  45. isar/state_machine/states/monitor.py +137 -247
  46. isar/state_machine/states/offline.py +51 -53
  47. isar/state_machine/states/paused.py +92 -23
  48. isar/state_machine/states/pausing.py +48 -0
  49. isar/state_machine/states/pausing_return_home.py +48 -0
  50. isar/state_machine/states/recharging.py +80 -0
  51. isar/state_machine/states/resuming.py +57 -0
  52. isar/state_machine/states/resuming_return_home.py +64 -0
  53. isar/state_machine/states/return_home_paused.py +109 -0
  54. isar/state_machine/states/returning_home.py +217 -0
  55. isar/state_machine/states/stopping.py +69 -0
  56. isar/state_machine/states/stopping_due_to_maintenance.py +61 -0
  57. isar/state_machine/states/stopping_go_to_lockdown.py +60 -0
  58. isar/state_machine/states/stopping_go_to_recharge.py +51 -0
  59. isar/state_machine/states/stopping_paused_mission.py +36 -0
  60. isar/state_machine/states/stopping_paused_return_home.py +59 -0
  61. isar/state_machine/states/stopping_return_home.py +59 -0
  62. isar/state_machine/states/unknown_status.py +74 -0
  63. isar/state_machine/states_enum.py +23 -5
  64. isar/state_machine/transitions/mission.py +225 -0
  65. isar/state_machine/transitions/return_home.py +108 -0
  66. isar/state_machine/transitions/robot_status.py +87 -0
  67. isar/state_machine/utils/common_event_handlers.py +138 -0
  68. isar/storage/blob_storage.py +70 -52
  69. isar/storage/local_storage.py +25 -12
  70. isar/storage/storage_interface.py +28 -7
  71. isar/storage/uploader.py +174 -55
  72. isar/storage/utilities.py +32 -29
  73. {isar-1.20.2.dist-info → isar-1.34.13.dist-info}/METADATA +119 -123
  74. isar-1.34.13.dist-info/RECORD +120 -0
  75. {isar-1.20.2.dist-info → isar-1.34.13.dist-info}/WHEEL +1 -1
  76. {isar-1.20.2.dist-info → isar-1.34.13.dist-info}/entry_points.txt +1 -0
  77. robot_interface/models/exceptions/robot_exceptions.py +91 -41
  78. robot_interface/models/inspection/__init__.py +0 -13
  79. robot_interface/models/inspection/inspection.py +42 -33
  80. robot_interface/models/mission/mission.py +14 -15
  81. robot_interface/models/mission/status.py +20 -26
  82. robot_interface/models/mission/task.py +154 -121
  83. robot_interface/models/robots/battery_state.py +6 -0
  84. robot_interface/models/robots/media.py +13 -0
  85. robot_interface/models/robots/robot_model.py +7 -7
  86. robot_interface/robot_interface.py +119 -84
  87. robot_interface/telemetry/mqtt_client.py +74 -12
  88. robot_interface/telemetry/payloads.py +91 -13
  89. robot_interface/utilities/json_service.py +7 -1
  90. isar/config/configuration_error.py +0 -2
  91. isar/config/keyvault/keyvault_error.py +0 -2
  92. isar/config/predefined_mission_definition/__init__.py +0 -0
  93. isar/config/predefined_mission_definition/default_exr.json +0 -51
  94. isar/config/predefined_mission_definition/default_mission.json +0 -91
  95. isar/config/predefined_mission_definition/default_turtlebot.json +0 -124
  96. isar/config/predefined_missions/__init__.py +0 -0
  97. isar/config/predefined_missions/default.json +0 -92
  98. isar/config/predefined_missions/default_turtlebot.json +0 -110
  99. isar/config/predefined_poses/__init__.py +0 -0
  100. isar/config/predefined_poses/predefined_poses.py +0 -616
  101. isar/config/settings.env +0 -25
  102. isar/mission_planner/__init__.py +0 -0
  103. isar/mission_planner/local_planner.py +0 -82
  104. isar/mission_planner/mission_planner_interface.py +0 -26
  105. isar/mission_planner/sequential_task_selector.py +0 -23
  106. isar/mission_planner/task_selector_interface.py +0 -31
  107. isar/models/communication/__init__.py +0 -0
  108. isar/models/communication/message.py +0 -12
  109. isar/models/communication/queues/__init__.py +0 -4
  110. isar/models/communication/queues/queue_io.py +0 -12
  111. isar/models/communication/queues/queue_timeout_error.py +0 -2
  112. isar/models/communication/queues/queues.py +0 -19
  113. isar/models/communication/queues/status_queue.py +0 -20
  114. isar/models/mission_metadata/__init__.py +0 -0
  115. isar/services/auth/__init__.py +0 -0
  116. isar/services/auth/azure_credentials.py +0 -14
  117. isar/services/readers/__init__.py +0 -0
  118. isar/services/readers/base_reader.py +0 -37
  119. isar/services/service_connections/request_handler.py +0 -153
  120. isar/services/service_connections/stid/__init__.py +0 -0
  121. isar/services/utilities/queue_utilities.py +0 -39
  122. isar/services/utilities/threaded_request.py +0 -68
  123. isar/state_machine/states/idle.py +0 -85
  124. isar/state_machine/states/initialize.py +0 -71
  125. isar/state_machine/states/initiate.py +0 -142
  126. isar/state_machine/states/off.py +0 -18
  127. isar/state_machine/states/stop.py +0 -95
  128. isar/storage/slimm_storage.py +0 -191
  129. isar-1.20.2.dist-info/RECORD +0 -116
  130. robot_interface/models/initialize/__init__.py +0 -1
  131. robot_interface/models/initialize/initialize_params.py +0 -9
  132. robot_interface/models/mission/step.py +0 -234
  133. {isar-1.20.2.dist-info → isar-1.34.13.dist-info/licenses}/LICENSE +0 -0
  134. {isar-1.20.2.dist-info → isar-1.34.13.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,225 @@
1
+ from typing import TYPE_CHECKING, List
2
+
3
+ if TYPE_CHECKING:
4
+ from isar.state_machine.state_machine import StateMachine
5
+
6
+
7
+ def get_mission_transitions(state_machine: "StateMachine") -> List[dict]:
8
+ mission_transitions: List[dict] = [
9
+ {
10
+ "trigger": "pause",
11
+ "source": state_machine.monitor_state,
12
+ "dest": state_machine.pausing_state,
13
+ },
14
+ {
15
+ "trigger": "mission_paused",
16
+ "source": state_machine.pausing_state,
17
+ "dest": state_machine.paused_state,
18
+ },
19
+ {
20
+ "trigger": "mission_pausing_failed",
21
+ "source": state_machine.pausing_state,
22
+ "dest": state_machine.monitor_state,
23
+ },
24
+ {
25
+ "trigger": "pause_return_home",
26
+ "source": state_machine.returning_home_state,
27
+ "dest": state_machine.pausing_return_home_state,
28
+ },
29
+ {
30
+ "trigger": "return_home_mission_pausing_failed",
31
+ "source": state_machine.pausing_return_home_state,
32
+ "dest": state_machine.returning_home_state,
33
+ },
34
+ {
35
+ "trigger": "return_home_mission_paused",
36
+ "source": state_machine.pausing_return_home_state,
37
+ "dest": state_machine.return_home_paused_state,
38
+ },
39
+ {
40
+ "trigger": "resume",
41
+ "source": state_machine.paused_state,
42
+ "dest": state_machine.resuming_state,
43
+ },
44
+ {
45
+ "trigger": "mission_resumed",
46
+ "source": state_machine.resuming_state,
47
+ "dest": state_machine.monitor_state,
48
+ },
49
+ {
50
+ "trigger": "mission_resuming_failed",
51
+ "source": state_machine.resuming_state,
52
+ "dest": state_machine.await_next_mission_state,
53
+ },
54
+ {
55
+ "trigger": "resume",
56
+ "source": state_machine.return_home_paused_state,
57
+ "dest": state_machine.resuming_return_home_state,
58
+ },
59
+ {
60
+ "trigger": "return_home_mission_resumed",
61
+ "source": state_machine.resuming_return_home_state,
62
+ "dest": state_machine.returning_home_state,
63
+ },
64
+ {
65
+ "trigger": "return_home_mission_resuming_failed",
66
+ "source": state_machine.resuming_return_home_state,
67
+ "dest": state_machine.await_next_mission_state,
68
+ },
69
+ {
70
+ "trigger": "resume_lockdown",
71
+ "source": state_machine.return_home_paused_state,
72
+ "dest": state_machine.going_to_lockdown_state,
73
+ },
74
+ {
75
+ "trigger": "stop",
76
+ "source": [
77
+ state_machine.await_next_mission_state,
78
+ state_machine.monitor_state,
79
+ ],
80
+ "dest": state_machine.stopping_state,
81
+ },
82
+ {
83
+ "trigger": "stop",
84
+ "source": [
85
+ state_machine.paused_state,
86
+ ],
87
+ "dest": state_machine.stopping_paused_mission_state,
88
+ },
89
+ {
90
+ "trigger": "stop_go_to_lockdown",
91
+ "source": [
92
+ state_machine.monitor_state,
93
+ state_machine.paused_state,
94
+ ],
95
+ "dest": state_machine.stopping_go_to_lockdown_state,
96
+ },
97
+ {
98
+ "trigger": "stop_go_to_recharge",
99
+ "source": state_machine.monitor_state,
100
+ "dest": state_machine.stopping_go_to_recharge_state,
101
+ },
102
+ {
103
+ "trigger": "stop_due_to_maintenance",
104
+ "source": [
105
+ state_machine.monitor_state,
106
+ state_machine.paused_state,
107
+ # state_machine.pausing_return_home_state, # Not neccessary since it will become paused and then the maintenance can trigger.
108
+ # state_machine.pausing_state, # Not neccessary since it will become paused and then the maintenance can trigger.
109
+ state_machine.return_home_paused_state,
110
+ state_machine.returning_home_state,
111
+ # state_machine.stopping_return_home_state, # Not neccessary since it will become monitor and then the maintenance can trigger.
112
+ # state_machine.stopping_state, # Not neccessary since it will become await next mission and then the maintenance can trigger.
113
+ ],
114
+ "dest": state_machine.stopping_due_to_maintenance_state,
115
+ },
116
+ {
117
+ "trigger": "stop_return_home",
118
+ "source": [
119
+ state_machine.returning_home_state,
120
+ ],
121
+ "dest": state_machine.stopping_return_home_state,
122
+ },
123
+ {
124
+ "trigger": "stop_return_home",
125
+ "source": [
126
+ state_machine.return_home_paused_state,
127
+ ],
128
+ "dest": state_machine.stopping_paused_return_home_state,
129
+ },
130
+ {
131
+ "trigger": "mission_stopped",
132
+ "source": [
133
+ state_machine.stopping_state,
134
+ state_machine.stopping_paused_mission_state,
135
+ ],
136
+ "dest": state_machine.await_next_mission_state,
137
+ },
138
+ {
139
+ "trigger": "mission_stopped",
140
+ "source": state_machine.stopping_go_to_lockdown_state,
141
+ "dest": state_machine.going_to_lockdown_state,
142
+ },
143
+ {
144
+ "trigger": "mission_stopped",
145
+ "source": state_machine.stopping_due_to_maintenance_state,
146
+ "dest": state_machine.maintenance_state,
147
+ },
148
+ {
149
+ "trigger": "mission_stopping_failed",
150
+ "source": [
151
+ state_machine.stopping_go_to_lockdown_state,
152
+ state_machine.stopping_go_to_recharge_state,
153
+ state_machine.stopping_state,
154
+ ],
155
+ "dest": state_machine.monitor_state,
156
+ },
157
+ {
158
+ "trigger": "mission_stopping_failed",
159
+ "source": state_machine.stopping_paused_mission_state,
160
+ "dest": state_machine.paused_state,
161
+ },
162
+ {
163
+ "trigger": "mission_stopping_failed",
164
+ "source": state_machine.stopping_due_to_maintenance_state,
165
+ "dest": state_machine.unknown_status_state, # We do not know if we need to go to monitor or return_home state
166
+ },
167
+ {
168
+ "trigger": "return_home_mission_stopping_failed",
169
+ "source": state_machine.stopping_return_home_state,
170
+ "dest": state_machine.returning_home_state,
171
+ },
172
+ {
173
+ "trigger": "return_home_mission_stopping_failed",
174
+ "source": state_machine.stopping_paused_return_home_state,
175
+ "dest": state_machine.return_home_paused_state,
176
+ },
177
+ {
178
+ "trigger": "start_mission_monitoring",
179
+ "source": [
180
+ state_machine.await_next_mission_state,
181
+ state_machine.home_state,
182
+ state_machine.stopping_return_home_state,
183
+ state_machine.stopping_paused_return_home_state,
184
+ ],
185
+ "dest": state_machine.monitor_state,
186
+ },
187
+ {
188
+ "trigger": "mission_failed_to_start",
189
+ "source": state_machine.monitor_state,
190
+ "dest": state_machine.await_next_mission_state,
191
+ },
192
+ {
193
+ "trigger": "mission_finished",
194
+ "source": state_machine.monitor_state,
195
+ "dest": state_machine.await_next_mission_state,
196
+ },
197
+ {
198
+ "trigger": "set_maintenance_mode",
199
+ "source": [
200
+ state_machine.await_next_mission_state,
201
+ state_machine.blocked_protective_stopping_state,
202
+ state_machine.home_state,
203
+ state_machine.intervention_needed_state,
204
+ state_machine.offline_state,
205
+ state_machine.recharging_state,
206
+ state_machine.unknown_status_state,
207
+ ],
208
+ "dest": state_machine.maintenance_state,
209
+ },
210
+ {
211
+ "trigger": "goto_home",
212
+ "source": [
213
+ state_machine.maintenance_state,
214
+ ],
215
+ "dest": state_machine.home_state,
216
+ },
217
+ {
218
+ "trigger": "goto_intervention_needed",
219
+ "source": [
220
+ state_machine.maintenance_state,
221
+ ],
222
+ "dest": state_machine.intervention_needed_state,
223
+ },
224
+ ]
225
+ return mission_transitions
@@ -0,0 +1,108 @@
1
+ from typing import TYPE_CHECKING, List
2
+
3
+ if TYPE_CHECKING:
4
+ from isar.state_machine.state_machine import StateMachine
5
+
6
+
7
+ def get_return_home_transitions(state_machine: "StateMachine") -> List[dict]:
8
+ return_home_transitions: List[dict] = [
9
+ {
10
+ "trigger": "start_return_home_monitoring",
11
+ "source": [
12
+ state_machine.await_next_mission_state,
13
+ state_machine.home_state,
14
+ state_machine.intervention_needed_state,
15
+ state_machine.monitor_state,
16
+ state_machine.stopping_state,
17
+ state_machine.stopping_return_home_state,
18
+ state_machine.stopping_paused_mission_state,
19
+ state_machine.stopping_paused_return_home_state,
20
+ ],
21
+ "dest": state_machine.returning_home_state,
22
+ },
23
+ {
24
+ "trigger": "returned_home",
25
+ "source": state_machine.returning_home_state,
26
+ "dest": state_machine.home_state,
27
+ },
28
+ {
29
+ "trigger": "starting_recharging",
30
+ "source": [
31
+ state_machine.lockdown_state,
32
+ state_machine.home_state,
33
+ state_machine.going_to_recharging_state,
34
+ ],
35
+ "dest": state_machine.recharging_state,
36
+ },
37
+ {
38
+ "trigger": "return_home_failed",
39
+ "source": [
40
+ state_machine.returning_home_state,
41
+ state_machine.going_to_recharging_state,
42
+ ],
43
+ "dest": state_machine.intervention_needed_state,
44
+ },
45
+ {
46
+ "trigger": "release_intervention_needed",
47
+ "source": state_machine.intervention_needed_state,
48
+ "dest": state_machine.unknown_status_state,
49
+ },
50
+ {
51
+ "trigger": "start_lockdown_mission_monitoring",
52
+ "source": [
53
+ state_machine.stopping_go_to_lockdown_state,
54
+ state_machine.await_next_mission_state,
55
+ ],
56
+ "dest": state_machine.going_to_lockdown_state,
57
+ },
58
+ {
59
+ "trigger": "start_recharging_mission_monitoring",
60
+ "source": [
61
+ state_machine.stopping_go_to_recharge_state,
62
+ state_machine.await_next_mission_state,
63
+ ],
64
+ "dest": state_machine.going_to_recharging_state,
65
+ },
66
+ {
67
+ "trigger": "go_to_lockdown",
68
+ "source": [
69
+ state_machine.returning_home_state,
70
+ state_machine.going_to_recharging_state,
71
+ ],
72
+ "dest": state_machine.going_to_lockdown_state,
73
+ },
74
+ {
75
+ "trigger": "go_to_recharging",
76
+ "source": [
77
+ state_machine.returning_home_state,
78
+ state_machine.return_home_paused_state,
79
+ state_machine.home_state,
80
+ ],
81
+ "dest": state_machine.going_to_recharging_state,
82
+ },
83
+ {
84
+ "trigger": "reached_lockdown",
85
+ "source": [
86
+ state_machine.home_state,
87
+ state_machine.going_to_lockdown_state,
88
+ state_machine.recharging_state,
89
+ ],
90
+ "dest": state_machine.lockdown_state,
91
+ },
92
+ {
93
+ "trigger": "lockdown_mission_failed",
94
+ "source": state_machine.going_to_lockdown_state,
95
+ "dest": state_machine.intervention_needed_state,
96
+ },
97
+ {
98
+ "trigger": "release_from_lockdown",
99
+ "source": state_machine.lockdown_state,
100
+ "dest": state_machine.home_state,
101
+ },
102
+ {
103
+ "trigger": "go_to_home",
104
+ "source": state_machine.intervention_needed_state,
105
+ "dest": state_machine.home_state,
106
+ },
107
+ ]
108
+ return return_home_transitions
@@ -0,0 +1,87 @@
1
+ from typing import TYPE_CHECKING, List
2
+
3
+ if TYPE_CHECKING:
4
+ from isar.state_machine.state_machine import StateMachine
5
+
6
+
7
+ def get_robot_status_transitions(state_machine: "StateMachine") -> List[dict]:
8
+ robot_status_transitions: List[dict] = [
9
+ {
10
+ "trigger": "initial_transition",
11
+ "source": state_machine.unknown_status_state,
12
+ "dest": state_machine.unknown_status_state,
13
+ },
14
+ {
15
+ "trigger": "initial_transition",
16
+ "source": state_machine.maintenance_state,
17
+ "dest": state_machine.maintenance_state,
18
+ },
19
+ {
20
+ "trigger": "robot_status_available",
21
+ "source": [
22
+ state_machine.unknown_status_state,
23
+ ],
24
+ "dest": state_machine.await_next_mission_state,
25
+ },
26
+ {
27
+ "trigger": "robot_status_available",
28
+ "source": [
29
+ state_machine.offline_state,
30
+ state_machine.blocked_protective_stopping_state,
31
+ state_machine.home_state,
32
+ ],
33
+ "dest": state_machine.intervention_needed_state,
34
+ },
35
+ {
36
+ "trigger": "robot_status_home",
37
+ "source": [
38
+ state_machine.home_state,
39
+ state_machine.blocked_protective_stopping_state,
40
+ state_machine.offline_state,
41
+ state_machine.unknown_status_state,
42
+ ],
43
+ "dest": state_machine.home_state,
44
+ },
45
+ {
46
+ "trigger": "robot_status_blocked_protective_stop",
47
+ "source": [
48
+ state_machine.home_state,
49
+ state_machine.offline_state,
50
+ state_machine.unknown_status_state,
51
+ ],
52
+ "dest": state_machine.blocked_protective_stopping_state,
53
+ },
54
+ {
55
+ "trigger": "robot_status_offline",
56
+ "source": [
57
+ state_machine.home_state,
58
+ state_machine.blocked_protective_stopping_state,
59
+ state_machine.unknown_status_state,
60
+ state_machine.recharging_state,
61
+ ],
62
+ "dest": state_machine.offline_state,
63
+ },
64
+ {
65
+ "trigger": "robot_status_unknown",
66
+ "source": [
67
+ state_machine.home_state,
68
+ state_machine.blocked_protective_stopping_state,
69
+ state_machine.offline_state,
70
+ state_machine.unknown_status_state,
71
+ ],
72
+ "dest": state_machine.unknown_status_state,
73
+ },
74
+ {
75
+ "trigger": "robot_status_busy",
76
+ "source": [
77
+ state_machine.unknown_status_state,
78
+ ],
79
+ "dest": state_machine.stopping_state,
80
+ },
81
+ {
82
+ "trigger": "robot_recharged",
83
+ "source": state_machine.recharging_state,
84
+ "dest": state_machine.home_state,
85
+ },
86
+ ]
87
+ return robot_status_transitions
@@ -0,0 +1,138 @@
1
+ from typing import TYPE_CHECKING, Callable, Optional
2
+
3
+ from isar.apis.models.models import ControlMissionResponse, MissionStartResponse
4
+ from isar.models.events import Event
5
+ from robot_interface.models.exceptions.robot_exceptions import ErrorMessage
6
+ from robot_interface.models.mission.mission import Mission
7
+
8
+ if TYPE_CHECKING:
9
+ from isar.state_machine.state_machine import StateMachine
10
+
11
+
12
+ def start_mission_event_handler(
13
+ state_machine: "StateMachine",
14
+ event: Event[Mission],
15
+ response: Event[MissionStartResponse],
16
+ ) -> Optional[Callable]:
17
+ mission: Optional[Mission] = event.consume_event()
18
+ if not mission:
19
+ return None
20
+
21
+ if not state_machine.battery_level_is_above_mission_start_threshold():
22
+ response.trigger_event(
23
+ MissionStartResponse(
24
+ mission_id=mission.id,
25
+ mission_started=False,
26
+ mission_not_started_reason="Robot battery too low",
27
+ )
28
+ )
29
+ return None
30
+ state_machine.start_mission(mission=mission)
31
+ response.trigger_event(MissionStartResponse(mission_started=True))
32
+ return state_machine.start_mission_monitoring # type: ignore
33
+
34
+
35
+ def return_home_event_handler(
36
+ state_machine: "StateMachine", event: Event[bool]
37
+ ) -> Optional[Callable]:
38
+ if not event.consume_event():
39
+ return None
40
+
41
+ state_machine.events.api_requests.return_home.response.trigger_event(True)
42
+ state_machine.start_return_home_mission()
43
+ return state_machine.start_return_home_monitoring # type: ignore
44
+
45
+
46
+ def stop_mission_event_handler(
47
+ state_machine: "StateMachine", event: Event[str]
48
+ ) -> Optional[Callable]:
49
+ mission_id: str = event.consume_event()
50
+ if mission_id is None:
51
+ return None
52
+
53
+ if state_machine.shared_state.mission_id.check() == mission_id or mission_id == "":
54
+ state_machine.events.api_requests.stop_mission.response.trigger_event(
55
+ ControlMissionResponse(success=True)
56
+ )
57
+ state_machine.events.state_machine_events.stop_mission.trigger_event(True)
58
+ return state_machine.stop # type: ignore
59
+ else:
60
+ state_machine.events.api_requests.stop_mission.response.trigger_event(
61
+ ControlMissionResponse(success=False, failure_reason="Mission not found")
62
+ )
63
+ return None
64
+
65
+
66
+ def mission_started_event_handler(
67
+ state_machine: "StateMachine",
68
+ event: Event[bool],
69
+ ) -> Optional[Callable]:
70
+ if not event.consume_event():
71
+ return None
72
+
73
+ state_machine.logger.info("Received confirmation that mission has started")
74
+ return None
75
+
76
+
77
+ def failed_stop_event_handler(
78
+ state_machine: "StateMachine",
79
+ event: Event[ErrorMessage],
80
+ ) -> Optional[Callable]:
81
+ error_message: Optional[ErrorMessage] = event.consume_event()
82
+ if error_message is None:
83
+ return None
84
+
85
+ stopped_mission_response: ControlMissionResponse = ControlMissionResponse(
86
+ success=False, failure_reason="ISAR failed to stop mission"
87
+ )
88
+ state_machine.events.api_requests.stop_mission.response.trigger_event(
89
+ stopped_mission_response
90
+ )
91
+ return state_machine.mission_stopping_failed # type: ignore
92
+
93
+
94
+ def successful_stop_event_handler(
95
+ state_machine: "StateMachine", event: Event[bool]
96
+ ) -> Optional[Callable]:
97
+ if not event.consume_event():
98
+ return None
99
+
100
+ state_machine.events.api_requests.stop_mission.response.trigger_event(
101
+ ControlMissionResponse(success=True)
102
+ )
103
+ state_machine.print_transitions()
104
+ if not state_machine.battery_level_is_above_mission_start_threshold():
105
+ state_machine.start_return_home_mission()
106
+ return state_machine.start_return_home_monitoring # type: ignore
107
+ return state_machine.mission_stopped # type: ignore
108
+
109
+
110
+ def failed_stop_return_home_event_handler(
111
+ state_machine: "StateMachine", event: Event[ErrorMessage]
112
+ ) -> Optional[Callable]:
113
+ error_message: Optional[ErrorMessage] = event.consume_event()
114
+ if error_message is None:
115
+ return None
116
+
117
+ state_machine.logger.warning(
118
+ f"Failed to stop return home mission {error_message.error_description}"
119
+ )
120
+ return state_machine.return_home_mission_stopping_failed # type: ignore
121
+
122
+
123
+ def successful_stop_return_home_event_handler(
124
+ state_machine: "StateMachine", event: Event[bool], mission: Optional[Mission]
125
+ ) -> Optional[Callable]:
126
+ if not event.consume_event():
127
+ return None
128
+
129
+ if mission:
130
+ state_machine.start_mission(mission=mission)
131
+ state_machine.events.api_requests.start_mission.response.trigger_event(
132
+ MissionStartResponse(mission_started=True)
133
+ )
134
+ return state_machine.start_mission_monitoring # type: ignore
135
+
136
+ state_machine.logger.error("Stopped return home without a new mission to start")
137
+ state_machine.start_return_home_mission()
138
+ return state_machine.start_return_home_monitoring # type: ignore