isar 1.20.2__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 (124) hide show
  1. isar/apis/api.py +148 -76
  2. isar/apis/models/__init__.py +0 -1
  3. isar/apis/models/models.py +21 -11
  4. isar/apis/models/start_mission_definition.py +110 -168
  5. isar/apis/robot_control/robot_controller.py +41 -0
  6. isar/apis/schedule/scheduling_controller.py +124 -162
  7. isar/apis/security/authentication.py +5 -5
  8. isar/config/certs/ca-cert.pem +33 -31
  9. isar/config/keyvault/keyvault_service.py +1 -1
  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/predefined_mission_definition/default_exr.json +0 -2
  14. isar/config/predefined_mission_definition/default_mission.json +1 -5
  15. isar/config/predefined_mission_definition/default_turtlebot.json +4 -11
  16. isar/config/predefined_missions/default.json +67 -87
  17. isar/config/predefined_missions/default_extra_capabilities.json +107 -0
  18. isar/config/settings.py +76 -111
  19. isar/eventhandlers/eventhandler.py +123 -0
  20. isar/mission_planner/local_planner.py +6 -20
  21. isar/mission_planner/mission_planner_interface.py +1 -1
  22. isar/models/events.py +184 -0
  23. isar/models/status.py +18 -0
  24. isar/modules.py +118 -199
  25. isar/robot/robot.py +377 -0
  26. isar/robot/robot_battery.py +60 -0
  27. isar/robot/robot_monitor_mission.py +357 -0
  28. isar/robot/robot_pause_mission.py +74 -0
  29. isar/robot/robot_resume_mission.py +67 -0
  30. isar/robot/robot_start_mission.py +66 -0
  31. isar/robot/robot_status.py +61 -0
  32. isar/robot/robot_stop_mission.py +68 -0
  33. isar/robot/robot_upload_inspection.py +75 -0
  34. isar/script.py +57 -40
  35. isar/services/service_connections/mqtt/mqtt_client.py +47 -11
  36. isar/services/service_connections/mqtt/robot_heartbeat_publisher.py +5 -2
  37. isar/services/service_connections/mqtt/robot_info_publisher.py +3 -3
  38. isar/services/service_connections/persistent_memory.py +69 -0
  39. isar/services/utilities/mqtt_utilities.py +93 -0
  40. isar/services/utilities/robot_utilities.py +20 -0
  41. isar/services/utilities/scheduling_utilities.py +393 -65
  42. isar/state_machine/state_machine.py +219 -538
  43. isar/state_machine/states/__init__.py +0 -8
  44. isar/state_machine/states/await_next_mission.py +114 -0
  45. isar/state_machine/states/blocked_protective_stop.py +60 -0
  46. isar/state_machine/states/going_to_lockdown.py +95 -0
  47. isar/state_machine/states/going_to_recharging.py +92 -0
  48. isar/state_machine/states/home.py +115 -0
  49. isar/state_machine/states/intervention_needed.py +77 -0
  50. isar/state_machine/states/lockdown.py +38 -0
  51. isar/state_machine/states/maintenance.py +36 -0
  52. isar/state_machine/states/monitor.py +137 -247
  53. isar/state_machine/states/offline.py +51 -53
  54. isar/state_machine/states/paused.py +92 -23
  55. isar/state_machine/states/pausing.py +48 -0
  56. isar/state_machine/states/pausing_return_home.py +48 -0
  57. isar/state_machine/states/recharging.py +80 -0
  58. isar/state_machine/states/resuming.py +57 -0
  59. isar/state_machine/states/resuming_return_home.py +64 -0
  60. isar/state_machine/states/return_home_paused.py +109 -0
  61. isar/state_machine/states/returning_home.py +217 -0
  62. isar/state_machine/states/stopping.py +61 -0
  63. isar/state_machine/states/stopping_due_to_maintenance.py +61 -0
  64. isar/state_machine/states/stopping_go_to_lockdown.py +60 -0
  65. isar/state_machine/states/stopping_go_to_recharge.py +51 -0
  66. isar/state_machine/states/stopping_return_home.py +77 -0
  67. isar/state_machine/states/unknown_status.py +72 -0
  68. isar/state_machine/states_enum.py +21 -5
  69. isar/state_machine/transitions/mission.py +192 -0
  70. isar/state_machine/transitions/return_home.py +106 -0
  71. isar/state_machine/transitions/robot_status.py +80 -0
  72. isar/state_machine/utils/common_event_handlers.py +73 -0
  73. isar/storage/blob_storage.py +70 -52
  74. isar/storage/local_storage.py +25 -12
  75. isar/storage/storage_interface.py +28 -7
  76. isar/storage/uploader.py +174 -55
  77. isar/storage/utilities.py +32 -29
  78. {isar-1.20.2.dist-info → isar-1.34.9.dist-info}/METADATA +73 -110
  79. isar-1.34.9.dist-info/RECORD +135 -0
  80. {isar-1.20.2.dist-info → isar-1.34.9.dist-info}/WHEEL +1 -1
  81. {isar-1.20.2.dist-info → isar-1.34.9.dist-info}/entry_points.txt +1 -0
  82. robot_interface/models/exceptions/robot_exceptions.py +91 -41
  83. robot_interface/models/initialize/__init__.py +0 -1
  84. robot_interface/models/inspection/__init__.py +0 -13
  85. robot_interface/models/inspection/inspection.py +42 -33
  86. robot_interface/models/mission/mission.py +14 -15
  87. robot_interface/models/mission/status.py +20 -26
  88. robot_interface/models/mission/task.py +154 -121
  89. robot_interface/models/robots/battery_state.py +6 -0
  90. robot_interface/models/robots/media.py +13 -0
  91. robot_interface/models/robots/robot_model.py +7 -7
  92. robot_interface/robot_interface.py +119 -84
  93. robot_interface/telemetry/mqtt_client.py +74 -12
  94. robot_interface/telemetry/payloads.py +91 -13
  95. robot_interface/utilities/json_service.py +7 -1
  96. isar/config/predefined_missions/default_turtlebot.json +0 -110
  97. isar/config/predefined_poses/__init__.py +0 -0
  98. isar/config/predefined_poses/predefined_poses.py +0 -616
  99. isar/config/settings.env +0 -25
  100. isar/mission_planner/sequential_task_selector.py +0 -23
  101. isar/mission_planner/task_selector_interface.py +0 -31
  102. isar/models/communication/__init__.py +0 -0
  103. isar/models/communication/message.py +0 -12
  104. isar/models/communication/queues/__init__.py +0 -4
  105. isar/models/communication/queues/queue_io.py +0 -12
  106. isar/models/communication/queues/queue_timeout_error.py +0 -2
  107. isar/models/communication/queues/queues.py +0 -19
  108. isar/models/communication/queues/status_queue.py +0 -20
  109. isar/models/mission_metadata/__init__.py +0 -0
  110. isar/services/readers/__init__.py +0 -0
  111. isar/services/readers/base_reader.py +0 -37
  112. isar/services/service_connections/stid/__init__.py +0 -0
  113. isar/services/utilities/queue_utilities.py +0 -39
  114. isar/state_machine/states/idle.py +0 -85
  115. isar/state_machine/states/initialize.py +0 -71
  116. isar/state_machine/states/initiate.py +0 -142
  117. isar/state_machine/states/off.py +0 -18
  118. isar/state_machine/states/stop.py +0 -95
  119. isar/storage/slimm_storage.py +0 -191
  120. isar-1.20.2.dist-info/RECORD +0 -116
  121. robot_interface/models/initialize/initialize_params.py +0 -9
  122. robot_interface/models/mission/step.py +0 -234
  123. {isar-1.20.2.dist-info → isar-1.34.9.dist-info/licenses}/LICENSE +0 -0
  124. {isar-1.20.2.dist-info → isar-1.34.9.dist-info}/top_level.txt +0 -0
@@ -1,61 +1,62 @@
1
- from abc import ABC
2
- from dataclasses import dataclass, field
3
1
  from datetime import datetime
4
2
  from typing import Optional, Type
5
3
 
6
- from alitra import Pose
4
+ from alitra import Pose, Position
5
+ from pydantic import BaseModel, Field
7
6
 
8
- from robot_interface.utilities.uuid_string_factory import uuid4_string
9
7
 
10
-
11
- @dataclass
12
- class InspectionMetadata(ABC):
8
+ class InspectionMetadata(BaseModel):
13
9
  start_time: datetime
14
- pose: Pose
10
+ robot_pose: Pose
11
+ target_position: Position
15
12
  file_type: str
16
- analysis_type: Optional[str] = field(default=None, init=False)
17
- tag_id: Optional[str] = field(default=None, init=False)
18
- additional: Optional[dict] = field(default_factory=dict, init=False)
13
+ tag_id: Optional[str] = None
14
+ inspection_description: Optional[str] = None
19
15
 
20
16
 
21
- @dataclass
22
17
  class ImageMetadata(InspectionMetadata):
23
18
  pass
24
19
 
25
20
 
26
- @dataclass
27
21
  class ThermalImageMetadata(InspectionMetadata):
28
22
  pass
29
23
 
30
24
 
31
- @dataclass
32
25
  class VideoMetadata(InspectionMetadata):
33
- duration: Optional[float] = field(default=None)
26
+ duration: float
34
27
 
35
28
 
36
- @dataclass
37
29
  class ThermalVideoMetadata(InspectionMetadata):
38
- duration: Optional[float] = field(default=None)
30
+ duration: float
39
31
 
40
32
 
41
- @dataclass
42
33
  class AudioMetadata(InspectionMetadata):
43
- duration: Optional[float] = field(default=None)
34
+ duration: float
35
+
36
+
37
+ class GasMeasurementMetadata(InspectionMetadata):
38
+ pass
44
39
 
45
40
 
46
- @dataclass
47
- class Inspection:
48
- id: str = field(default_factory=uuid4_string, init=False)
41
+ class Inspection(BaseModel):
49
42
  metadata: InspectionMetadata
50
- data: Optional[bytes] = field(default=None, init=False)
43
+ id: str = Field(frozen=True)
51
44
 
52
45
  @staticmethod
53
46
  def get_metadata_type() -> Type[InspectionMetadata]:
54
47
  return InspectionMetadata
55
48
 
56
49
 
57
- @dataclass
58
- class Image(Inspection):
50
+ class InspectionValue(Inspection):
51
+ value: float = Field(frozen=True)
52
+ unit: str = Field(frozen=True)
53
+
54
+
55
+ class InspectionBlob(Inspection):
56
+ data: Optional[bytes] = Field(default=None, frozen=True)
57
+
58
+
59
+ class Image(InspectionBlob):
59
60
  metadata: ImageMetadata
60
61
 
61
62
  @staticmethod
@@ -63,8 +64,7 @@ class Image(Inspection):
63
64
  return ImageMetadata
64
65
 
65
66
 
66
- @dataclass
67
- class ThermalImage(Inspection):
67
+ class ThermalImage(InspectionBlob):
68
68
  metadata: ThermalImageMetadata
69
69
 
70
70
  @staticmethod
@@ -72,8 +72,7 @@ class ThermalImage(Inspection):
72
72
  return ThermalImageMetadata
73
73
 
74
74
 
75
- @dataclass
76
- class Video(Inspection):
75
+ class Video(InspectionBlob):
77
76
  metadata: VideoMetadata
78
77
 
79
78
  @staticmethod
@@ -81,8 +80,7 @@ class Video(Inspection):
81
80
  return VideoMetadata
82
81
 
83
82
 
84
- @dataclass
85
- class ThermalVideo(Inspection):
83
+ class ThermalVideo(InspectionBlob):
86
84
  metadata: ThermalVideoMetadata
87
85
 
88
86
  @staticmethod
@@ -90,10 +88,21 @@ class ThermalVideo(Inspection):
90
88
  return ThermalVideoMetadata
91
89
 
92
90
 
93
- @dataclass
94
- class Audio(Inspection):
91
+ class Audio(InspectionBlob):
95
92
  metadata: AudioMetadata
96
93
 
97
94
  @staticmethod
98
95
  def get_metadata_type() -> Type[InspectionMetadata]:
99
96
  return AudioMetadata
97
+
98
+
99
+ class GasMeasurement(InspectionValue):
100
+ metadata: GasMeasurementMetadata
101
+
102
+ @staticmethod
103
+ def get_metadata_type() -> Type[InspectionMetadata]:
104
+ return GasMeasurementMetadata
105
+
106
+
107
+ class CO2Measurement(GasMeasurement):
108
+ pass
@@ -1,26 +1,25 @@
1
- from dataclasses import dataclass, field
2
1
  from typing import List, Optional
3
2
 
4
3
  from alitra import Pose
4
+ from pydantic import BaseModel, Field
5
5
 
6
6
  from robot_interface.models.exceptions.robot_exceptions import ErrorMessage
7
7
  from robot_interface.models.mission.status import MissionStatus
8
- from robot_interface.models.mission.task import Task
8
+ from robot_interface.models.mission.task import TASKS, TaskTypes
9
9
  from robot_interface.utilities.uuid_string_factory import uuid4_string
10
10
 
11
11
 
12
- @dataclass
13
- class Mission:
14
- tasks: List[Task]
15
- id: str = field(default_factory=uuid4_string, init=True)
16
- name: str = ""
17
- start_pose: Optional[Pose] = None
12
+ class Mission(BaseModel):
13
+ id: str = Field(default_factory=uuid4_string, frozen=True)
14
+ tasks: List[TASKS] = Field(default_factory=list, frozen=True)
15
+ name: str = Field(frozen=True)
16
+ start_pose: Optional[Pose] = Field(default=None, frozen=True)
18
17
  status: MissionStatus = MissionStatus.NotStarted
19
- error_message: Optional[ErrorMessage] = field(default=None, init=False)
18
+ error_message: Optional[ErrorMessage] = Field(default=None)
20
19
 
21
- def _set_unique_id(self) -> None:
22
- self.id: str = uuid4_string()
23
-
24
- def __post_init__(self) -> None:
25
- if self.id is None:
26
- self._set_unique_id()
20
+ def _is_return_to_home_mission(self) -> bool:
21
+ if len(self.tasks) != 1:
22
+ return False
23
+ if self.tasks[0].type != TaskTypes.ReturnToHome:
24
+ return False
25
+ return True
@@ -2,35 +2,29 @@ from enum import Enum
2
2
 
3
3
 
4
4
  class MissionStatus(str, Enum):
5
- NotStarted: str = "not_started"
6
- InProgress: str = "in_progress"
7
- Paused: str = "paused"
8
- Failed: str = "failed"
9
- Cancelled: str = "cancelled"
10
- Successful: str = "successful"
11
- PartiallySuccessful: str = "partially_successful"
12
-
13
-
14
- class StepStatus(str, Enum):
15
- NotStarted: str = "not_started"
16
- Successful: str = "successful"
17
- InProgress: str = "in_progress"
18
- Failed: str = "failed"
19
- Cancelled: str = "cancelled"
5
+ NotStarted = "not_started"
6
+ InProgress = "in_progress"
7
+ Paused = "paused"
8
+ Failed = "failed"
9
+ Cancelled = "cancelled"
10
+ Successful = "successful"
11
+ PartiallySuccessful = "partially_successful"
20
12
 
21
13
 
22
14
  class TaskStatus(str, Enum):
23
- NotStarted: str = "not_started"
24
- InProgress: str = "in_progress"
25
- Paused: str = "paused"
26
- Failed: str = "failed"
27
- Cancelled: str = "cancelled"
28
- Successful: str = "successful"
29
- PartiallySuccessful: str = "partially_successful"
15
+ NotStarted = "not_started"
16
+ InProgress = "in_progress"
17
+ Paused = "paused"
18
+ Failed = "failed"
19
+ Cancelled = "cancelled"
20
+ Successful = "successful"
21
+ PartiallySuccessful = "partially_successful"
30
22
 
31
23
 
32
24
  class RobotStatus(Enum):
33
- Available: str = "available"
34
- Busy: str = "busy"
35
- Offline: str = "offline"
36
- Blocked: str = "blocked"
25
+ Available = "available"
26
+ Paused = "paused"
27
+ Busy = "busy"
28
+ Home = "home"
29
+ Offline = "offline"
30
+ BlockedProtectiveStop = "blockedprotectivestop"
@@ -1,127 +1,160 @@
1
- from dataclasses import dataclass, field
2
- from typing import Iterator, List, Optional
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
3
6
 
4
7
  from robot_interface.models.exceptions.robot_exceptions import ErrorMessage
5
- from robot_interface.models.mission.status import StepStatus, TaskStatus
6
- from robot_interface.models.mission.step import (
7
- STEPS,
8
- DriveToPose,
9
- InspectionStep,
10
- MotionStep,
11
- Step,
8
+ from robot_interface.models.inspection.inspection import (
9
+ Audio,
10
+ CO2Measurement,
11
+ Image,
12
+ Inspection,
13
+ ThermalImage,
14
+ ThermalVideo,
15
+ Video,
12
16
  )
17
+ from robot_interface.models.mission.status import TaskStatus
13
18
  from robot_interface.utilities.uuid_string_factory import uuid4_string
14
19
 
15
20
 
16
- @dataclass
17
- class Task:
18
- steps: List[STEPS]
19
- status: TaskStatus = field(default=TaskStatus.NotStarted, init=False)
20
- error_message: Optional[ErrorMessage] = field(default=None, init=False)
21
- tag_id: Optional[str] = field(default=None)
22
- id: str = field(default_factory=uuid4_string, init=True)
23
- _iterator: Iterator = None
24
-
25
- def next_step(self) -> Step:
26
- step: Step = next(self._iterator)
27
- while step.status != StepStatus.NotStarted:
28
- step = next(self._iterator)
29
- return step
30
-
31
- def is_finished(self) -> bool:
32
- for step in self.steps:
33
- if step.status is StepStatus.Failed and isinstance(step, MotionStep):
34
- # One motion step has failed meaning the task as a whole should be
35
- # considered as failed
36
- return True
37
-
38
- elif (step.status is StepStatus.Failed) and isinstance(
39
- step, InspectionStep
40
- ):
41
- # It should be possible to perform several inspections per task. If
42
- # one out of many inspections fail the task is considered as
43
- # partially successful.
44
- continue
45
-
46
- elif step.status is StepStatus.Successful:
47
- # The task is complete once all steps are completed
48
- continue
49
- else:
50
- # Not all steps have been completed yet
51
- return False
52
-
53
- return True
54
-
55
- def update_task_status(self) -> None:
56
- some_not_started: bool = False
57
- for step in self.steps:
58
- if step.status is StepStatus.Failed and isinstance(step, MotionStep):
59
- self.error_message = ErrorMessage(
60
- error_reason=None,
61
- error_description=f"Inspection "
62
- f"{'of ' + self.tag_id if self.tag_id else ''}failed because the "
63
- f"robot could not navigate to the desired location",
64
- )
65
- self.status = TaskStatus.Failed
66
- return
67
-
68
- elif (step.status is StepStatus.Failed) and isinstance(
69
- step, InspectionStep
70
- ):
71
- self.error_message = ErrorMessage(
72
- error_reason=None,
73
- error_description=f"Inspection "
74
- f"{'of ' + self.tag_id if self.tag_id else ''}was partially "
75
- f"successful because one or more inspection steps failed",
76
- )
77
- self.status = TaskStatus.PartiallySuccessful
78
- continue
79
-
80
- elif step.status is StepStatus.Successful:
81
- continue
82
-
83
- elif (step.status is StepStatus.NotStarted) and isinstance(
84
- step, InspectionStep
85
- ):
86
- some_not_started = True
87
-
88
- if self.status is not TaskStatus.PartiallySuccessful:
89
- if some_not_started:
90
- self.status = TaskStatus.InProgress # TODO: handle all not_started
91
- else:
92
- self.status = TaskStatus.Successful
93
-
94
- elif self._all_inspection_steps_failed():
95
- self.error_message = ErrorMessage(
96
- error_reason=None,
97
- error_description=f"Inspection "
98
- f"{'of ' + self.tag_id if self.tag_id else ''}failed as all inspection "
99
- f"steps failed",
100
- )
101
- self.status = TaskStatus.Failed
102
-
103
- def reset_task(self):
104
- self.error_message = None
105
- for step in self.steps:
106
- step.error_message = None
107
- if isinstance(step, DriveToPose):
108
- step.status = StepStatus.NotStarted
109
- elif (
110
- isinstance(step, InspectionStep)
111
- and step.status == StepStatus.InProgress
112
- ):
113
- step.status = StepStatus.NotStarted
114
- self._iterator = iter(self.steps)
115
-
116
- def _all_inspection_steps_failed(self) -> bool:
117
- for step in self.steps:
118
- if isinstance(step, MotionStep):
119
- continue
120
- elif step.status is not StepStatus.Failed:
121
- return False
122
-
123
- return True
124
-
125
- def __post_init__(self) -> None:
126
- if self._iterator is None:
127
- 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"