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,15 +1,38 @@
1
+ import json
1
2
  import time
2
3
  from abc import ABCMeta, abstractmethod
4
+ from datetime import datetime, timezone
3
5
  from queue import Queue
4
6
  from typing import Callable, Tuple
5
7
 
6
- from robot_interface.models.exceptions import RobotException
8
+ from paho.mqtt.packettypes import PacketTypes
9
+ from paho.mqtt.properties import Properties
10
+
11
+ from isar.config.settings import settings
12
+ from robot_interface.models.exceptions.robot_exceptions import (
13
+ RobotTelemetryException,
14
+ RobotTelemetryNoUpdateException,
15
+ RobotTelemetryPoseException,
16
+ )
17
+ from robot_interface.telemetry.payloads import CloudHealthPayload
18
+ from robot_interface.utilities.json_service import EnhancedJSONEncoder
19
+
20
+
21
+ def props_expiry(seconds: int) -> Properties:
22
+ p = Properties(PacketTypes.PUBLISH)
23
+ p.MessageExpiryInterval = seconds
24
+ return p
7
25
 
8
26
 
9
27
  class MqttClientInterface(metaclass=ABCMeta):
10
28
  @abstractmethod
11
29
  def publish(
12
- self, topic: str, payload: str, qos: int = 0, retain: bool = False
30
+ self,
31
+ topic: str,
32
+ payload: str,
33
+ qos: int = 0,
34
+ retain: bool = False,
35
+ properties: Properties = None,
13
36
  ) -> None:
14
37
  """
15
38
  Parameters
@@ -25,7 +48,6 @@ class MqttClientInterface(metaclass=ABCMeta):
25
48
 
26
49
  Returns
27
50
  -------
28
-
29
51
  """
30
52
  pass
31
53
 
@@ -35,9 +57,20 @@ class MqttPublisher(MqttClientInterface):
35
57
  self.mqtt_queue: Queue = mqtt_queue
36
58
 
37
59
  def publish(
38
- self, topic: str, payload: str, qos: int = 0, retain: bool = False
60
+ self,
61
+ topic: str,
62
+ payload: str,
63
+ qos: int = 0,
64
+ retain: bool = False,
65
+ properties: Properties = None,
39
66
  ) -> None:
40
- queue_message: Tuple[str, str, int, bool] = (topic, payload, qos, retain)
67
+ queue_message: Tuple[str, str, int, bool, Properties] = (
68
+ topic,
69
+ payload,
70
+ qos,
71
+ retain,
72
+ properties,
73
+ )
41
74
  self.mqtt_queue.put(queue_message)
42
75
 
43
76
 
@@ -50,6 +83,7 @@ class MqttTelemetryPublisher(MqttClientInterface):
50
83
  interval: float,
51
84
  qos: int = 0,
52
85
  retain: bool = False,
86
+ properties: Properties = None,
53
87
  ) -> None:
54
88
  self.mqtt_queue: Queue = mqtt_queue
55
89
  self.telemetry_method: Callable = telemetry_method
@@ -57,23 +91,61 @@ class MqttTelemetryPublisher(MqttClientInterface):
57
91
  self.interval: float = interval
58
92
  self.qos: int = qos
59
93
  self.retain: bool = retain
94
+ self.properties: Properties = properties
60
95
 
61
96
  def run(self, isar_id: str, robot_name: str) -> None:
97
+ self.cloud_health_topic: str = f"isar/{isar_id}/cloud_health"
98
+ self.battery_topic: str = f"isar/{isar_id}/battery"
99
+ self.pose_topic: str = f"isar/{isar_id}/pose"
100
+ self.pressure_topic: str = f"isar/{isar_id}/pressure"
101
+ topic: str
102
+ payload: str
103
+
62
104
  while True:
63
105
  try:
64
- payload: str = self.telemetry_method(
65
- isar_id=isar_id, robot_name=robot_name
66
- )
67
- except RobotException:
106
+ payload = self.telemetry_method(isar_id=isar_id, robot_name=robot_name)
107
+ topic = self.topic
108
+ except (RobotTelemetryPoseException, RobotTelemetryNoUpdateException):
109
+ time.sleep(self.interval)
68
110
  continue
111
+ except RobotTelemetryException:
112
+ payload = json.dumps(
113
+ CloudHealthPayload(isar_id, robot_name, datetime.now(timezone.utc)),
114
+ cls=EnhancedJSONEncoder,
115
+ )
116
+ topic = self.cloud_health_topic
117
+
118
+ publish_properties = self.properties
119
+
120
+ if topic in (
121
+ self.battery_topic,
122
+ self.pose_topic,
123
+ self.pressure_topic,
124
+ ):
125
+ publish_properties = props_expiry(settings.MQTT_TELEMETRY_EXPIRY)
69
126
 
70
127
  self.publish(
71
- topic=self.topic, payload=payload, qos=self.qos, retain=self.retain
128
+ topic=topic,
129
+ payload=payload,
130
+ qos=self.qos,
131
+ retain=self.retain,
132
+ properties=publish_properties,
72
133
  )
73
134
  time.sleep(self.interval)
74
135
 
75
136
  def publish(
76
- self, topic: str, payload: str, qos: int = 0, retain: bool = False
137
+ self,
138
+ topic: str,
139
+ payload: str,
140
+ qos: int = 0,
141
+ retain: bool = False,
142
+ properties: Properties = None,
77
143
  ) -> None:
78
- queue_message: Tuple[str, str, int, bool] = (topic, payload, qos, retain)
144
+ queue_message: Tuple[str, str, int, bool, Properties] = (
145
+ topic,
146
+ payload,
147
+ qos,
148
+ retain,
149
+ properties,
150
+ )
79
151
  self.mqtt_queue.put(queue_message)
@@ -1,11 +1,15 @@
1
1
  from dataclasses import dataclass
2
2
  from datetime import datetime
3
- from typing import List
3
+ from typing import List, Optional
4
4
 
5
5
  from alitra import Pose
6
- from transitions import State
7
6
 
8
- from robot_interface.models.mission.status import RobotStatus
7
+ from isar.models.status import IsarStatus
8
+ from isar.storage.storage_interface import BlobStoragePath
9
+ from robot_interface.models.exceptions.robot_exceptions import ErrorReason
10
+ from robot_interface.models.mission.status import MissionStatus, TaskStatus
11
+ from robot_interface.models.mission.task import TaskTypes
12
+ from robot_interface.models.robots.battery_state import BatteryState
9
13
 
10
14
 
11
15
  @dataclass
@@ -15,6 +19,13 @@ class TelemetryPayload:
15
19
  timestamp: datetime
16
20
 
17
21
 
22
+ @dataclass
23
+ class CloudHealthPayload:
24
+ isar_id: str
25
+ robot_name: str
26
+ timestamp: datetime
27
+
28
+
18
29
  @dataclass
19
30
  class TelemetryPosePayload(TelemetryPayload):
20
31
  pose: Pose
@@ -23,6 +34,12 @@ class TelemetryPosePayload(TelemetryPayload):
23
34
  @dataclass
24
35
  class TelemetryBatteryPayload(TelemetryPayload):
25
36
  battery_level: float
37
+ battery_state: Optional[BatteryState] = None
38
+
39
+
40
+ @dataclass
41
+ class TelemetryObstacleStatusPayload(TelemetryPayload):
42
+ obstacle_status: bool
26
43
 
27
44
 
28
45
  @dataclass
@@ -31,21 +48,16 @@ class TelemetryPressurePayload(TelemetryPayload):
31
48
 
32
49
 
33
50
  @dataclass
34
- class VideoStream:
51
+ class DocumentInfo:
35
52
  name: str
36
53
  url: str
37
- type: str
38
54
 
39
55
 
40
56
  @dataclass
41
- class RobotStatusPayload:
57
+ class IsarStatusPayload:
42
58
  isar_id: str
43
59
  robot_name: str
44
- robot_status: RobotStatus
45
- current_isar_state: State
46
- current_mission_id: str
47
- current_task_id: str
48
- current_step_id: str
60
+ status: IsarStatus
49
61
  timestamp: datetime
50
62
 
51
63
 
@@ -56,7 +68,94 @@ class RobotInfoPayload:
56
68
  robot_model: str
57
69
  robot_serial_number: str
58
70
  robot_asset: str
59
- video_streams: List[VideoStream]
71
+ documentation: List[DocumentInfo]
60
72
  host: str
61
73
  port: int
74
+ capabilities: List[str]
75
+ timestamp: datetime
76
+
77
+
78
+ @dataclass
79
+ class RobotHeartbeatPayload:
80
+ isar_id: str
81
+ robot_name: str
82
+ timestamp: datetime
83
+
84
+
85
+ @dataclass
86
+ class MissionPayload:
87
+ isar_id: str
88
+ robot_name: str
89
+ mission_id: Optional[str]
90
+ status: Optional[MissionStatus]
91
+ error_reason: Optional[ErrorReason]
92
+ error_description: Optional[str]
93
+ timestamp: datetime
94
+
95
+
96
+ @dataclass
97
+ class MissionAbortedPayload:
98
+ isar_id: str
99
+ robot_name: str
100
+ mission_id: str
101
+ can_be_continued: bool
102
+ timestamp: datetime
103
+ reason: Optional[str]
104
+
105
+
106
+ @dataclass
107
+ class TaskPayload:
108
+ isar_id: str
109
+ robot_name: str
110
+ mission_id: Optional[str]
111
+ task_id: Optional[str]
112
+ status: Optional[TaskStatus]
113
+ task_type: Optional[TaskTypes]
114
+ error_reason: Optional[ErrorReason]
115
+ error_description: Optional[str]
116
+ timestamp: datetime
117
+
118
+
119
+ @dataclass
120
+ class InspectionResultPayload:
121
+ isar_id: str
122
+ robot_name: str
123
+ inspection_id: str
124
+ blob_storage_data_path: BlobStoragePath
125
+ blob_storage_metadata_path: BlobStoragePath
126
+ installation_code: str
127
+ tag_id: Optional[str]
128
+ inspection_type: Optional[str]
129
+ inspection_description: Optional[str]
130
+ timestamp: datetime
131
+
132
+
133
+ @dataclass
134
+ class InspectionValuePayload:
135
+ isar_id: str
136
+ robot_name: str
137
+ inspection_id: str
138
+ installation_code: str
139
+ tag_id: Optional[str]
140
+ inspection_type: Optional[str]
141
+ inspection_description: Optional[str]
142
+ value: float
143
+ unit: str
144
+ x: float
145
+ y: float
146
+ z: float
147
+ timestamp: datetime
148
+
149
+
150
+ @dataclass
151
+ class StartUpMessagePayload:
152
+ isar_id: str
153
+ timestamp: datetime
154
+
155
+
156
+ @dataclass
157
+ class InterventionNeededPayload:
158
+ isar_id: str
159
+ robot_name: str
160
+ reason: str
62
161
  timestamp: datetime
@@ -7,6 +7,7 @@ from uuid import UUID
7
7
 
8
8
  import numpy as np
9
9
  from alitra import Orientation
10
+ from pydantic import BaseModel
10
11
 
11
12
 
12
13
  class EnhancedJSONEncoder(json.JSONEncoder):
@@ -15,8 +16,13 @@ class EnhancedJSONEncoder(json.JSONEncoder):
15
16
  """
16
17
 
17
18
  def default(self, o):
19
+ if isinstance(o, BaseModel):
20
+ dump = getattr(o, "model_dump", None)
21
+ if callable(dump):
22
+ return dump()
23
+ return o.__dict__
18
24
  if is_dataclass(o):
19
- return asdict(o)
25
+ return asdict(o) # type: ignore
20
26
  if isinstance(o, UUID):
21
27
  return str(o)
22
28
  if isinstance(o, Orientation):
@@ -1,110 +0,0 @@
1
- {
2
- "id": "2",
3
- "tasks": [
4
- {
5
- "steps": [
6
- {
7
- "type": "drive_to_pose",
8
- "pose": {
9
- "position": {
10
- "x": -3.6,
11
- "y": 4,
12
- "z": 0,
13
- "frame": "asset"
14
- },
15
- "orientation": {
16
- "x": 0,
17
- "y": 0,
18
- "z": -0.7286672256879113,
19
- "w": -0.6848660759820616,
20
- "frame": "asset"
21
- },
22
- "frame": "asset"
23
- }
24
- },
25
- {
26
- "type": "take_image",
27
- "target": {
28
- "x": -4.7,
29
- "y": 4.9,
30
- "z": 0,
31
- "frame": "robot"
32
- }
33
- }
34
- ]
35
- },
36
- {
37
- "steps": [
38
- {
39
- "type": "drive_to_pose",
40
- "pose": {
41
- "position": {
42
- "x": 4.7,
43
- "y": 3,
44
- "z": 0,
45
- "frame": "asset"
46
- },
47
- "orientation": {
48
- "x": 0,
49
- "y": 0,
50
- "z": 0.5769585,
51
- "w": 0.8167734,
52
- "frame": "asset"
53
- },
54
- "frame": "asset"
55
- }
56
- },
57
- {
58
- "type": "take_image",
59
- "target": {
60
- "x": 5.6,
61
- "y": 5.2,
62
- "z": 0,
63
- "frame": "robot"
64
- }
65
- },
66
- {
67
- "type": "take_thermal_image",
68
- "target": {
69
- "x": 3.1,
70
- "y": 5.2,
71
- "z": 0,
72
- "frame": "robot"
73
- }
74
- }
75
- ]
76
- },
77
- {
78
- "steps": [
79
- {
80
- "type": "drive_to_pose",
81
- "pose": {
82
- "position": {
83
- "x": 0.95,
84
- "y": 2.6,
85
- "z": 0,
86
- "frame": "asset"
87
- },
88
- "orientation": {
89
- "x": 0,
90
- "y": 0,
91
- "z": -0.6992469,
92
- "w": 0.7148802,
93
- "frame": "asset"
94
- },
95
- "frame": "asset"
96
- }
97
- },
98
- {
99
- "type": "take_thermal_image",
100
- "target": {
101
- "x": 1.9,
102
- "y": 1.9,
103
- "z": 0,
104
- "frame": "robot"
105
- }
106
- }
107
- ]
108
- }
109
- ]
110
- }
File without changes