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.
Files changed (129) hide show
  1. isar/__init__.py +2 -5
  2. isar/apis/api.py +159 -66
  3. isar/apis/models/__init__.py +0 -1
  4. isar/apis/models/models.py +22 -12
  5. isar/apis/models/start_mission_definition.py +128 -123
  6. isar/apis/robot_control/robot_controller.py +41 -0
  7. isar/apis/schedule/scheduling_controller.py +135 -121
  8. isar/apis/security/authentication.py +5 -5
  9. isar/config/certs/ca-cert.pem +32 -32
  10. isar/config/keyvault/keyvault_service.py +1 -2
  11. isar/config/log.py +47 -39
  12. isar/config/logging.conf +16 -31
  13. isar/config/open_telemetry.py +102 -0
  14. isar/config/predefined_mission_definition/default_exr.json +49 -0
  15. isar/config/predefined_mission_definition/default_mission.json +1 -5
  16. isar/config/predefined_mission_definition/default_turtlebot.json +4 -11
  17. isar/config/predefined_missions/default.json +67 -87
  18. isar/config/predefined_missions/default_extra_capabilities.json +107 -0
  19. isar/config/settings.py +119 -142
  20. isar/eventhandlers/eventhandler.py +123 -0
  21. isar/mission_planner/local_planner.py +6 -20
  22. isar/mission_planner/mission_planner_interface.py +1 -1
  23. isar/models/events.py +184 -0
  24. isar/models/status.py +18 -0
  25. isar/modules.py +118 -205
  26. isar/robot/robot.py +377 -0
  27. isar/robot/robot_battery.py +60 -0
  28. isar/robot/robot_monitor_mission.py +357 -0
  29. isar/robot/robot_pause_mission.py +74 -0
  30. isar/robot/robot_resume_mission.py +67 -0
  31. isar/robot/robot_start_mission.py +66 -0
  32. isar/robot/robot_status.py +61 -0
  33. isar/robot/robot_stop_mission.py +68 -0
  34. isar/robot/robot_upload_inspection.py +75 -0
  35. isar/script.py +171 -0
  36. isar/services/service_connections/mqtt/mqtt_client.py +47 -11
  37. isar/services/service_connections/mqtt/robot_heartbeat_publisher.py +32 -0
  38. isar/services/service_connections/mqtt/robot_info_publisher.py +4 -3
  39. isar/services/service_connections/persistent_memory.py +69 -0
  40. isar/services/utilities/mqtt_utilities.py +93 -0
  41. isar/services/utilities/robot_utilities.py +20 -0
  42. isar/services/utilities/scheduling_utilities.py +393 -65
  43. isar/state_machine/state_machine.py +227 -486
  44. isar/state_machine/states/__init__.py +0 -7
  45. isar/state_machine/states/await_next_mission.py +114 -0
  46. isar/state_machine/states/blocked_protective_stop.py +60 -0
  47. isar/state_machine/states/going_to_lockdown.py +95 -0
  48. isar/state_machine/states/going_to_recharging.py +92 -0
  49. isar/state_machine/states/home.py +115 -0
  50. isar/state_machine/states/intervention_needed.py +77 -0
  51. isar/state_machine/states/lockdown.py +38 -0
  52. isar/state_machine/states/maintenance.py +36 -0
  53. isar/state_machine/states/monitor.py +137 -166
  54. isar/state_machine/states/offline.py +60 -0
  55. isar/state_machine/states/paused.py +92 -23
  56. isar/state_machine/states/pausing.py +48 -0
  57. isar/state_machine/states/pausing_return_home.py +48 -0
  58. isar/state_machine/states/recharging.py +80 -0
  59. isar/state_machine/states/resuming.py +57 -0
  60. isar/state_machine/states/resuming_return_home.py +64 -0
  61. isar/state_machine/states/return_home_paused.py +109 -0
  62. isar/state_machine/states/returning_home.py +217 -0
  63. isar/state_machine/states/stopping.py +61 -0
  64. isar/state_machine/states/stopping_due_to_maintenance.py +61 -0
  65. isar/state_machine/states/stopping_go_to_lockdown.py +60 -0
  66. isar/state_machine/states/stopping_go_to_recharge.py +51 -0
  67. isar/state_machine/states/stopping_return_home.py +77 -0
  68. isar/state_machine/states/unknown_status.py +72 -0
  69. isar/state_machine/states_enum.py +22 -5
  70. isar/state_machine/transitions/mission.py +192 -0
  71. isar/state_machine/transitions/return_home.py +106 -0
  72. isar/state_machine/transitions/robot_status.py +80 -0
  73. isar/state_machine/utils/common_event_handlers.py +73 -0
  74. isar/storage/blob_storage.py +71 -45
  75. isar/storage/local_storage.py +28 -14
  76. isar/storage/storage_interface.py +28 -6
  77. isar/storage/uploader.py +184 -55
  78. isar/storage/utilities.py +35 -27
  79. isar-1.34.9.dist-info/METADATA +496 -0
  80. isar-1.34.9.dist-info/RECORD +135 -0
  81. {isar-1.15.0.dist-info → isar-1.34.9.dist-info}/WHEEL +1 -1
  82. isar-1.34.9.dist-info/entry_points.txt +3 -0
  83. robot_interface/models/exceptions/__init__.py +0 -7
  84. robot_interface/models/exceptions/robot_exceptions.py +274 -4
  85. robot_interface/models/initialize/__init__.py +0 -1
  86. robot_interface/models/inspection/__init__.py +0 -13
  87. robot_interface/models/inspection/inspection.py +43 -34
  88. robot_interface/models/mission/mission.py +18 -14
  89. robot_interface/models/mission/status.py +20 -25
  90. robot_interface/models/mission/task.py +156 -92
  91. robot_interface/models/robots/battery_state.py +6 -0
  92. robot_interface/models/robots/media.py +13 -0
  93. robot_interface/models/robots/robot_model.py +7 -7
  94. robot_interface/robot_interface.py +135 -66
  95. robot_interface/telemetry/mqtt_client.py +84 -12
  96. robot_interface/telemetry/payloads.py +111 -12
  97. robot_interface/utilities/json_service.py +7 -1
  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 -26
  102. isar/mission_planner/sequential_task_selector.py +0 -23
  103. isar/mission_planner/task_selector_interface.py +0 -31
  104. isar/models/communication/__init__.py +0 -0
  105. isar/models/communication/message.py +0 -12
  106. isar/models/communication/queues/__init__.py +0 -4
  107. isar/models/communication/queues/queue_io.py +0 -12
  108. isar/models/communication/queues/queue_timeout_error.py +0 -2
  109. isar/models/communication/queues/queues.py +0 -19
  110. isar/models/communication/queues/status_queue.py +0 -20
  111. isar/models/mission_metadata/__init__.py +0 -0
  112. isar/services/readers/__init__.py +0 -0
  113. isar/services/readers/base_reader.py +0 -37
  114. isar/services/service_connections/mqtt/robot_status_publisher.py +0 -93
  115. isar/services/service_connections/stid/__init__.py +0 -0
  116. isar/services/service_connections/stid/stid_service.py +0 -45
  117. isar/services/utilities/queue_utilities.py +0 -39
  118. isar/state_machine/states/idle.py +0 -40
  119. isar/state_machine/states/initialize.py +0 -60
  120. isar/state_machine/states/initiate.py +0 -129
  121. isar/state_machine/states/off.py +0 -18
  122. isar/state_machine/states/stop.py +0 -78
  123. isar/storage/slimm_storage.py +0 -181
  124. isar-1.15.0.dist-info/METADATA +0 -417
  125. isar-1.15.0.dist-info/RECORD +0 -113
  126. robot_interface/models/initialize/initialize_params.py +0 -9
  127. robot_interface/models/mission/step.py +0 -211
  128. {isar-1.15.0.dist-info → isar-1.34.9.dist-info/licenses}/LICENSE +0 -0
  129. {isar-1.15.0.dist-info → isar-1.34.9.dist-info}/top_level.txt +0 -0
@@ -1,96 +1,160 @@
1
- from dataclasses import dataclass, field
2
- from typing import Iterator, List, Optional
3
-
4
- from robot_interface.models.mission.status import StepStatus, TaskStatus
5
- from robot_interface.models.mission.step import (
6
- STEPS,
7
- DriveToPose,
8
- InspectionStep,
9
- MotionStep,
10
- Step,
1
+ from enum import Enum
2
+ from typing import Literal, Optional, Type, Union
3
+
4
+ from alitra import Pose, Position
5
+ from pydantic import BaseModel, Field
6
+
7
+ from robot_interface.models.exceptions.robot_exceptions import ErrorMessage
8
+ from robot_interface.models.inspection.inspection import (
9
+ Audio,
10
+ CO2Measurement,
11
+ Image,
12
+ Inspection,
13
+ ThermalImage,
14
+ ThermalVideo,
15
+ Video,
11
16
  )
17
+ from robot_interface.models.mission.status import TaskStatus
12
18
  from robot_interface.utilities.uuid_string_factory import uuid4_string
13
19
 
14
20
 
15
- @dataclass
16
- class Task:
17
- steps: List[STEPS]
18
- status: TaskStatus = field(default=TaskStatus.NotStarted, init=False)
19
- tag_id: Optional[str] = field(default=None)
20
- id: str = field(default_factory=uuid4_string, init=True)
21
- _iterator: Iterator = None
22
-
23
- def next_step(self) -> Step:
24
- step: Step = next(self._iterator)
25
- while step.status != StepStatus.NotStarted:
26
- step = next(self._iterator)
27
- return step
28
-
29
- def is_finished(self) -> bool:
30
- for step in self.steps:
31
- if step.status is StepStatus.Failed and isinstance(step, MotionStep):
32
- # One motion step has failed meaning the task as a whole should be
33
- # considered as failed
34
- return True
35
-
36
- elif (step.status is StepStatus.Failed) and isinstance(
37
- step, InspectionStep
38
- ):
39
- # It should be possible to perform several inspections per task. If
40
- # one out of many inspections fail the task is considered as
41
- # partially successful.
42
- continue
43
-
44
- elif step.status is StepStatus.Successful:
45
- # The task is complete once all steps are completed
46
- continue
47
- else:
48
- # Not all steps have been completed yet
49
- return False
50
-
51
- return True
52
-
53
- def update_task_status(self) -> None:
54
- for step in self.steps:
55
- if step.status is StepStatus.Failed and isinstance(step, MotionStep):
56
- self.status = TaskStatus.Failed
57
- return
58
-
59
- elif (step.status is StepStatus.Failed) and isinstance(
60
- step, InspectionStep
61
- ):
62
- self.status = TaskStatus.PartiallySuccessful
63
- continue
64
-
65
- elif step.status is StepStatus.Successful:
66
- continue
67
-
68
- if self.status is not TaskStatus.PartiallySuccessful:
69
- self.status = TaskStatus.Successful
70
-
71
- elif self._all_inspection_steps_failed():
72
- self.status = TaskStatus.Failed
73
-
74
- def reset_task(self):
75
- for step in self.steps:
76
- if isinstance(step, DriveToPose):
77
- step.status = StepStatus.NotStarted
78
- elif (
79
- isinstance(step, InspectionStep)
80
- and step.status == StepStatus.InProgress
81
- ):
82
- step.status = StepStatus.NotStarted
83
- self._iterator = iter(self.steps)
84
-
85
- def _all_inspection_steps_failed(self) -> bool:
86
- for step in self.steps:
87
- if isinstance(step, MotionStep):
88
- continue
89
- elif step.status is not StepStatus.Failed:
90
- return False
91
-
92
- return True
93
-
94
- def __post_init__(self) -> None:
95
- if self._iterator is None:
96
- self._iterator = iter(self.steps)
21
+ class TaskTypes(str, Enum):
22
+ ReturnToHome = "return_to_home"
23
+ TakeImage = "take_image"
24
+ TakeThermalImage = "take_thermal_image"
25
+ TakeVideo = "take_video"
26
+ TakeThermalVideo = "take_thermal_video"
27
+ TakeCO2Measurement = "take_co2_measurement"
28
+ RecordAudio = "record_audio"
29
+
30
+
31
+ class ZoomDescription(BaseModel):
32
+ objectWidth: float
33
+ objectHeight: float
34
+
35
+
36
+ class Task(BaseModel):
37
+ status: TaskStatus = Field(default=TaskStatus.NotStarted)
38
+ error_message: Optional[ErrorMessage] = Field(default=None)
39
+ tag_id: Optional[str] = Field(default=None)
40
+ id: str = Field(default_factory=uuid4_string, frozen=True)
41
+
42
+
43
+ class InspectionTask(Task):
44
+ """
45
+ Base class for all inspection tasks which produce results to be uploaded.
46
+ """
47
+
48
+ inspection_id: str = Field(default_factory=uuid4_string, frozen=True)
49
+ robot_pose: Pose = Field(default=None, init=True)
50
+ inspection_description: Optional[str] = Field(default=None)
51
+ zoom: Optional[ZoomDescription] = Field(default=None)
52
+
53
+ @staticmethod
54
+ def get_inspection_type() -> Type[Inspection]:
55
+ return Inspection
56
+
57
+
58
+ class ReturnToHome(Task):
59
+ """
60
+ Task which cases the robot to return home
61
+ """
62
+
63
+ type: Literal[TaskTypes.ReturnToHome] = TaskTypes.ReturnToHome
64
+
65
+
66
+ class TakeImage(InspectionTask):
67
+ """
68
+ Task which causes the robot to take an image towards the given target.
69
+ """
70
+
71
+ target: Position = Field(default=None)
72
+ type: Literal[TaskTypes.TakeImage] = TaskTypes.TakeImage
73
+
74
+ @staticmethod
75
+ def get_inspection_type() -> Type[Inspection]:
76
+ return Image
77
+
78
+
79
+ class TakeThermalImage(InspectionTask):
80
+ """
81
+ Task which causes the robot to take a thermal image towards the given target.
82
+ """
83
+
84
+ target: Position = Field(default=None)
85
+ type: Literal[TaskTypes.TakeThermalImage] = TaskTypes.TakeThermalImage
86
+
87
+ @staticmethod
88
+ def get_inspection_type() -> Type[Inspection]:
89
+ return ThermalImage
90
+
91
+
92
+ class TakeVideo(InspectionTask):
93
+ """
94
+ Task which causes the robot to take a video towards the given target.
95
+
96
+ Duration of video is given in seconds.
97
+ """
98
+
99
+ target: Position = Field(default=None)
100
+ duration: float = Field(default=None)
101
+ type: Literal[TaskTypes.TakeVideo] = TaskTypes.TakeVideo
102
+
103
+ @staticmethod
104
+ def get_inspection_type() -> Type[Inspection]:
105
+ return Video
106
+
107
+
108
+ class TakeThermalVideo(InspectionTask):
109
+ """
110
+ Task which causes the robot to record thermal video towards the given target
111
+
112
+ Duration of video is given in seconds.
113
+ """
114
+
115
+ target: Position = Field(default=None)
116
+ duration: float = Field(default=None)
117
+ type: Literal[TaskTypes.TakeThermalVideo] = TaskTypes.TakeThermalVideo
118
+
119
+ @staticmethod
120
+ def get_inspection_type() -> Type[Inspection]:
121
+ return ThermalVideo
122
+
123
+
124
+ class RecordAudio(InspectionTask):
125
+ """
126
+ Task which causes the robot to record a video at its position, facing the target.
127
+
128
+ Duration of audio is given in seconds.
129
+ """
130
+
131
+ target: Position = Field(default=None)
132
+ duration: float = Field(default=None)
133
+ type: Literal[TaskTypes.RecordAudio] = TaskTypes.RecordAudio
134
+
135
+ @staticmethod
136
+ def get_inspection_type() -> Type[Inspection]:
137
+ return Audio
138
+
139
+
140
+ class TakeCO2Measurement(InspectionTask):
141
+ """
142
+ Task which causes the robot to take a CO2 measurement at its position.
143
+ """
144
+
145
+ type: Literal[TaskTypes.TakeCO2Measurement] = TaskTypes.TakeCO2Measurement
146
+
147
+ @staticmethod
148
+ def get_inspection_type() -> Type[Inspection]:
149
+ return CO2Measurement
150
+
151
+
152
+ TASKS = Union[
153
+ ReturnToHome,
154
+ TakeImage,
155
+ TakeThermalImage,
156
+ TakeVideo,
157
+ TakeThermalVideo,
158
+ TakeCO2Measurement,
159
+ RecordAudio,
160
+ ]
@@ -0,0 +1,6 @@
1
+ from enum import Enum
2
+
3
+
4
+ class BatteryState(Enum):
5
+ Normal = "Normal"
6
+ Charging = "Charging"
@@ -0,0 +1,13 @@
1
+ from dataclasses import dataclass
2
+ from enum import Enum
3
+
4
+
5
+ class MediaConnectionType(str, Enum):
6
+ LiveKit = "LiveKit"
7
+
8
+
9
+ @dataclass
10
+ class MediaConfig:
11
+ url: str
12
+ token: str
13
+ media_connection_type: MediaConnectionType
@@ -4,10 +4,10 @@ from enum import Enum
4
4
  # Did you write your own isar-robot package and would like to have it included here?
5
5
  # Open a pull request to the ISAR repository!
6
6
  class RobotModel(Enum):
7
- TaurobInspector: str = "TaurobInspector"
8
- TaurobOperator: str = "TaurobOperator"
9
- ExR2: str = "ExR2"
10
- Robot: str = "Robot" # This corresponds to the mock in isar_robot
11
- Turtlebot: str = "Turtlebot"
12
- AnymalX: str = "AnymalX"
13
- AnymalD: str = "AnymalD"
7
+ TaurobInspector = "TaurobInspector"
8
+ TaurobOperator = "TaurobOperator"
9
+ ExR2 = "ExR2"
10
+ Robot = "Robot" # This corresponds to the mock in isar_robot
11
+ Turtlebot = "Turtlebot"
12
+ AnymalX = "AnymalX"
13
+ AnymalD = "AnymalD"
@@ -1,13 +1,13 @@
1
1
  from abc import ABCMeta, abstractmethod
2
2
  from queue import Queue
3
3
  from threading import Thread
4
- from typing import List, Sequence
4
+ from typing import Callable, List, Optional
5
5
 
6
- from robot_interface.models.initialize import InitializeParams
7
6
  from robot_interface.models.inspection.inspection import Inspection
8
7
  from robot_interface.models.mission.mission import Mission
9
- from robot_interface.models.mission.status import MissionStatus, RobotStatus, StepStatus
10
- from robot_interface.models.mission.step import InspectionStep, Step
8
+ from robot_interface.models.mission.status import MissionStatus, RobotStatus, TaskStatus
9
+ from robot_interface.models.mission.task import InspectionTask
10
+ from robot_interface.models.robots.media import MediaConfig
11
11
 
12
12
 
13
13
  class RobotInterface(metaclass=ABCMeta):
@@ -17,10 +17,6 @@ class RobotInterface(metaclass=ABCMeta):
17
17
  def initiate_mission(self, mission: Mission) -> None:
18
18
  """Send a mission to the robot and initiate execution of the mission
19
19
 
20
- This function should be used in combination with the mission_status function
21
- if the robot is designed to run full missions and not in a stepwise
22
- configuration.
23
-
24
20
  Parameters
25
21
  ----------
26
22
  mission: Mission
@@ -31,47 +27,66 @@ class RobotInterface(metaclass=ABCMeta):
31
27
 
32
28
  Raises
33
29
  ------
30
+ RobotAlreadyHomeException
31
+ If the mission is a return home mission and the robot wish to disregard the
32
+ mission as it is already at home
33
+ RobotInfeasibleMissionException
34
+ If the mission input is infeasible and the mission fails to be scheduled in
35
+ a way that means attempting to schedule again is not necessary
34
36
  RobotException
35
- If the mission is not initiated.
36
- NotImplementedError
37
- If the robot is designed for stepwise mission execution.
37
+ Will catch all RobotExceptions not previously listed and retry scheduling of
38
+ the mission until the number of allowed retries is exceeded
38
39
 
39
40
  """
40
41
  raise NotImplementedError
41
42
 
42
- def mission_status(self) -> MissionStatus:
43
- """Gets the status of the currently active mission on the robot
43
+ @abstractmethod
44
+ def task_status(self, task_id: str) -> TaskStatus:
45
+ """Gets the status of the currently active task on robot.
44
46
 
45
- This function should be used in combination with the initiate_mission function
46
- if the robot is designed to run full missions and not in a stepwise
47
- configuration.
47
+ Returns
48
+ -------
49
+ TaskStatus
50
+ Status of the execution of current task.
51
+
52
+ Raises
53
+ ------
54
+ RobotCommunicationTimeoutException or RobotCommunicationException
55
+ If the robot package is unable to communicate with the robot API the fetching
56
+ of task status will be attempted again until a certain number of retries
57
+ RobotTaskStatusException
58
+ If there was an error when retrieving the task status
59
+ RobotException
60
+ If the task status could not be retrieved.
61
+
62
+ """
63
+ raise NotImplementedError
64
+
65
+ @abstractmethod
66
+ def mission_status(self, mission_id: str) -> MissionStatus:
67
+ """Gets the status of the mission with ID mission_id on robot.
48
68
 
49
69
  Returns
50
70
  -------
51
71
  MissionStatus
52
- Status of the executing mission on the robot.
72
+ Status of the execution of mission.
53
73
 
54
74
  Raises
55
75
  ------
76
+ RobotCommunicationTimeoutException or RobotCommunicationException
77
+ If the robot package is unable to communicate with the robot API the fetching
78
+ of mission status will be attempted again until a certain number of retries
79
+ RobotMissionStatusException
80
+ If there was an error when retrieving the mission status
56
81
  RobotException
57
82
  If the mission status could not be retrieved.
58
- NotImplementedError
59
- If the robot is designed for stepwise mission execution.
60
83
 
61
84
  """
85
+ raise NotImplementedError
62
86
 
63
87
  @abstractmethod
64
- def initiate_step(self, step: Step) -> None:
65
- """Send a step to the robot and initiate the execution of the step
66
-
67
- This function should be used in combination with the step_status function
68
- if the robot is designed to run stepwise missions and not in a full mission
69
- configuration.
70
-
71
- Parameters
72
- ----------
73
- step : Step
74
- The step that should be initiated on the robot.
88
+ def stop(self) -> None:
89
+ """Stops the execution of the current task and corresponding mission.
75
90
 
76
91
  Returns
77
92
  -------
@@ -79,40 +94,37 @@ class RobotInterface(metaclass=ABCMeta):
79
94
 
80
95
  Raises
81
96
  ------
97
+ RobotActionException
98
+ If the robot fails to perform the requested action to stop mission execution
99
+ the action to stop will be attempted again until a certain number of retries
82
100
  RobotException
83
- If the step is not initiated.
84
- NotImplementedError
85
- If the robot is designed for full mission execution.
101
+ Will catch other RobotExceptions and retry to stop the mission
86
102
 
87
103
  """
88
104
  raise NotImplementedError
89
105
 
90
106
  @abstractmethod
91
- def step_status(self) -> StepStatus:
92
- """Gets the status of the currently active step on robot.
93
-
94
- This function should be used in combination with the initiate_step function
95
- if the robot is designed to run stepwise missions and not in a full mission
96
- configuration.
107
+ def pause(self) -> None:
108
+ """Pauses the execution of the current task and stops the movement of the robot.
97
109
 
98
110
  Returns
99
111
  -------
100
- StepStatus
101
- Status of the execution of current step.
112
+ None
102
113
 
103
114
  Raises
104
115
  ------
116
+ RobotActionException
117
+ If the robot fails to perform the requested action to pause mission execution
118
+ the action to pause will be attempted again until a certain number of retries
105
119
  RobotException
106
- If the step status could not be retrieved.
107
- NotImplementedError
108
- If the robot is designed for full mission execution.
120
+ Will catch other RobotExceptions and retry to pause the mission
109
121
 
110
122
  """
111
123
  raise NotImplementedError
112
124
 
113
125
  @abstractmethod
114
- def stop(self) -> None:
115
- """Stops the execution of the current step and stops the movement of the robot.
126
+ def resume(self) -> None:
127
+ """Resumes the execution of the current task and continues the rest of the mission.
116
128
 
117
129
  Returns
118
130
  -------
@@ -120,51 +132,70 @@ class RobotInterface(metaclass=ABCMeta):
120
132
 
121
133
  Raises
122
134
  ------
135
+ RobotActionException
136
+ If the robot fails to perform the requested action to resume mission execution
137
+ the action to resume will be attempted again until a certain number of retries
123
138
  RobotException
124
- If the robot is not stopped.
139
+ Will catch other RobotExceptions and retry to resume the mission
125
140
 
126
141
  """
127
142
  raise NotImplementedError
128
143
 
129
144
  @abstractmethod
130
- def get_inspections(self, step: InspectionStep) -> Sequence[Inspection]:
131
- """Return the inspections connected to the given step.
145
+ def get_inspection(self, task: InspectionTask) -> Inspection:
146
+ """Return the inspection connected to the given task.
132
147
 
133
148
  Parameters
134
149
  ----------
135
- step : Step
150
+ task : InspectionTask
136
151
 
137
152
  Returns
138
153
  -------
139
- Sequence[InspectionResult]
140
- List containing all the inspection results connected to the given step.
154
+ Inspection
155
+ The inspection connected to the given task.
156
+ get_inspection has responsibility to assign the inspection_id of the task
157
+ to the inspection that it returns.
141
158
 
142
159
  Raises
143
160
  ------
161
+ RobotRetrieveInspectionException
162
+ If the robot package is unable to retrieve the inspections for the relevant
163
+ mission or task an error message is logged and the state machine continues
144
164
  RobotException
145
- If the inspection results can't be retrieved.
165
+ Catches other RobotExceptions that lead to the same result as a
166
+ RobotRetrieveInspectionException
146
167
 
147
168
  """
148
169
  raise NotImplementedError
149
170
 
150
171
  @abstractmethod
151
- def initialize(self, params: InitializeParams) -> None:
152
- """Initializes the robot. The initialization needed is robot dependent and the
153
- function can be a simple return statement if no initialization is needed for the
154
- robot.
172
+ def register_inspection_callback(
173
+ self, callback_function: Callable[[Inspection, Mission], None]
174
+ ) -> None:
175
+ """Register a function which should be run when inspection data is received
176
+ asynchronously. This function should expect to receive an Inspection from.
155
177
 
156
178
  Parameters
157
179
  ----------
158
- params: InitializeParams
180
+ callback_function : Callable[[Inspection, Mission], None]
159
181
 
160
182
  Returns
161
183
  -------
162
184
  None
163
185
 
164
- Raises
165
- ------
166
- RobotException
167
- If the initialization failed
186
+ """
187
+ raise NotImplementedError
188
+
189
+ @abstractmethod
190
+ def generate_media_config(self) -> Optional[MediaConfig]:
191
+ """
192
+ Generate a JSON containing the url and token needed to establish a media stream
193
+ connection to a robot.
194
+
195
+ Returns
196
+ -------
197
+ MediaConfig
198
+ An object containing the connection information for a media stream connection
168
199
 
169
200
  """
170
201
  raise NotImplementedError
@@ -195,15 +226,53 @@ class RobotInterface(metaclass=ABCMeta):
195
226
  @abstractmethod
196
227
  def robot_status(self) -> RobotStatus:
197
228
  """
198
- Method which returns an enum indicating if the robot package is able to reach
199
- the interface which is used to communicate with the robot. This is further used
200
- by ISAR to indicate whether the ISAR instance is fully functional and may be
201
- used by other systems.
229
+ Method which returns an enum indicating the status of the robot.
202
230
 
203
231
  Returns
204
232
  -------
205
233
  RobotStatus
206
234
  Enum indicating if the robot may be reached by the isar-robot package.
207
235
 
236
+ Raises
237
+ -------
238
+ RobotCommunicationException
239
+ Raised if the robot package is unable to communicate with the robot API.
240
+ The fetching of robot status will be attempted again until success
241
+ RobotAPIException
242
+ Raised if the robot package is able to communicate with the API but an error
243
+ occurred while interpreting the response. The fetching of robot status will
244
+ be attempted again until success
245
+ RobotException
246
+ Catches other RobotExceptions that may have occurred while retrieving the
247
+ robot status. The fetching of robot status will be attempted again until
248
+ success
249
+
250
+ """
251
+ raise NotImplementedError
252
+
253
+ @abstractmethod
254
+ def get_battery_level(self) -> float:
255
+ """
256
+ Method which returns the percent charge remaining in the robot battery.
257
+
258
+ Returns
259
+ -------
260
+ float
261
+ The battery percentage on the robot
262
+
263
+ Raises
264
+ -------
265
+ RobotCommunicationException
266
+ Raised if the robot package is unable to communicate with the robot API.
267
+ The fetching of robot battery level will be attempted again until success
268
+ RobotAPIException
269
+ Raised if the robot package is able to communicate with the API but an error
270
+ occurred while interpreting the response. The fetching of robot battery level
271
+ will be attempted again until success
272
+ RobotException
273
+ Catches other RobotExceptions that may have occurred while retrieving the
274
+ robot battery level. The fetching of robot battery level will
275
+ be attempted again until success
276
+
208
277
  """
209
278
  raise NotImplementedError