isar 1.30.5__py3-none-any.whl → 1.31.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of isar might be problematic. Click here for more details.

Files changed (62) hide show
  1. isar/apis/api.py +7 -51
  2. isar/apis/models/models.py +1 -0
  3. isar/apis/models/start_mission_definition.py +4 -0
  4. isar/apis/robot_control/robot_controller.py +0 -2
  5. isar/apis/schedule/scheduling_controller.py +12 -4
  6. isar/config/log.py +8 -29
  7. isar/config/open_telemetry.py +62 -0
  8. isar/config/settings.py +12 -0
  9. isar/eventhandlers/eventhandler.py +93 -0
  10. isar/mission_planner/local_planner.py +0 -3
  11. isar/models/events.py +118 -0
  12. isar/modules.py +1 -1
  13. isar/robot/robot.py +16 -21
  14. isar/robot/robot_start_mission.py +8 -14
  15. isar/robot/robot_status.py +2 -3
  16. isar/robot/robot_stop_mission.py +3 -9
  17. isar/robot/robot_task_status.py +3 -7
  18. isar/script.py +4 -1
  19. isar/services/utilities/robot_utilities.py +0 -3
  20. isar/services/utilities/scheduling_utilities.py +45 -35
  21. isar/state_machine/state_machine.py +79 -11
  22. isar/state_machine/states/await_next_mission.py +46 -11
  23. isar/state_machine/states/blocked_protective_stop.py +24 -15
  24. isar/state_machine/states/home.py +40 -9
  25. isar/state_machine/states/monitor.py +83 -14
  26. isar/state_machine/states/offline.py +25 -13
  27. isar/state_machine/states/paused.py +24 -38
  28. isar/state_machine/states/returning_home.py +75 -14
  29. isar/state_machine/states/robot_standing_still.py +41 -11
  30. isar/state_machine/states/stopping.py +52 -67
  31. isar/state_machine/states/unknown_status.py +37 -64
  32. isar/state_machine/transitions/functions/pause.py +39 -10
  33. isar/state_machine/transitions/functions/resume.py +44 -15
  34. isar/state_machine/transitions/functions/robot_status.py +4 -5
  35. isar/state_machine/transitions/functions/stop.py +3 -12
  36. isar/state_machine/transitions/mission.py +12 -2
  37. isar/state_machine/transitions/return_home.py +1 -1
  38. isar/state_machine/utils/common_event_handlers.py +166 -0
  39. isar/storage/blob_storage.py +0 -2
  40. isar/storage/uploader.py +1 -4
  41. {isar-1.30.5.dist-info → isar-1.31.1.dist-info}/METADATA +7 -4
  42. {isar-1.30.5.dist-info → isar-1.31.1.dist-info}/RECORD +48 -58
  43. robot_interface/models/mission/task.py +0 -3
  44. robot_interface/robot_interface.py +1 -4
  45. isar/models/communication/__init__.py +0 -0
  46. isar/models/communication/message.py +0 -8
  47. isar/models/communication/queues/__init__.py +0 -0
  48. isar/models/communication/queues/events.py +0 -58
  49. isar/models/communication/queues/queue_io.py +0 -12
  50. isar/models/communication/queues/queue_timeout_error.py +0 -2
  51. isar/models/communication/queues/queue_utils.py +0 -38
  52. isar/models/communication/queues/status_queue.py +0 -22
  53. isar/models/mission_metadata/__init__.py +0 -0
  54. isar/services/service_connections/stid/__init__.py +0 -0
  55. isar/services/utilities/queue_utilities.py +0 -39
  56. isar/state_machine/generic_states/idle.py +0 -133
  57. isar/state_machine/generic_states/ongoing_mission.py +0 -294
  58. isar/state_machine/generic_states/robot_unavailable.py +0 -61
  59. {isar-1.30.5.dist-info → isar-1.31.1.dist-info}/WHEEL +0 -0
  60. {isar-1.30.5.dist-info → isar-1.31.1.dist-info}/entry_points.txt +0 -0
  61. {isar-1.30.5.dist-info → isar-1.31.1.dist-info}/licenses/LICENSE +0 -0
  62. {isar-1.30.5.dist-info → isar-1.31.1.dist-info}/top_level.txt +0 -0
@@ -1,24 +1,33 @@
1
- from typing import TYPE_CHECKING
1
+ from typing import TYPE_CHECKING, List
2
2
 
3
- from transitions import State
4
-
5
- from isar.state_machine.generic_states.robot_unavailable import (
6
- RobotUnavailable,
7
- RobotUnavailableStates,
8
- )
3
+ from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
4
+ from isar.models.events import Event
5
+ from robot_interface.models.mission.status import RobotStatus
9
6
 
10
7
  if TYPE_CHECKING:
11
8
  from isar.state_machine.state_machine import StateMachine
12
9
 
13
10
 
14
- class BlockedProtectiveStop(State, RobotUnavailable):
15
- def __init__(self, state_machine: "StateMachine") -> None:
16
- State.__init__(
17
- self, name="blocked_protective_stop", on_enter=self.start, on_exit=self.stop
18
- )
11
+ class BlockedProtectiveStop(EventHandlerBase):
12
+
13
+ def __init__(self, state_machine: "StateMachine"):
14
+ shared_state = state_machine.shared_state
15
+
16
+ def _robot_status_event_handler(event: Event[RobotStatus]):
17
+ robot_status: RobotStatus = event.check()
18
+ if robot_status != RobotStatus.BlockedProtectiveStop:
19
+ return state_machine.robot_status_changed # type: ignore
20
+ return None
19
21
 
20
- RobotUnavailable.__init__(
21
- self,
22
+ event_handlers: List[EventHandlerMapping] = [
23
+ EventHandlerMapping(
24
+ name="robot_status_event",
25
+ event=shared_state.robot_status,
26
+ handler=_robot_status_event_handler,
27
+ ),
28
+ ]
29
+ super().__init__(
30
+ state_name="blocked_protective_stop",
22
31
  state_machine=state_machine,
23
- state=RobotUnavailableStates.BlockedProtectiveStop,
32
+ event_handler_mappings=event_handlers,
24
33
  )
@@ -1,19 +1,50 @@
1
- from typing import TYPE_CHECKING
1
+ from typing import TYPE_CHECKING, List
2
2
 
3
- from transitions import State
3
+ from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
4
+ from isar.state_machine.utils.common_event_handlers import (
5
+ return_home_event_handler,
6
+ robot_status_event_handler,
7
+ start_mission_event_handler,
8
+ stop_mission_event_handler,
9
+ )
10
+ from robot_interface.models.mission.status import RobotStatus
4
11
 
5
12
  if TYPE_CHECKING:
6
13
  from isar.state_machine.state_machine import StateMachine
7
14
 
8
- from isar.state_machine.generic_states.idle import Idle, IdleStates
9
15
 
16
+ class Home(EventHandlerBase):
10
17
 
11
- class Home(State, Idle):
12
- def __init__(self, state_machine: "StateMachine") -> None:
13
- State.__init__(self, name="home", on_enter=self.start, on_exit=self.stop)
18
+ def __init__(self, state_machine: "StateMachine"):
19
+ events = state_machine.events
20
+ shared_state = state_machine.shared_state
14
21
 
15
- Idle.__init__(
16
- self,
22
+ event_handlers: List[EventHandlerMapping] = [
23
+ EventHandlerMapping(
24
+ name="start_mission_event",
25
+ event=events.api_requests.start_mission.input,
26
+ handler=lambda event: start_mission_event_handler(state_machine, event),
27
+ ),
28
+ EventHandlerMapping(
29
+ name="return_home_event",
30
+ event=events.api_requests.return_home.input,
31
+ handler=lambda event: return_home_event_handler(state_machine, event),
32
+ ),
33
+ EventHandlerMapping(
34
+ name="stop_mission_event",
35
+ event=events.api_requests.return_home.input,
36
+ handler=lambda event: stop_mission_event_handler(state_machine, event),
37
+ ),
38
+ EventHandlerMapping(
39
+ name="robot_status_event",
40
+ event=shared_state.robot_status,
41
+ handler=lambda event: robot_status_event_handler(
42
+ state_machine, RobotStatus.Home, event
43
+ ),
44
+ ),
45
+ ]
46
+ super().__init__(
47
+ state_name="home",
17
48
  state_machine=state_machine,
18
- state=IdleStates.Home,
49
+ event_handler_mappings=event_handlers,
19
50
  )
@@ -1,24 +1,93 @@
1
- from typing import TYPE_CHECKING
1
+ import logging
2
+ from copy import deepcopy
3
+ from typing import TYPE_CHECKING, Callable, List, Optional
2
4
 
3
- from dependency_injector.wiring import inject
4
- from transitions import State
5
-
6
- from isar.state_machine.generic_states.ongoing_mission import (
7
- OngoingMission,
8
- OngoingMissionStates,
5
+ from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
6
+ from isar.models.events import Event
7
+ from isar.services.utilities.threaded_request import ThreadedRequest
8
+ from isar.state_machine.utils.common_event_handlers import (
9
+ mission_failed_event_handler,
10
+ mission_started_event_handler,
11
+ stop_mission_event_handler,
12
+ task_status_event_handler,
13
+ task_status_failed_event_handler,
9
14
  )
15
+ from robot_interface.models.mission.status import TaskStatus
10
16
 
11
17
  if TYPE_CHECKING:
12
18
  from isar.state_machine.state_machine import StateMachine
13
19
 
14
20
 
15
- class Monitor(State, OngoingMission):
16
- @inject
17
- def __init__(self, state_machine: "StateMachine") -> None:
18
- State.__init__(self, name="monitor", on_enter=self.start, on_exit=self.stop)
21
+ class Monitor(EventHandlerBase):
22
+
23
+ def __init__(self, state_machine: "StateMachine"):
24
+ logger = logging.getLogger("state_machine")
25
+ events = state_machine.events
26
+
27
+ def _pause_mission_event_handler(event: Event[bool]) -> Optional[Callable]:
28
+ if event.consume_event():
29
+ return state_machine.pause # type: ignore
30
+ return None
31
+
32
+ def _handle_task_completed(task_status: TaskStatus):
33
+ if state_machine.should_upload_inspections():
34
+ get_inspection_thread = ThreadedRequest(
35
+ state_machine.queue_inspections_for_upload
36
+ )
37
+ get_inspection_thread.start_thread(
38
+ deepcopy(state_machine.current_mission),
39
+ deepcopy(state_machine.current_task),
40
+ logger,
41
+ name="State Machine Get Inspections",
42
+ )
43
+
44
+ state_machine.iterate_current_task()
45
+ if state_machine.current_task is None:
46
+ return state_machine.mission_finished # type: ignore
47
+ return None
19
48
 
20
- OngoingMission.__init__(
21
- self,
49
+ event_handlers: List[EventHandlerMapping] = [
50
+ EventHandlerMapping(
51
+ name="stop_mission_event",
52
+ event=events.api_requests.stop_mission.input,
53
+ handler=lambda event: stop_mission_event_handler(state_machine, event),
54
+ ),
55
+ EventHandlerMapping(
56
+ name="pause_mission_event",
57
+ event=events.api_requests.pause_mission.input,
58
+ handler=_pause_mission_event_handler,
59
+ ),
60
+ EventHandlerMapping(
61
+ name="mission_started_event",
62
+ event=events.robot_service_events.mission_started,
63
+ handler=lambda event: mission_started_event_handler(
64
+ state_machine, event
65
+ ),
66
+ ),
67
+ EventHandlerMapping(
68
+ name="mission_failed_event",
69
+ event=events.robot_service_events.mission_failed,
70
+ handler=lambda event: mission_failed_event_handler(
71
+ state_machine, event
72
+ ),
73
+ ),
74
+ EventHandlerMapping(
75
+ name="task_status_failed_event",
76
+ event=events.robot_service_events.task_status_failed,
77
+ handler=lambda event: task_status_failed_event_handler(
78
+ state_machine, _handle_task_completed, event
79
+ ),
80
+ ),
81
+ EventHandlerMapping(
82
+ name="task_status_event",
83
+ event=events.robot_service_events.task_status_updated,
84
+ handler=lambda event: task_status_event_handler(
85
+ state_machine, _handle_task_completed, event
86
+ ),
87
+ ),
88
+ ]
89
+ super().__init__(
90
+ state_name="monitor",
22
91
  state_machine=state_machine,
23
- state=OngoingMissionStates.Monitor,
92
+ event_handler_mappings=event_handlers,
24
93
  )
@@ -1,22 +1,34 @@
1
- from typing import TYPE_CHECKING
1
+ from typing import TYPE_CHECKING, List
2
2
 
3
- from transitions import State
4
-
5
- from isar.state_machine.generic_states.robot_unavailable import (
6
- RobotUnavailable,
7
- RobotUnavailableStates,
8
- )
3
+ from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
4
+ from isar.models.events import Event
5
+ from robot_interface.models.mission.status import RobotStatus
9
6
 
10
7
  if TYPE_CHECKING:
11
8
  from isar.state_machine.state_machine import StateMachine
12
9
 
13
10
 
14
- class Offline(State, RobotUnavailable):
15
- def __init__(self, state_machine: "StateMachine") -> None:
16
- State.__init__(self, name="offline", on_enter=self.start, on_exit=self.stop)
11
+ class Offline(EventHandlerBase):
12
+
13
+ def __init__(self, state_machine: "StateMachine"):
14
+
15
+ shared_state = state_machine.shared_state
16
+
17
+ def _robot_status_event_handler(event: Event[RobotStatus]):
18
+ robot_status: RobotStatus = event.check()
19
+ if robot_status != RobotStatus.Offline:
20
+ return state_machine.robot_status_changed # type: ignore
21
+ return None
17
22
 
18
- RobotUnavailable.__init__(
19
- self,
23
+ event_handlers: List[EventHandlerMapping] = [
24
+ EventHandlerMapping(
25
+ name="robot_status_event",
26
+ event=shared_state.robot_status,
27
+ handler=_robot_status_event_handler,
28
+ ),
29
+ ]
30
+ super().__init__(
31
+ state_name="offline",
20
32
  state_machine=state_machine,
21
- state=RobotUnavailableStates.Offline,
33
+ event_handler_mappings=event_handlers,
22
34
  )
@@ -1,44 +1,30 @@
1
- import logging
2
- import time
3
- from typing import TYPE_CHECKING, Callable
1
+ from typing import TYPE_CHECKING, List
4
2
 
5
- from transitions import State
6
-
7
- from isar.models.communication.queues.queue_utils import check_for_event
3
+ from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
8
4
 
9
5
  if TYPE_CHECKING:
10
6
  from isar.state_machine.state_machine import StateMachine
11
7
 
12
8
 
13
- class Paused(State):
14
- def __init__(self, state_machine: "StateMachine") -> None:
15
- super().__init__(name="paused", on_enter=self.start)
16
- self.state_machine: "StateMachine" = state_machine
17
- self.logger = logging.getLogger("state_machine")
18
- self.events = self.state_machine.events
19
- self.signal_state_machine_to_stop = state_machine.signal_state_machine_to_stop
20
-
21
- def start(self) -> None:
22
- self.state_machine.update_state()
23
- self._run()
24
-
25
- def _run(self) -> None:
26
- transition: Callable
27
- while True:
28
- if self.signal_state_machine_to_stop.is_set():
29
- self.logger.info(
30
- "Stopping state machine from %s state", self.__class__.__name__
31
- )
32
- break
33
-
34
- if check_for_event(self.events.api_requests.stop_mission.input):
35
- transition = self.state_machine.stop # type: ignore
36
- break
37
-
38
- if check_for_event(self.events.api_requests.resume_mission.input):
39
- transition = self.state_machine.resume # type: ignore
40
- break
41
-
42
- time.sleep(self.state_machine.sleep_time)
43
-
44
- transition()
9
+ class Paused(EventHandlerBase):
10
+
11
+ def __init__(self, state_machine: "StateMachine"):
12
+ events = state_machine.events
13
+
14
+ event_handlers: List[EventHandlerMapping] = [
15
+ EventHandlerMapping(
16
+ name="stop_mission_event",
17
+ event=events.api_requests.stop_mission.input,
18
+ handler=lambda event: state_machine.stop if event.consume_event() else None, # type: ignore
19
+ ),
20
+ EventHandlerMapping(
21
+ name="resume_mission_event",
22
+ event=events.api_requests.resume_mission.input,
23
+ handler=lambda event: state_machine.resume if event.consume_event() else None, # type: ignore
24
+ ),
25
+ ]
26
+ super().__init__(
27
+ state_name="paused",
28
+ state_machine=state_machine,
29
+ event_handler_mappings=event_handlers,
30
+ )
@@ -1,24 +1,85 @@
1
- from typing import TYPE_CHECKING
1
+ from typing import TYPE_CHECKING, Callable, List, Optional
2
2
 
3
- from transitions import State
4
-
5
- from isar.state_machine.generic_states.ongoing_mission import (
6
- OngoingMission,
7
- OngoingMissionStates,
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 (
6
+ mission_failed_event_handler,
7
+ mission_started_event_handler,
8
+ stop_mission_event_handler,
9
+ task_status_event_handler,
10
+ task_status_failed_event_handler,
8
11
  )
12
+ from robot_interface.models.exceptions.robot_exceptions import ErrorMessage, ErrorReason
13
+ from robot_interface.models.mission.mission import Mission
14
+ from robot_interface.models.mission.status import TaskStatus
9
15
 
10
16
  if TYPE_CHECKING:
11
17
  from isar.state_machine.state_machine import StateMachine
12
18
 
13
19
 
14
- class ReturningHome(State, OngoingMission):
15
- def __init__(self, state_machine: "StateMachine") -> None:
16
- State.__init__(
17
- self, name="returning_home", on_enter=self.start, on_exit=self.stop
18
- )
20
+ class ReturningHome(EventHandlerBase):
21
+
22
+ def __init__(self, state_machine: "StateMachine"):
23
+ events = state_machine.events
24
+
25
+ def _handle_task_completed(status: TaskStatus):
26
+ if status != TaskStatus.Successful:
27
+ state_machine.current_mission.error_message = ErrorMessage(
28
+ error_reason=ErrorReason.RobotActionException,
29
+ error_description="Return home failed.",
30
+ )
31
+ return state_machine.return_home_failed # type: ignore
32
+ return state_machine.returned_home # type: ignore
33
+
34
+ def _start_mission_event_handler(
35
+ event: Event[Mission],
36
+ ) -> Optional[Callable]:
37
+ if event.has_event():
38
+ return state_machine.stop # type: ignore
39
+ return None
19
40
 
20
- OngoingMission.__init__(
21
- self,
41
+ event_handlers: List[EventHandlerMapping] = [
42
+ EventHandlerMapping(
43
+ name="stop_mission_event",
44
+ event=events.api_requests.stop_mission.input,
45
+ handler=lambda event: stop_mission_event_handler(state_machine, event),
46
+ ),
47
+ EventHandlerMapping(
48
+ name="mission_started_event",
49
+ event=events.robot_service_events.mission_started,
50
+ handler=lambda event: mission_started_event_handler(
51
+ state_machine, event
52
+ ),
53
+ ),
54
+ EventHandlerMapping(
55
+ name="mission_failed_event",
56
+ event=events.robot_service_events.mission_failed,
57
+ handler=lambda event: mission_failed_event_handler(
58
+ state_machine, event
59
+ ),
60
+ ),
61
+ EventHandlerMapping(
62
+ name="start_mission_event",
63
+ event=events.api_requests.start_mission.input,
64
+ handler=_start_mission_event_handler,
65
+ ),
66
+ EventHandlerMapping(
67
+ name="task_status_failed_event",
68
+ event=events.robot_service_events.task_status_failed,
69
+ handler=lambda event: task_status_failed_event_handler(
70
+ state_machine, _handle_task_completed, event
71
+ ),
72
+ ),
73
+ EventHandlerMapping(
74
+ name="task_status_event",
75
+ event=events.robot_service_events.task_status_updated,
76
+ handler=lambda event: task_status_event_handler(
77
+ state_machine, _handle_task_completed, event
78
+ ),
79
+ ),
80
+ ]
81
+ super().__init__(
82
+ state_name="returning_home",
22
83
  state_machine=state_machine,
23
- state=OngoingMissionStates.ReturningHome,
84
+ event_handler_mappings=event_handlers,
24
85
  )
@@ -1,20 +1,50 @@
1
- from typing import TYPE_CHECKING
1
+ from typing import TYPE_CHECKING, List
2
2
 
3
- from transitions import State
3
+ from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
4
+ from isar.state_machine.utils.common_event_handlers import (
5
+ return_home_event_handler,
6
+ robot_status_event_handler,
7
+ start_mission_event_handler,
8
+ stop_mission_event_handler,
9
+ )
10
+ from robot_interface.models.mission.status import RobotStatus
4
11
 
5
12
  if TYPE_CHECKING:
6
13
  from isar.state_machine.state_machine import StateMachine
7
14
 
8
- from isar.state_machine.generic_states.idle import Idle, IdleStates
9
15
 
16
+ class RobotStandingStill(EventHandlerBase):
10
17
 
11
- class RobotStandingStill(State, Idle):
12
- def __init__(self, state_machine: "StateMachine") -> None:
13
- State.__init__(
14
- self, name="robot_standing_still", on_enter=self.start, on_exit=self.stop
15
- )
16
- Idle.__init__(
17
- self,
18
+ def __init__(self, state_machine: "StateMachine"):
19
+ events = state_machine.events
20
+ shared_state = state_machine.shared_state
21
+
22
+ event_handlers: List[EventHandlerMapping] = [
23
+ EventHandlerMapping(
24
+ name="start_mission_event",
25
+ event=events.api_requests.start_mission.input,
26
+ handler=lambda event: start_mission_event_handler(state_machine, event),
27
+ ),
28
+ EventHandlerMapping(
29
+ name="return_home_event",
30
+ event=events.api_requests.return_home.input,
31
+ handler=lambda event: return_home_event_handler(state_machine, event),
32
+ ),
33
+ EventHandlerMapping(
34
+ name="stop_mission_event",
35
+ event=events.api_requests.return_home.input,
36
+ handler=lambda event: stop_mission_event_handler(state_machine, event),
37
+ ),
38
+ EventHandlerMapping(
39
+ name="robot_status_event",
40
+ event=shared_state.robot_status,
41
+ handler=lambda event: robot_status_event_handler(
42
+ state_machine, RobotStatus.Available, event
43
+ ),
44
+ ),
45
+ ]
46
+ super().__init__(
47
+ state_name="robot_standing_still",
18
48
  state_machine=state_machine,
19
- state=IdleStates.RobotStandingStill,
49
+ event_handler_mappings=event_handlers,
20
50
  )
@@ -1,75 +1,60 @@
1
1
  import logging
2
- import time
3
- from queue import Queue
4
- from typing import TYPE_CHECKING, Optional
2
+ from typing import TYPE_CHECKING, Callable, List, Optional
5
3
 
6
- from transitions import State
7
-
8
- from isar.models.communication.queues.queue_utils import check_for_event
4
+ from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
5
+ from isar.models.events import Event
9
6
  from robot_interface.models.exceptions.robot_exceptions import ErrorMessage
10
7
 
11
8
  if TYPE_CHECKING:
12
9
  from isar.state_machine.state_machine import StateMachine
13
10
 
14
11
 
15
- class Stopping(State):
16
- def __init__(self, state_machine: "StateMachine") -> None:
17
- super().__init__(name="stopping", on_enter=self.start, on_exit=self.stop)
18
- self.state_machine: "StateMachine" = state_machine
19
- self.logger = logging.getLogger("state_machine")
20
- self.events = self.state_machine.events
21
- self._count_number_retries: int = 0
22
- self.signal_state_machine_to_stop = state_machine.signal_state_machine_to_stop
23
- self.stopping_return_home_mission: bool = False
24
-
25
- def start(self) -> None:
26
- self.state_machine.update_state()
27
- if self.state_machine.current_mission is not None:
28
- self.stopping_return_home_mission = (
29
- self.state_machine.current_mission._is_return_to_home_mission()
30
- )
31
- self._run()
32
-
33
- def stop(self) -> None:
34
- self._count_number_retries = 0
35
- self.stopping_return_home_mission = False
36
-
37
- def _check_and_handle_failed_stop(self, event: Queue[ErrorMessage]) -> bool:
38
- error_message: Optional[ErrorMessage] = check_for_event(event)
39
- if error_message is not None:
40
- self.logger.warning(error_message.error_description)
41
- if self.stopping_return_home_mission:
42
- self.state_machine.return_home_mission_stopping_failed() # type: ignore
43
- else:
44
- self.state_machine.mission_stopping_failed() # type: ignore
45
- return True
46
- return False
47
-
48
- def _check_and_handle_successful_stop(self, event: Queue[bool]) -> bool:
49
- if check_for_event(event):
50
- if self.stopping_return_home_mission:
51
- self.state_machine.return_home_mission_stopped() # type: ignore
52
- else:
53
- self.state_machine.mission_stopped() # type: ignore
54
- return True
55
- return False
56
-
57
- def _run(self) -> None:
58
- while True:
59
- if self.signal_state_machine_to_stop.is_set():
60
- self.logger.info(
61
- "Stopping state machine from %s state", self.__class__.__name__
62
- )
63
- break
64
-
65
- if self._check_and_handle_failed_stop(
66
- self.events.robot_service_events.mission_failed_to_stop
67
- ):
68
- break
69
-
70
- if self._check_and_handle_successful_stop(
71
- self.events.robot_service_events.mission_successfully_stopped
72
- ):
73
- break
74
-
75
- time.sleep(self.state_machine.sleep_time)
12
+ class Stopping(EventHandlerBase):
13
+
14
+ def __init__(self, state_machine: "StateMachine"):
15
+ logger = logging.getLogger("state_machine")
16
+ events = state_machine.events
17
+
18
+ def _failed_stop_event_handler(
19
+ event: Event[ErrorMessage],
20
+ ) -> Optional[Callable]:
21
+ error_message: Optional[ErrorMessage] = event.consume_event()
22
+ if error_message is not None:
23
+ logger.warning(error_message.error_description)
24
+ if (
25
+ state_machine.current_mission is not None
26
+ and state_machine.current_mission._is_return_to_home_mission()
27
+ ):
28
+ return state_machine.return_home_mission_stopping_failed # type: ignore
29
+ else:
30
+ return state_machine.mission_stopping_failed # type: ignore
31
+ return None
32
+
33
+ def _successful_stop_event_handler(event: Event[bool]) -> Optional[Callable]:
34
+ if event.consume_event():
35
+ if (
36
+ state_machine.current_mission is not None
37
+ and state_machine.current_mission._is_return_to_home_mission()
38
+ ):
39
+ return state_machine.return_home_mission_stopped # type: ignore
40
+ else:
41
+ return state_machine.mission_stopped # type: ignore
42
+ return None
43
+
44
+ event_handlers: List[EventHandlerMapping] = [
45
+ EventHandlerMapping(
46
+ name="failed_stop_event",
47
+ event=events.robot_service_events.mission_failed_to_stop,
48
+ handler=_failed_stop_event_handler,
49
+ ),
50
+ EventHandlerMapping(
51
+ name="successful_stop_event",
52
+ event=events.robot_service_events.mission_successfully_stopped,
53
+ handler=_successful_stop_event_handler,
54
+ ),
55
+ ]
56
+ super().__init__(
57
+ state_name="stopping",
58
+ state_machine=state_machine,
59
+ event_handler_mappings=event_handlers,
60
+ )