isar 1.15.0__py3-none-any.whl → 1.34.9__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.
- isar/__init__.py +2 -5
- isar/apis/api.py +159 -66
- isar/apis/models/__init__.py +0 -1
- isar/apis/models/models.py +22 -12
- isar/apis/models/start_mission_definition.py +128 -123
- isar/apis/robot_control/robot_controller.py +41 -0
- isar/apis/schedule/scheduling_controller.py +135 -121
- isar/apis/security/authentication.py +5 -5
- isar/config/certs/ca-cert.pem +32 -32
- isar/config/keyvault/keyvault_service.py +1 -2
- isar/config/log.py +47 -39
- isar/config/logging.conf +16 -31
- isar/config/open_telemetry.py +102 -0
- isar/config/predefined_mission_definition/default_exr.json +49 -0
- isar/config/predefined_mission_definition/default_mission.json +1 -5
- isar/config/predefined_mission_definition/default_turtlebot.json +4 -11
- isar/config/predefined_missions/default.json +67 -87
- isar/config/predefined_missions/default_extra_capabilities.json +107 -0
- isar/config/settings.py +119 -142
- isar/eventhandlers/eventhandler.py +123 -0
- isar/mission_planner/local_planner.py +6 -20
- isar/mission_planner/mission_planner_interface.py +1 -1
- isar/models/events.py +184 -0
- isar/models/status.py +18 -0
- isar/modules.py +118 -205
- isar/robot/robot.py +377 -0
- isar/robot/robot_battery.py +60 -0
- isar/robot/robot_monitor_mission.py +357 -0
- isar/robot/robot_pause_mission.py +74 -0
- isar/robot/robot_resume_mission.py +67 -0
- isar/robot/robot_start_mission.py +66 -0
- isar/robot/robot_status.py +61 -0
- isar/robot/robot_stop_mission.py +68 -0
- isar/robot/robot_upload_inspection.py +75 -0
- isar/script.py +171 -0
- isar/services/service_connections/mqtt/mqtt_client.py +47 -11
- isar/services/service_connections/mqtt/robot_heartbeat_publisher.py +32 -0
- isar/services/service_connections/mqtt/robot_info_publisher.py +4 -3
- isar/services/service_connections/persistent_memory.py +69 -0
- isar/services/utilities/mqtt_utilities.py +93 -0
- isar/services/utilities/robot_utilities.py +20 -0
- isar/services/utilities/scheduling_utilities.py +393 -65
- isar/state_machine/state_machine.py +227 -486
- isar/state_machine/states/__init__.py +0 -7
- isar/state_machine/states/await_next_mission.py +114 -0
- isar/state_machine/states/blocked_protective_stop.py +60 -0
- isar/state_machine/states/going_to_lockdown.py +95 -0
- isar/state_machine/states/going_to_recharging.py +92 -0
- isar/state_machine/states/home.py +115 -0
- isar/state_machine/states/intervention_needed.py +77 -0
- isar/state_machine/states/lockdown.py +38 -0
- isar/state_machine/states/maintenance.py +36 -0
- isar/state_machine/states/monitor.py +137 -166
- isar/state_machine/states/offline.py +60 -0
- isar/state_machine/states/paused.py +92 -23
- isar/state_machine/states/pausing.py +48 -0
- isar/state_machine/states/pausing_return_home.py +48 -0
- isar/state_machine/states/recharging.py +80 -0
- isar/state_machine/states/resuming.py +57 -0
- isar/state_machine/states/resuming_return_home.py +64 -0
- isar/state_machine/states/return_home_paused.py +109 -0
- isar/state_machine/states/returning_home.py +217 -0
- isar/state_machine/states/stopping.py +61 -0
- isar/state_machine/states/stopping_due_to_maintenance.py +61 -0
- isar/state_machine/states/stopping_go_to_lockdown.py +60 -0
- isar/state_machine/states/stopping_go_to_recharge.py +51 -0
- isar/state_machine/states/stopping_return_home.py +77 -0
- isar/state_machine/states/unknown_status.py +72 -0
- isar/state_machine/states_enum.py +22 -5
- isar/state_machine/transitions/mission.py +192 -0
- isar/state_machine/transitions/return_home.py +106 -0
- isar/state_machine/transitions/robot_status.py +80 -0
- isar/state_machine/utils/common_event_handlers.py +73 -0
- isar/storage/blob_storage.py +71 -45
- isar/storage/local_storage.py +28 -14
- isar/storage/storage_interface.py +28 -6
- isar/storage/uploader.py +184 -55
- isar/storage/utilities.py +35 -27
- isar-1.34.9.dist-info/METADATA +496 -0
- isar-1.34.9.dist-info/RECORD +135 -0
- {isar-1.15.0.dist-info → isar-1.34.9.dist-info}/WHEEL +1 -1
- isar-1.34.9.dist-info/entry_points.txt +3 -0
- robot_interface/models/exceptions/__init__.py +0 -7
- robot_interface/models/exceptions/robot_exceptions.py +274 -4
- robot_interface/models/initialize/__init__.py +0 -1
- robot_interface/models/inspection/__init__.py +0 -13
- robot_interface/models/inspection/inspection.py +43 -34
- robot_interface/models/mission/mission.py +18 -14
- robot_interface/models/mission/status.py +20 -25
- robot_interface/models/mission/task.py +156 -92
- robot_interface/models/robots/battery_state.py +6 -0
- robot_interface/models/robots/media.py +13 -0
- robot_interface/models/robots/robot_model.py +7 -7
- robot_interface/robot_interface.py +135 -66
- robot_interface/telemetry/mqtt_client.py +84 -12
- robot_interface/telemetry/payloads.py +111 -12
- robot_interface/utilities/json_service.py +7 -1
- isar/config/predefined_missions/default_turtlebot.json +0 -110
- isar/config/predefined_poses/__init__.py +0 -0
- isar/config/predefined_poses/predefined_poses.py +0 -616
- isar/config/settings.env +0 -26
- isar/mission_planner/sequential_task_selector.py +0 -23
- isar/mission_planner/task_selector_interface.py +0 -31
- isar/models/communication/__init__.py +0 -0
- isar/models/communication/message.py +0 -12
- isar/models/communication/queues/__init__.py +0 -4
- isar/models/communication/queues/queue_io.py +0 -12
- isar/models/communication/queues/queue_timeout_error.py +0 -2
- isar/models/communication/queues/queues.py +0 -19
- isar/models/communication/queues/status_queue.py +0 -20
- isar/models/mission_metadata/__init__.py +0 -0
- isar/services/readers/__init__.py +0 -0
- isar/services/readers/base_reader.py +0 -37
- isar/services/service_connections/mqtt/robot_status_publisher.py +0 -93
- isar/services/service_connections/stid/__init__.py +0 -0
- isar/services/service_connections/stid/stid_service.py +0 -45
- isar/services/utilities/queue_utilities.py +0 -39
- isar/state_machine/states/idle.py +0 -40
- isar/state_machine/states/initialize.py +0 -60
- isar/state_machine/states/initiate.py +0 -129
- isar/state_machine/states/off.py +0 -18
- isar/state_machine/states/stop.py +0 -78
- isar/storage/slimm_storage.py +0 -181
- isar-1.15.0.dist-info/METADATA +0 -417
- isar-1.15.0.dist-info/RECORD +0 -113
- robot_interface/models/initialize/initialize_params.py +0 -9
- robot_interface/models/mission/step.py +0 -211
- {isar-1.15.0.dist-info → isar-1.34.9.dist-info/licenses}/LICENSE +0 -0
- {isar-1.15.0.dist-info → isar-1.34.9.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Callable, List, Optional
|
|
2
|
+
|
|
3
|
+
from isar.apis.models.models import LockdownResponse, MaintenanceResponse
|
|
4
|
+
from isar.config.settings import settings
|
|
5
|
+
from isar.eventhandlers.eventhandler import (
|
|
6
|
+
EventHandlerBase,
|
|
7
|
+
EventHandlerMapping,
|
|
8
|
+
TimeoutHandlerMapping,
|
|
9
|
+
)
|
|
10
|
+
from isar.models.events import Event
|
|
11
|
+
from isar.state_machine.utils.common_event_handlers import (
|
|
12
|
+
return_home_event_handler,
|
|
13
|
+
start_mission_event_handler,
|
|
14
|
+
stop_mission_event_handler,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from isar.state_machine.state_machine import StateMachine
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class AwaitNextMission(EventHandlerBase):
|
|
22
|
+
|
|
23
|
+
def __init__(self, state_machine: "StateMachine"):
|
|
24
|
+
events = state_machine.events
|
|
25
|
+
shared_state = state_machine.shared_state
|
|
26
|
+
|
|
27
|
+
def _send_to_lockdown_event_handler(
|
|
28
|
+
event: Event[bool],
|
|
29
|
+
) -> Optional[Callable]:
|
|
30
|
+
should_lockdown: bool = event.consume_event()
|
|
31
|
+
if not should_lockdown:
|
|
32
|
+
return None
|
|
33
|
+
|
|
34
|
+
events.api_requests.send_to_lockdown.response.trigger_event(
|
|
35
|
+
LockdownResponse(lockdown_started=True)
|
|
36
|
+
)
|
|
37
|
+
state_machine.start_return_home_mission()
|
|
38
|
+
return state_machine.start_lockdown_mission_monitoring # type: ignore
|
|
39
|
+
|
|
40
|
+
def _robot_battery_level_updated_handler(
|
|
41
|
+
event: Event[float],
|
|
42
|
+
) -> Optional[Callable]:
|
|
43
|
+
battery_level: float = event.check()
|
|
44
|
+
if (
|
|
45
|
+
battery_level is None
|
|
46
|
+
or battery_level >= settings.ROBOT_MISSION_BATTERY_START_THRESHOLD
|
|
47
|
+
):
|
|
48
|
+
return None
|
|
49
|
+
|
|
50
|
+
state_machine.start_return_home_mission()
|
|
51
|
+
return state_machine.start_recharging_mission_monitoring # type: ignore
|
|
52
|
+
|
|
53
|
+
def _set_maintenance_mode_event_handler(event: Event[bool]):
|
|
54
|
+
should_set_maintenande_mode: bool = event.consume_event()
|
|
55
|
+
if should_set_maintenande_mode:
|
|
56
|
+
events.api_requests.set_maintenance_mode.response.trigger_event(
|
|
57
|
+
MaintenanceResponse(is_maintenance_mode=True)
|
|
58
|
+
)
|
|
59
|
+
return state_machine.set_maintenance_mode # type: ignore
|
|
60
|
+
return None
|
|
61
|
+
|
|
62
|
+
def _start_return_home():
|
|
63
|
+
state_machine.start_return_home_mission()
|
|
64
|
+
return state_machine.start_return_home_monitoring # type: ignore
|
|
65
|
+
|
|
66
|
+
event_handlers: List[EventHandlerMapping] = [
|
|
67
|
+
EventHandlerMapping(
|
|
68
|
+
name="start_mission_event",
|
|
69
|
+
event=events.api_requests.start_mission.request,
|
|
70
|
+
handler=lambda event: start_mission_event_handler(
|
|
71
|
+
state_machine, event, events.api_requests.start_mission.response
|
|
72
|
+
),
|
|
73
|
+
),
|
|
74
|
+
EventHandlerMapping(
|
|
75
|
+
name="return_home_event",
|
|
76
|
+
event=events.api_requests.return_home.request,
|
|
77
|
+
handler=lambda event: return_home_event_handler(state_machine, event),
|
|
78
|
+
),
|
|
79
|
+
EventHandlerMapping(
|
|
80
|
+
name="stop_mission_event",
|
|
81
|
+
event=events.api_requests.return_home.request,
|
|
82
|
+
handler=lambda event: stop_mission_event_handler(state_machine, event),
|
|
83
|
+
),
|
|
84
|
+
EventHandlerMapping(
|
|
85
|
+
name="send_to_lockdown_event",
|
|
86
|
+
event=events.api_requests.send_to_lockdown.request,
|
|
87
|
+
handler=_send_to_lockdown_event_handler,
|
|
88
|
+
),
|
|
89
|
+
EventHandlerMapping(
|
|
90
|
+
name="robot_battery_update_event",
|
|
91
|
+
event=shared_state.robot_battery_level,
|
|
92
|
+
handler=_robot_battery_level_updated_handler,
|
|
93
|
+
),
|
|
94
|
+
EventHandlerMapping(
|
|
95
|
+
name="set_maintenance_mode",
|
|
96
|
+
event=events.api_requests.set_maintenance_mode.request,
|
|
97
|
+
handler=_set_maintenance_mode_event_handler,
|
|
98
|
+
),
|
|
99
|
+
]
|
|
100
|
+
|
|
101
|
+
timers: List[TimeoutHandlerMapping] = [
|
|
102
|
+
TimeoutHandlerMapping(
|
|
103
|
+
name="should_return_home_timer",
|
|
104
|
+
timeout_in_seconds=settings.RETURN_HOME_DELAY,
|
|
105
|
+
handler=_start_return_home,
|
|
106
|
+
)
|
|
107
|
+
]
|
|
108
|
+
|
|
109
|
+
super().__init__(
|
|
110
|
+
state_name="await_next_mission",
|
|
111
|
+
state_machine=state_machine,
|
|
112
|
+
event_handler_mappings=event_handlers,
|
|
113
|
+
timers=timers,
|
|
114
|
+
)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Callable, List, Optional
|
|
2
|
+
|
|
3
|
+
from isar.apis.models.models import MaintenanceResponse
|
|
4
|
+
from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
|
|
5
|
+
from isar.models.events import Event
|
|
6
|
+
from robot_interface.models.mission.status import RobotStatus
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from isar.state_machine.state_machine import StateMachine
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class BlockedProtectiveStop(EventHandlerBase):
|
|
13
|
+
|
|
14
|
+
def __init__(self, state_machine: "StateMachine"):
|
|
15
|
+
events = state_machine.events
|
|
16
|
+
shared_state = state_machine.shared_state
|
|
17
|
+
|
|
18
|
+
def _set_maintenance_mode_event_handler(event: Event[bool]):
|
|
19
|
+
should_set_maintenande_mode: bool = event.consume_event()
|
|
20
|
+
if should_set_maintenande_mode:
|
|
21
|
+
events.api_requests.set_maintenance_mode.response.trigger_event(
|
|
22
|
+
MaintenanceResponse(is_maintenance_mode=True)
|
|
23
|
+
)
|
|
24
|
+
return state_machine.set_maintenance_mode # type: ignore
|
|
25
|
+
return None
|
|
26
|
+
|
|
27
|
+
def _robot_status_event_handler(
|
|
28
|
+
status_changed_event: Event[bool],
|
|
29
|
+
) -> Optional[Callable]:
|
|
30
|
+
has_changed = status_changed_event.consume_event()
|
|
31
|
+
if not has_changed:
|
|
32
|
+
return None
|
|
33
|
+
robot_status: Optional[RobotStatus] = shared_state.robot_status.check()
|
|
34
|
+
if robot_status == RobotStatus.BlockedProtectiveStop:
|
|
35
|
+
return None
|
|
36
|
+
elif robot_status == RobotStatus.Home:
|
|
37
|
+
return state_machine.robot_status_home # type: ignore
|
|
38
|
+
elif robot_status == RobotStatus.Available:
|
|
39
|
+
return state_machine.robot_status_available # type: ignore
|
|
40
|
+
elif robot_status == RobotStatus.Offline:
|
|
41
|
+
return state_machine.robot_status_offline # type: ignore
|
|
42
|
+
return state_machine.robot_status_unknown # type: ignore
|
|
43
|
+
|
|
44
|
+
event_handlers: List[EventHandlerMapping] = [
|
|
45
|
+
EventHandlerMapping(
|
|
46
|
+
name="robot_status_event",
|
|
47
|
+
event=events.robot_service_events.robot_status_changed,
|
|
48
|
+
handler=_robot_status_event_handler,
|
|
49
|
+
),
|
|
50
|
+
EventHandlerMapping(
|
|
51
|
+
name="set_maintenance_mode",
|
|
52
|
+
event=events.api_requests.set_maintenance_mode.request,
|
|
53
|
+
handler=_set_maintenance_mode_event_handler,
|
|
54
|
+
),
|
|
55
|
+
]
|
|
56
|
+
super().__init__(
|
|
57
|
+
state_name="blocked_protective_stop",
|
|
58
|
+
state_machine=state_machine,
|
|
59
|
+
event_handler_mappings=event_handlers,
|
|
60
|
+
)
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Callable, List, Optional
|
|
2
|
+
|
|
3
|
+
from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
|
|
4
|
+
from isar.models.events import Event
|
|
5
|
+
from isar.state_machine.utils.common_event_handlers import mission_started_event_handler
|
|
6
|
+
from robot_interface.models.exceptions.robot_exceptions import ErrorMessage
|
|
7
|
+
from robot_interface.models.mission.status import MissionStatus
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from isar.state_machine.state_machine import StateMachine
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class GoingToLockdown(EventHandlerBase):
|
|
14
|
+
|
|
15
|
+
def __init__(self, state_machine: "StateMachine"):
|
|
16
|
+
events = state_machine.events
|
|
17
|
+
|
|
18
|
+
def _mission_failed_event_handler(
|
|
19
|
+
event: Event[Optional[ErrorMessage]],
|
|
20
|
+
) -> Optional[Callable]:
|
|
21
|
+
mission_failed: Optional[ErrorMessage] = event.consume_event()
|
|
22
|
+
if mission_failed is None:
|
|
23
|
+
return None
|
|
24
|
+
|
|
25
|
+
state_machine.logger.warning(
|
|
26
|
+
f"Failed to go to lockdown because: "
|
|
27
|
+
f"{mission_failed.error_description}"
|
|
28
|
+
)
|
|
29
|
+
state_machine.publish_intervention_needed(
|
|
30
|
+
error_message="Lockdown mission failed."
|
|
31
|
+
)
|
|
32
|
+
return state_machine.lockdown_mission_failed # type: ignore
|
|
33
|
+
|
|
34
|
+
def _mission_failed_to_resume_event_handler(
|
|
35
|
+
event: Event[Optional[ErrorMessage]],
|
|
36
|
+
) -> Optional[Callable]:
|
|
37
|
+
mission_failed_to_resume: Optional[ErrorMessage] = event.consume_event()
|
|
38
|
+
if mission_failed_to_resume is None:
|
|
39
|
+
return None
|
|
40
|
+
|
|
41
|
+
state_machine.logger.warning(
|
|
42
|
+
f"Failed to resume return to home mission and going to lockdown because: "
|
|
43
|
+
f"{mission_failed_to_resume.error_description or ''}"
|
|
44
|
+
)
|
|
45
|
+
return state_machine.lockdown_mission_failed # type: ignore
|
|
46
|
+
|
|
47
|
+
def _mission_status_event_handler(
|
|
48
|
+
event: Event[MissionStatus],
|
|
49
|
+
) -> Optional[Callable]:
|
|
50
|
+
mission_status: Optional[MissionStatus] = event.consume_event()
|
|
51
|
+
|
|
52
|
+
if mission_status and mission_status not in [
|
|
53
|
+
MissionStatus.InProgress,
|
|
54
|
+
MissionStatus.NotStarted,
|
|
55
|
+
MissionStatus.Paused,
|
|
56
|
+
]:
|
|
57
|
+
if mission_status != MissionStatus.Successful:
|
|
58
|
+
state_machine.publish_intervention_needed(
|
|
59
|
+
error_message="Lockdown mission failed."
|
|
60
|
+
)
|
|
61
|
+
return state_machine.lockdown_mission_failed # type: ignore
|
|
62
|
+
|
|
63
|
+
state_machine.print_transitions()
|
|
64
|
+
return state_machine.reached_lockdown # type: ignore
|
|
65
|
+
return None
|
|
66
|
+
|
|
67
|
+
event_handlers: List[EventHandlerMapping] = [
|
|
68
|
+
EventHandlerMapping(
|
|
69
|
+
name="mission_started_event",
|
|
70
|
+
event=events.robot_service_events.mission_started,
|
|
71
|
+
handler=lambda event: mission_started_event_handler(
|
|
72
|
+
state_machine, event
|
|
73
|
+
),
|
|
74
|
+
),
|
|
75
|
+
EventHandlerMapping(
|
|
76
|
+
name="mission_failed_event",
|
|
77
|
+
event=events.robot_service_events.mission_failed,
|
|
78
|
+
handler=_mission_failed_event_handler,
|
|
79
|
+
),
|
|
80
|
+
EventHandlerMapping(
|
|
81
|
+
name="mission_failed_to_resume",
|
|
82
|
+
event=events.robot_service_events.mission_failed_to_resume,
|
|
83
|
+
handler=_mission_failed_to_resume_event_handler,
|
|
84
|
+
),
|
|
85
|
+
EventHandlerMapping(
|
|
86
|
+
name="mission_status_event",
|
|
87
|
+
event=events.robot_service_events.mission_status_updated,
|
|
88
|
+
handler=_mission_status_event_handler,
|
|
89
|
+
),
|
|
90
|
+
]
|
|
91
|
+
super().__init__(
|
|
92
|
+
state_name="going_to_lockdown",
|
|
93
|
+
state_machine=state_machine,
|
|
94
|
+
event_handler_mappings=event_handlers,
|
|
95
|
+
)
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Callable, List, Optional
|
|
2
|
+
|
|
3
|
+
from isar.apis.models.models import LockdownResponse
|
|
4
|
+
from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
|
|
5
|
+
from isar.models.events import Event
|
|
6
|
+
from robot_interface.models.exceptions.robot_exceptions import ErrorMessage
|
|
7
|
+
from robot_interface.models.mission.status import MissionStatus
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from isar.state_machine.state_machine import StateMachine
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class GoingToRecharging(EventHandlerBase):
|
|
14
|
+
|
|
15
|
+
def __init__(self, state_machine: "StateMachine"):
|
|
16
|
+
events = state_machine.events
|
|
17
|
+
|
|
18
|
+
def _mission_failed_event_handler(
|
|
19
|
+
event: Event[Optional[ErrorMessage]],
|
|
20
|
+
) -> Optional[Callable]:
|
|
21
|
+
mission_failed: Optional[ErrorMessage] = event.consume_event()
|
|
22
|
+
if mission_failed is None:
|
|
23
|
+
return None
|
|
24
|
+
|
|
25
|
+
state_machine.logger.warning(
|
|
26
|
+
f"Failed to go to recharging because: "
|
|
27
|
+
f"{mission_failed.error_description}"
|
|
28
|
+
)
|
|
29
|
+
state_machine.publish_intervention_needed(
|
|
30
|
+
error_message="Return home to recharge failed."
|
|
31
|
+
)
|
|
32
|
+
state_machine.print_transitions()
|
|
33
|
+
return state_machine.return_home_failed # type: ignore
|
|
34
|
+
|
|
35
|
+
def _mission_status_event_handler(
|
|
36
|
+
event: Event[MissionStatus],
|
|
37
|
+
) -> Optional[Callable]:
|
|
38
|
+
mission_status: Optional[MissionStatus] = event.consume_event()
|
|
39
|
+
|
|
40
|
+
if not mission_status or mission_status in [
|
|
41
|
+
MissionStatus.InProgress,
|
|
42
|
+
MissionStatus.NotStarted,
|
|
43
|
+
MissionStatus.Paused,
|
|
44
|
+
]:
|
|
45
|
+
return None
|
|
46
|
+
|
|
47
|
+
if mission_status != MissionStatus.Successful:
|
|
48
|
+
state_machine.logger.warning(
|
|
49
|
+
"Failed to return home. Mission reported as failed."
|
|
50
|
+
)
|
|
51
|
+
state_machine.publish_intervention_needed(
|
|
52
|
+
error_message="Return home to recharge failed."
|
|
53
|
+
)
|
|
54
|
+
state_machine.print_transitions()
|
|
55
|
+
return state_machine.return_home_failed # type: ignore
|
|
56
|
+
|
|
57
|
+
return state_machine.starting_recharging # type: ignore
|
|
58
|
+
|
|
59
|
+
def _send_to_lockdown_event_handler(
|
|
60
|
+
event: Event[bool],
|
|
61
|
+
) -> Optional[Callable]:
|
|
62
|
+
should_lockdown: bool = event.consume_event()
|
|
63
|
+
if not should_lockdown:
|
|
64
|
+
return None
|
|
65
|
+
|
|
66
|
+
events.api_requests.send_to_lockdown.response.trigger_event(
|
|
67
|
+
LockdownResponse(lockdown_started=True)
|
|
68
|
+
)
|
|
69
|
+
return state_machine.go_to_lockdown # type: ignore
|
|
70
|
+
|
|
71
|
+
event_handlers: List[EventHandlerMapping] = [
|
|
72
|
+
EventHandlerMapping(
|
|
73
|
+
name="mission_failed_event",
|
|
74
|
+
event=events.robot_service_events.mission_failed,
|
|
75
|
+
handler=_mission_failed_event_handler,
|
|
76
|
+
),
|
|
77
|
+
EventHandlerMapping(
|
|
78
|
+
name="mission_status_event",
|
|
79
|
+
event=events.robot_service_events.mission_status_updated,
|
|
80
|
+
handler=_mission_status_event_handler,
|
|
81
|
+
),
|
|
82
|
+
EventHandlerMapping(
|
|
83
|
+
name="send_to_lockdown_event",
|
|
84
|
+
event=events.api_requests.send_to_lockdown.request,
|
|
85
|
+
handler=_send_to_lockdown_event_handler,
|
|
86
|
+
),
|
|
87
|
+
]
|
|
88
|
+
super().__init__(
|
|
89
|
+
state_name="going_to_recharging",
|
|
90
|
+
state_machine=state_machine,
|
|
91
|
+
event_handler_mappings=event_handlers,
|
|
92
|
+
)
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Callable, List, Optional
|
|
2
|
+
|
|
3
|
+
from isar.apis.models.models import LockdownResponse, MaintenanceResponse
|
|
4
|
+
from isar.config.settings import settings
|
|
5
|
+
from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
|
|
6
|
+
from isar.models.events import Event
|
|
7
|
+
from isar.state_machine.utils.common_event_handlers import (
|
|
8
|
+
return_home_event_handler,
|
|
9
|
+
start_mission_event_handler,
|
|
10
|
+
stop_mission_event_handler,
|
|
11
|
+
)
|
|
12
|
+
from robot_interface.models.mission.status import RobotStatus
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from isar.state_machine.state_machine import StateMachine
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Home(EventHandlerBase):
|
|
19
|
+
|
|
20
|
+
def __init__(self, state_machine: "StateMachine"):
|
|
21
|
+
events = state_machine.events
|
|
22
|
+
shared_state = state_machine.shared_state
|
|
23
|
+
|
|
24
|
+
def _send_to_lockdown_event_handler(event: Event[bool]):
|
|
25
|
+
should_send_robot_home: bool = event.consume_event()
|
|
26
|
+
if not should_send_robot_home:
|
|
27
|
+
return None
|
|
28
|
+
|
|
29
|
+
events.api_requests.send_to_lockdown.response.trigger_event(
|
|
30
|
+
LockdownResponse(lockdown_started=True)
|
|
31
|
+
)
|
|
32
|
+
return state_machine.reached_lockdown # type: ignore
|
|
33
|
+
|
|
34
|
+
def _set_maintenance_mode_event_handler(event: Event[bool]):
|
|
35
|
+
should_set_maintenande_mode: bool = event.consume_event()
|
|
36
|
+
if should_set_maintenande_mode:
|
|
37
|
+
events.api_requests.set_maintenance_mode.response.trigger_event(
|
|
38
|
+
MaintenanceResponse(is_maintenance_mode=True)
|
|
39
|
+
)
|
|
40
|
+
return state_machine.set_maintenance_mode # type: ignore
|
|
41
|
+
return None
|
|
42
|
+
|
|
43
|
+
def _robot_status_event_handler(
|
|
44
|
+
status_changed_event: Event[bool],
|
|
45
|
+
) -> Optional[Callable]:
|
|
46
|
+
has_changed = status_changed_event.consume_event()
|
|
47
|
+
if not has_changed:
|
|
48
|
+
return None
|
|
49
|
+
robot_status: Optional[RobotStatus] = shared_state.robot_status.check()
|
|
50
|
+
if robot_status == RobotStatus.Home:
|
|
51
|
+
return None
|
|
52
|
+
elif robot_status == RobotStatus.Available:
|
|
53
|
+
return state_machine.robot_status_available # type: ignore
|
|
54
|
+
elif robot_status == RobotStatus.Offline:
|
|
55
|
+
return state_machine.robot_status_offline # type: ignore
|
|
56
|
+
elif robot_status == RobotStatus.BlockedProtectiveStop:
|
|
57
|
+
return state_machine.robot_status_blocked_protective_stop # type: ignore
|
|
58
|
+
return state_machine.robot_status_unknown # type: ignore
|
|
59
|
+
|
|
60
|
+
def _robot_battery_level_updated_handler(
|
|
61
|
+
event: Event[float],
|
|
62
|
+
) -> Optional[Callable]:
|
|
63
|
+
battery_level: float = event.check()
|
|
64
|
+
if (
|
|
65
|
+
battery_level is None
|
|
66
|
+
or battery_level >= settings.ROBOT_MISSION_BATTERY_START_THRESHOLD
|
|
67
|
+
):
|
|
68
|
+
return None
|
|
69
|
+
|
|
70
|
+
return state_machine.starting_recharging # type: ignore
|
|
71
|
+
|
|
72
|
+
event_handlers: List[EventHandlerMapping] = [
|
|
73
|
+
EventHandlerMapping(
|
|
74
|
+
name="start_mission_event",
|
|
75
|
+
event=events.api_requests.start_mission.request,
|
|
76
|
+
handler=lambda event: start_mission_event_handler(
|
|
77
|
+
state_machine, event, events.api_requests.start_mission.response
|
|
78
|
+
),
|
|
79
|
+
),
|
|
80
|
+
EventHandlerMapping(
|
|
81
|
+
name="return_home_event",
|
|
82
|
+
event=events.api_requests.return_home.request,
|
|
83
|
+
handler=lambda event: return_home_event_handler(state_machine, event),
|
|
84
|
+
),
|
|
85
|
+
EventHandlerMapping(
|
|
86
|
+
name="stop_mission_event",
|
|
87
|
+
event=events.api_requests.return_home.request,
|
|
88
|
+
handler=lambda event: stop_mission_event_handler(state_machine, event),
|
|
89
|
+
),
|
|
90
|
+
EventHandlerMapping(
|
|
91
|
+
name="robot_status_event",
|
|
92
|
+
event=events.robot_service_events.robot_status_changed,
|
|
93
|
+
handler=_robot_status_event_handler,
|
|
94
|
+
),
|
|
95
|
+
EventHandlerMapping(
|
|
96
|
+
name="send_to_lockdown_event",
|
|
97
|
+
event=events.api_requests.send_to_lockdown.request,
|
|
98
|
+
handler=_send_to_lockdown_event_handler,
|
|
99
|
+
),
|
|
100
|
+
EventHandlerMapping(
|
|
101
|
+
name="robot_battery_update_event",
|
|
102
|
+
event=shared_state.robot_battery_level,
|
|
103
|
+
handler=_robot_battery_level_updated_handler,
|
|
104
|
+
),
|
|
105
|
+
EventHandlerMapping(
|
|
106
|
+
name="set_maintenance_mode",
|
|
107
|
+
event=events.api_requests.set_maintenance_mode.request,
|
|
108
|
+
handler=_set_maintenance_mode_event_handler,
|
|
109
|
+
),
|
|
110
|
+
]
|
|
111
|
+
super().__init__(
|
|
112
|
+
state_name="home",
|
|
113
|
+
state_machine=state_machine,
|
|
114
|
+
event_handler_mappings=event_handlers,
|
|
115
|
+
)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
from collections.abc import Callable
|
|
2
|
+
from typing import TYPE_CHECKING, List, Optional
|
|
3
|
+
|
|
4
|
+
from isar.apis.models.models import MaintenanceResponse
|
|
5
|
+
from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
|
|
6
|
+
from isar.models.events import Event
|
|
7
|
+
from isar.state_machine.utils.common_event_handlers import return_home_event_handler
|
|
8
|
+
from robot_interface.models.mission.status import RobotStatus
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from isar.state_machine.state_machine import StateMachine
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class InterventionNeeded(EventHandlerBase):
|
|
15
|
+
|
|
16
|
+
def __init__(self, state_machine: "StateMachine"):
|
|
17
|
+
events = state_machine.events
|
|
18
|
+
shared_state = state_machine.shared_state
|
|
19
|
+
|
|
20
|
+
def _set_maintenance_mode_event_handler(event: Event[bool]):
|
|
21
|
+
should_set_maintenande_mode: bool = event.consume_event()
|
|
22
|
+
if should_set_maintenande_mode:
|
|
23
|
+
events.api_requests.set_maintenance_mode.response.trigger_event(
|
|
24
|
+
MaintenanceResponse(is_maintenance_mode=True)
|
|
25
|
+
)
|
|
26
|
+
return state_machine.set_maintenance_mode # type: ignore
|
|
27
|
+
return None
|
|
28
|
+
|
|
29
|
+
def release_intervention_needed_handler(
|
|
30
|
+
event: Event[bool],
|
|
31
|
+
) -> Optional[Callable]:
|
|
32
|
+
if not event.consume_event():
|
|
33
|
+
return None
|
|
34
|
+
|
|
35
|
+
state_machine.events.api_requests.release_intervention_needed.response.trigger_event(
|
|
36
|
+
True
|
|
37
|
+
)
|
|
38
|
+
return state_machine.release_intervention_needed # type: ignore
|
|
39
|
+
|
|
40
|
+
def _robot_status_event_handler(
|
|
41
|
+
status_changed_event: Event[bool],
|
|
42
|
+
) -> Optional[Callable]:
|
|
43
|
+
has_changed = status_changed_event.consume_event()
|
|
44
|
+
if not has_changed:
|
|
45
|
+
return None
|
|
46
|
+
robot_status: Optional[RobotStatus] = shared_state.robot_status.check()
|
|
47
|
+
if robot_status == RobotStatus.Home:
|
|
48
|
+
return state_machine.go_to_home # type: ignore
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
event_handlers: List[EventHandlerMapping] = [
|
|
52
|
+
EventHandlerMapping(
|
|
53
|
+
name="return_home_event",
|
|
54
|
+
event=events.api_requests.return_home.request,
|
|
55
|
+
handler=lambda event: return_home_event_handler(state_machine, event),
|
|
56
|
+
),
|
|
57
|
+
EventHandlerMapping(
|
|
58
|
+
name="release_intervention_needed_event",
|
|
59
|
+
event=events.api_requests.release_intervention_needed.request,
|
|
60
|
+
handler=release_intervention_needed_handler,
|
|
61
|
+
),
|
|
62
|
+
EventHandlerMapping(
|
|
63
|
+
name="set_maintenance_mode",
|
|
64
|
+
event=events.api_requests.set_maintenance_mode.request,
|
|
65
|
+
handler=_set_maintenance_mode_event_handler,
|
|
66
|
+
),
|
|
67
|
+
EventHandlerMapping(
|
|
68
|
+
name="robot_status_event",
|
|
69
|
+
event=events.robot_service_events.robot_status_changed,
|
|
70
|
+
handler=_robot_status_event_handler,
|
|
71
|
+
),
|
|
72
|
+
]
|
|
73
|
+
super().__init__(
|
|
74
|
+
state_name="intervention_needed",
|
|
75
|
+
state_machine=state_machine,
|
|
76
|
+
event_handler_mappings=event_handlers,
|
|
77
|
+
)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, List
|
|
2
|
+
|
|
3
|
+
from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
|
|
4
|
+
from isar.models.events import Event
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from isar.state_machine.state_machine import StateMachine
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Lockdown(EventHandlerBase):
|
|
11
|
+
|
|
12
|
+
def __init__(self, state_machine: "StateMachine"):
|
|
13
|
+
events = state_machine.events
|
|
14
|
+
|
|
15
|
+
def _release_from_lockdown_handler(event: Event[bool]):
|
|
16
|
+
should_release_from_lockdown: bool = event.consume_event()
|
|
17
|
+
if not should_release_from_lockdown:
|
|
18
|
+
return None
|
|
19
|
+
|
|
20
|
+
events.api_requests.release_from_lockdown.response.trigger_event(True)
|
|
21
|
+
if state_machine.battery_level_is_above_mission_start_threshold():
|
|
22
|
+
return state_machine.release_from_lockdown # type: ignore
|
|
23
|
+
else:
|
|
24
|
+
return state_machine.starting_recharging # type: ignore
|
|
25
|
+
|
|
26
|
+
event_handlers: List[EventHandlerMapping] = [
|
|
27
|
+
EventHandlerMapping(
|
|
28
|
+
name="release_from_lockdown",
|
|
29
|
+
event=events.api_requests.release_from_lockdown.request,
|
|
30
|
+
handler=_release_from_lockdown_handler,
|
|
31
|
+
),
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
super().__init__(
|
|
35
|
+
state_name="lockdown",
|
|
36
|
+
state_machine=state_machine,
|
|
37
|
+
event_handler_mappings=event_handlers,
|
|
38
|
+
)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, List
|
|
2
|
+
|
|
3
|
+
from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
|
|
4
|
+
from isar.models.events import Event
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from isar.state_machine.state_machine import StateMachine
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Maintenance(EventHandlerBase):
|
|
11
|
+
|
|
12
|
+
def __init__(self, state_machine: "StateMachine"):
|
|
13
|
+
events = state_machine.events
|
|
14
|
+
|
|
15
|
+
def _release_from_maintenance_handler(event: Event[bool]):
|
|
16
|
+
should_release_from_maintenance: bool = event.consume_event()
|
|
17
|
+
if should_release_from_maintenance:
|
|
18
|
+
events.api_requests.release_from_maintenance_mode.response.trigger_event(
|
|
19
|
+
True
|
|
20
|
+
)
|
|
21
|
+
return state_machine.release_from_maintenance # type: ignore
|
|
22
|
+
return None
|
|
23
|
+
|
|
24
|
+
event_handlers: List[EventHandlerMapping] = [
|
|
25
|
+
EventHandlerMapping(
|
|
26
|
+
name="release_from_maintenance",
|
|
27
|
+
event=events.api_requests.release_from_maintenance_mode.request,
|
|
28
|
+
handler=_release_from_maintenance_handler,
|
|
29
|
+
),
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
super().__init__(
|
|
33
|
+
state_name="maintenance",
|
|
34
|
+
state_machine=state_machine,
|
|
35
|
+
event_handler_mappings=event_handlers,
|
|
36
|
+
)
|