isar 1.16.17__py3-none-any.whl → 1.16.18__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.

isar/config/settings.env CHANGED
@@ -14,7 +14,7 @@ ISAR_MQTT_SSL_ENABLED = true
14
14
 
15
15
  ISAR_AUTHENTICATION_ENABLED = false
16
16
 
17
- ISAR_PLANT_SHORT_NAME = KAA
17
+ ISAR_PLANT_SHORT_NAME = HUA
18
18
 
19
19
  ISAR_API_HOST_VIEWED_EXTERNALLY = 0.0.0.0
20
20
 
@@ -24,6 +24,7 @@ class RobotInfoPublisher:
24
24
  video_streams=settings.VIDEO_STREAMS,
25
25
  host=settings.API_HOST_VIEWED_EXTERNALLY,
26
26
  port=settings.API_PORT,
27
+ capabilities=robot_settings.CAPABILITIES,
27
28
  timestamp=datetime.utcnow(),
28
29
  )
29
30
 
@@ -1,7 +1,6 @@
1
1
  import json
2
2
  import logging
3
3
  import queue
4
- import time
5
4
  from collections import deque
6
5
  from datetime import datetime
7
6
  from typing import Deque, List, Optional
@@ -226,18 +225,13 @@ class StateMachine(object):
226
225
  def _initiated(self) -> None:
227
226
  if self.stepwise_mission:
228
227
  self.current_step.status = StepStatus.InProgress
229
- self.publish_step_status(step=self.current_step)
230
- self.logger.info(
231
- f"Successfully initiated "
232
- f"{type(self.current_step).__name__} "
233
- f"step: {str(self.current_step.id)[:8]}"
234
- )
235
- else:
236
- self.current_mission.status = MissionStatus.InProgress
237
- self.logger.info(
238
- f"Successfully initiated full mission with ID: "
239
- f"{str(self.current_mission.id)[:8]}"
240
- )
228
+ self.current_mission.status = MissionStatus.InProgress
229
+ self.publish_step_status(step=self.current_step)
230
+ self.logger.info(
231
+ f"Successfully initiated "
232
+ f"{type(self.current_step).__name__} "
233
+ f"step: {str(self.current_step.id)[:8]}"
234
+ )
241
235
 
242
236
  def _pause(self) -> None:
243
237
  return
@@ -269,7 +263,9 @@ class StateMachine(object):
269
263
  ]
270
264
  partially_fail_statuses = fail_statuses + [TaskStatus.PartiallySuccessful]
271
265
 
272
- if all(task.status in fail_statuses for task in self.current_mission.tasks):
266
+ if len(self.current_mission.tasks) == 0:
267
+ self.current_mission.status = MissionStatus.Successful
268
+ elif all(task.status in fail_statuses for task in self.current_mission.tasks):
273
269
  self.current_mission.error_message = ErrorMessage(
274
270
  error_reason=None,
275
271
  error_description="The mission failed because all tasks in the mission "
@@ -296,9 +292,12 @@ class StateMachine(object):
296
292
  self.current_mission.status = MissionStatus.InProgress
297
293
  self.publish_mission_status()
298
294
  self.current_task = self.task_selector.next_task()
299
- self.current_task.status = TaskStatus.InProgress
300
- self.publish_task_status(task=self.current_task)
301
- self.update_current_step()
295
+ if self.current_task == None:
296
+ self._mission_finished()
297
+ else:
298
+ self.current_task.status = TaskStatus.InProgress
299
+ self.publish_task_status(task=self.current_task)
300
+ self.update_current_step()
302
301
 
303
302
  def _step_finished(self) -> None:
304
303
  self.publish_step_status(step=self.current_step)
@@ -307,28 +306,6 @@ class StateMachine(object):
307
306
 
308
307
  def _full_mission_finished(self) -> None:
309
308
  self.current_task = None
310
- step_status: StepStatus = StepStatus.Failed
311
- task_status: TaskStatus = TaskStatus.Failed
312
-
313
- if self.current_mission.status == MissionStatus.Failed:
314
- step_status = StepStatus.Failed
315
- task_status = TaskStatus.Failed
316
- elif self.current_mission.status == MissionStatus.Cancelled:
317
- step_status = StepStatus.Cancelled
318
- task_status = TaskStatus.Cancelled
319
- elif (
320
- self.current_mission.status == MissionStatus.Successful
321
- or self.current_mission.status == MissionStatus.PartiallySuccessful
322
- ):
323
- step_status = StepStatus.Successful
324
- task_status = TaskStatus.Successful
325
-
326
- for task in self.current_mission.tasks:
327
- task.status = task_status
328
- for step in task.steps:
329
- step.status = step_status
330
- self.publish_step_status(step=step)
331
- self.publish_task_status(task=task)
332
309
 
333
310
  def _mission_paused(self) -> None:
334
311
  self.logger.info(f"Pausing mission: {self.current_mission.id}")
@@ -349,26 +326,12 @@ class StateMachine(object):
349
326
  self.stopped = True
350
327
 
351
328
  def _initiate_failed(self) -> None:
352
- if self.stepwise_mission:
353
- self.current_step.status = StepStatus.Failed
354
- self.current_task.update_task_status()
355
- self.current_mission.status = MissionStatus.Failed
356
- self.publish_step_status(step=self.current_step)
357
- self.publish_task_status(task=self.current_task)
358
- self._finalize()
359
-
360
- else:
361
- self.current_task = None
362
- step_status: StepStatus = StepStatus.Cancelled
363
- task_status: TaskStatus = TaskStatus.Cancelled
364
-
365
- for task in self.current_mission.tasks:
366
- task.status = task_status
367
- for step in task.steps:
368
- step.status = step_status
369
- self.publish_step_status(step=step)
370
- self.publish_task_status(task=task)
371
- self._finalize()
329
+ self.current_step.status = StepStatus.Failed
330
+ self.current_task.update_task_status()
331
+ self.current_mission.status = MissionStatus.Failed
332
+ self.publish_step_status(step=self.current_step)
333
+ self.publish_task_status(task=self.current_task)
334
+ self._finalize()
372
335
 
373
336
  def _initiate_infeasible(self) -> None:
374
337
  if self.stepwise_mission:
@@ -435,9 +398,19 @@ class StateMachine(object):
435
398
  self.current_task = None
436
399
 
437
400
  def update_current_step(self):
438
- if self.current_task:
401
+ if self.current_task != None:
439
402
  self.current_step = self.current_task.next_step()
440
403
 
404
+ def update_remaining_steps(self):
405
+ if self.current_task:
406
+ for step in self.current_task.steps:
407
+ if (
408
+ step.status == StepStatus.InProgress
409
+ or step.status == StepStatus.NotStarted
410
+ ):
411
+ step.status = self.current_task.status
412
+ self.publish_step_status(step=step)
413
+
441
414
  def update_state(self):
442
415
  """Updates the current state of the state machine."""
443
416
  self.current_state = States(self.state)
@@ -6,6 +6,7 @@ from typing import Callable, Optional, Sequence, TYPE_CHECKING, Tuple, Union
6
6
  from injector import inject
7
7
  from transitions import State
8
8
 
9
+ from isar.mission_planner.task_selector_interface import TaskSelectorStop
9
10
  from isar.services.utilities.threaded_request import (
10
11
  ThreadedRequest,
11
12
  ThreadedRequestNotFinishedError,
@@ -19,7 +20,7 @@ from robot_interface.models.exceptions.robot_exceptions import (
19
20
  )
20
21
  from robot_interface.models.inspection.inspection import Inspection
21
22
  from robot_interface.models.mission.mission import Mission
22
- from robot_interface.models.mission.status import MissionStatus
23
+ from robot_interface.models.mission.status import MissionStatus, TaskStatus
23
24
  from robot_interface.models.mission.step import InspectionStep, Step, StepStatus
24
25
 
25
26
  if TYPE_CHECKING:
@@ -56,16 +57,10 @@ class Monitor(State):
56
57
  break
57
58
 
58
59
  if not self.step_status_thread:
59
- if self.state_machine.stepwise_mission:
60
- self._run_get_status_thread(
61
- status_function=self.state_machine.robot.step_status,
62
- thread_name="State Machine Monitor Get Step Status",
63
- )
64
- else:
65
- self._run_get_status_thread(
66
- status_function=self.state_machine.robot.mission_status,
67
- thread_name="State Machine Monitor Get Mission Status",
68
- )
60
+ self._run_get_status_thread(
61
+ status_function=self.state_machine.robot.step_status,
62
+ thread_name="State Machine Monitor Get Step Status",
63
+ )
69
64
 
70
65
  try:
71
66
  status: Union[StepStatus, MissionStatus] = (
@@ -97,19 +92,19 @@ class Monitor(State):
97
92
 
98
93
  except RobotException as e:
99
94
  self._set_error_message(e)
100
- if self.state_machine.stepwise_mission:
101
- status = StepStatus.Failed
102
- else:
103
- status = MissionStatus.Failed
95
+ status = StepStatus.Failed
104
96
 
105
97
  self.logger.error(
106
98
  f"Retrieving the status failed because: {e.error_description}"
107
99
  )
108
100
 
109
- if self.state_machine.stepwise_mission and isinstance(status, StepStatus):
101
+ if isinstance(status, StepStatus):
110
102
  self.state_machine.current_step.status = status
111
103
  elif isinstance(status, MissionStatus):
112
104
  self.state_machine.current_mission.status = status
105
+ self.logger.error(
106
+ f"Received an invalid status update when monitoring mission. Only StepStatus is expected."
107
+ )
113
108
 
114
109
  if self._should_upload_inspections():
115
110
  get_inspections_thread = ThreadedRequest(
@@ -126,7 +121,28 @@ class Monitor(State):
126
121
  transition = self.state_machine.step_finished # type: ignore
127
122
  break
128
123
  else:
129
- if self._mission_finished(self.state_machine.current_mission):
124
+ if isinstance(status, StepStatus):
125
+ if self._step_finished(self.state_machine.current_step):
126
+ self.state_machine.current_task.update_task_status()
127
+ else: # If not all steps are done
128
+ self.state_machine.current_task.status = TaskStatus.InProgress
129
+
130
+ self.state_machine.publish_task_status(
131
+ self.state_machine.current_task
132
+ )
133
+ if self.state_machine.current_task.status == TaskStatus.Successful:
134
+ self.state_machine.update_remaining_steps()
135
+ try:
136
+ self.state_machine.current_task = (
137
+ self.state_machine.task_selector.next_task()
138
+ )
139
+ except TaskSelectorStop:
140
+ # Indicates that all tasks are finished
141
+ self.state_machine.current_task = None
142
+ transition = self.state_machine.full_mission_finished # type: ignore
143
+ break
144
+ self.state_machine.update_current_step()
145
+ elif self._mission_finished(self.state_machine.current_mission):
130
146
  transition = self.state_machine.full_mission_finished # type: ignore
131
147
  break
132
148
 
@@ -196,28 +212,15 @@ class Monitor(State):
196
212
  return False
197
213
 
198
214
  def _should_upload_inspections(self) -> bool:
199
- if self.state_machine.stepwise_mission:
200
- step: Step = self.state_machine.current_step
201
- return (
202
- self._step_finished(step)
203
- and step.status == StepStatus.Successful
204
- and isinstance(step, InspectionStep)
205
- )
206
- else:
207
- mission_status: MissionStatus = self.state_machine.current_mission.status
208
- if (
209
- mission_status == MissionStatus.Successful
210
- or mission_status == MissionStatus.PartiallySuccessful
211
- ):
212
- return True
213
- return False
215
+ step: Step = self.state_machine.current_step
216
+ return (
217
+ self._step_finished(step)
218
+ and step.status == StepStatus.Successful
219
+ and isinstance(step, InspectionStep)
220
+ )
214
221
 
215
222
  def _set_error_message(self, e: RobotException) -> None:
216
223
  error_message: ErrorMessage = ErrorMessage(
217
224
  error_reason=e.error_reason, error_description=e.error_description
218
225
  )
219
- if self.state_machine.stepwise_mission:
220
- self.state_machine.current_step.error_message = error_message
221
- else:
222
- if self.state_machine.current_mission:
223
- self.state_machine.current_mission.error_message = error_message
226
+ self.state_machine.current_step.error_message = error_message
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: isar
3
- Version: 1.16.17
3
+ Version: 1.16.18
4
4
  Summary: Integration and Supervisory control of Autonomous Robots
5
5
  Home-page: https://github.com/equinor/isar
6
6
  Author: Equinor ASA
@@ -13,7 +13,7 @@ isar/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  isar/config/configuration_error.py,sha256=rO6WOhafX6xvVib8WxV-eY483Z0PpN-9PxGsq5ATfKc,46
14
14
  isar/config/log.py,sha256=39G_Cue0qvw0Uv-1NYXvQ83yivPIKcAv-bGNNREFw5o,2251
15
15
  isar/config/logging.conf,sha256=mYO1xf27gAopEMHhGzY7-mwyfN16rwRLkPNMvy3zn2g,1127
16
- isar/config/settings.env,sha256=-RCBJiVRWBLky7FKuQX1qYXy8rCzTNLM4LDuyp12EbY,535
16
+ isar/config/settings.env,sha256=-kivj0osAAKlInnY81ugySTlcImhVABbnj9kUoBDLu8,535
17
17
  isar/config/settings.py,sha256=ZECul4dywwZb-hJeWi-4XfjrUjthqMs42bNfsyI7feA,13056
18
18
  isar/config/certs/ca-cert.pem,sha256=gSBTyY0tKSFnssyvrvbFvHpQwii0kEkBryklVmevdtc,2029
19
19
  isar/config/keyvault/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -59,7 +59,7 @@ isar/services/service_connections/request_handler.py,sha256=0LxC0lu_HXeEf_xmJWjf
59
59
  isar/services/service_connections/mqtt/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
60
60
  isar/services/service_connections/mqtt/mqtt_client.py,sha256=Aib0lqaddxW9aVXXYD7wGL9jIpr2USCCH91SQgFdIG4,3548
61
61
  isar/services/service_connections/mqtt/robot_heartbeat_publisher.py,sha256=TxvpLA_qfyXwwN58h2X-eomTnhbFPhqfjamPxBz084E,1000
62
- isar/services/service_connections/mqtt/robot_info_publisher.py,sha256=_7lXSyOaTbde584M67bG7N9sQJH51yhaSuhsjuCM02U,1325
62
+ isar/services/service_connections/mqtt/robot_info_publisher.py,sha256=d5HQ6Hfp5E21kaj1IJsFMWXecbzvH8iYByZhOucR004,1383
63
63
  isar/services/service_connections/mqtt/robot_status_publisher.py,sha256=KPxRrdtu-yLQolQ7DejC1v1NCeELUzrK_ZoiEpsrqD4,4425
64
64
  isar/services/service_connections/stid/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
65
65
  isar/services/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -67,13 +67,13 @@ isar/services/utilities/queue_utilities.py,sha256=Pw3hehSwkXJNeDv-bDVDfs58VOwtt3
67
67
  isar/services/utilities/scheduling_utilities.py,sha256=LFimEmacML3J9q-FNLfKPhcAr-R3f2rkYkbsoro0Gyo,8434
68
68
  isar/services/utilities/threaded_request.py,sha256=py4G-_RjnIdHljmKFAcQ6ddqMmp-ZYV39Ece-dqRqjs,1874
69
69
  isar/state_machine/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
70
- isar/state_machine/state_machine.py,sha256=HXH9XuXRUfhKZQdp5IfwV-Do-QRRConpyiUBFl_p-mU,23707
70
+ isar/state_machine/state_machine.py,sha256=yud8FODucCFLVkK1E4NfKZ5YCrFb8IRfk752Nn_WTIY,22606
71
71
  isar/state_machine/states_enum.py,sha256=ks1A8gO7DOpLbSe6Vzq4-BfTCU78IsQZyoEJwQ9Wg4M,254
72
72
  isar/state_machine/states/__init__.py,sha256=gUikQDu-O-lmunwzwcN9gN6VaEmlCFlqqgdNfFAfXBc,189
73
73
  isar/state_machine/states/idle.py,sha256=tfciqI7NPDVF8WMe5qbSO3c-xDzUTQYLmJinb9e0JS8,1231
74
74
  isar/state_machine/states/initialize.py,sha256=Vx7OxWZI_xEkRwHWFh9ymxK_7mDH0Wayt09dGGqBJWk,2359
75
75
  isar/state_machine/states/initiate.py,sha256=b0Fq3tN6TZMg5j4192OsYdGbphTXWCkftBsFX57mhrw,5652
76
- isar/state_machine/states/monitor.py,sha256=2eYv2wUH0MLwxZCizBHIpigELPeou6KzCzW_JuEVlls,8612
76
+ isar/state_machine/states/monitor.py,sha256=ykVQe54Lm_V-X7kJ16GMkycG7T9Kz3g2hsPtL35NSSk,9004
77
77
  isar/state_machine/states/off.py,sha256=jjqN_oJMpBtWuY7hP-c9f0w3p2CYCfe-NpmYHHPnmyI,544
78
78
  isar/state_machine/states/paused.py,sha256=xVZM9WMt90FTiP5forSlA3eJ5Vt9LzZYCFDQDPIocKA,1004
79
79
  isar/state_machine/states/stop.py,sha256=Sxdo4FGhxc2Pj91jidYtVIjpSNklbEf1sJYJ6x51HgE,3348
@@ -102,13 +102,13 @@ robot_interface/models/mission/task.py,sha256=bjp-m_Ak6tzgUIQvbGe90Mnwt6QhofTgFx
102
102
  robot_interface/models/robots/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
103
103
  robot_interface/models/robots/robot_model.py,sha256=pZQsqhn9hh6XE3EjMZhWMzYqg5oJ4CJ4CXeOASKvEf8,452
104
104
  robot_interface/telemetry/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
105
- robot_interface/telemetry/mqtt_client.py,sha256=56i_jCfg2CMe5fwefKxwW4GSpWvrDXo6Zwb7vBGTZ6k,2297
106
- robot_interface/telemetry/payloads.py,sha256=9EshERifjD1u8CwjSiV3NGuj0KuXnwblQNBsEWCh5c4,1336
105
+ robot_interface/telemetry/mqtt_client.py,sha256=p82lvfCqLyBHQ2n4jhWGRNb0RktAn4ptL8FZkASGGl4,2753
106
+ robot_interface/telemetry/payloads.py,sha256=eMK7mjZPsLY6yvu7AK-OcdvkeUpChzDrySDY7IjQ9RM,1464
107
107
  robot_interface/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
108
108
  robot_interface/utilities/json_service.py,sha256=nU2Q_3P9Fq9hs6F_wtUjWtHfl_g1Siy-yDhXXSKwHwg,1018
109
109
  robot_interface/utilities/uuid_string_factory.py,sha256=_NQIbBQ56w0qqO0MUDP6aPpHbxW7ATRhK8HnQiBSLkc,76
110
- isar-1.16.17.dist-info/LICENSE,sha256=3fc2-ebLwHWwzfQbulGNRdcNob3SBQeCfEVUDYxsuqw,14058
111
- isar-1.16.17.dist-info/METADATA,sha256=50txXV96ijDaWa6NcBmtj4tsfH3WohQJfoUPuv0F9PQ,14752
112
- isar-1.16.17.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
113
- isar-1.16.17.dist-info/top_level.txt,sha256=UwIML2RtuQKCyJJkatcSnyp6-ldDjboB9k9JgKipO-U,21
114
- isar-1.16.17.dist-info/RECORD,,
110
+ isar-1.16.18.dist-info/LICENSE,sha256=3fc2-ebLwHWwzfQbulGNRdcNob3SBQeCfEVUDYxsuqw,14058
111
+ isar-1.16.18.dist-info/METADATA,sha256=kVSluDGtKWU_oYcDkJvO9cv6OLUmVWBLH5gwV8sseug,14752
112
+ isar-1.16.18.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
113
+ isar-1.16.18.dist-info/top_level.txt,sha256=UwIML2RtuQKCyJJkatcSnyp6-ldDjboB9k9JgKipO-U,21
114
+ isar-1.16.18.dist-info/RECORD,,
@@ -1,11 +1,15 @@
1
1
  import time
2
2
  from abc import ABCMeta, abstractmethod
3
3
  from queue import Queue
4
- from typing import Callable, Tuple
4
+ from typing import Callable, Tuple, Type
5
+ from datetime import datetime
6
+ import json
5
7
 
6
8
  from robot_interface.models.exceptions.robot_exceptions import (
7
9
  RobotTelemetryException,
8
10
  )
11
+ from robot_interface.telemetry.payloads import CloudHealthPayload
12
+ from robot_interface.utilities.json_service import EnhancedJSONEncoder
9
13
 
10
14
 
11
15
  class MqttClientInterface(metaclass=ABCMeta):
@@ -61,17 +65,23 @@ class MqttTelemetryPublisher(MqttClientInterface):
61
65
  self.retain: bool = retain
62
66
 
63
67
  def run(self, isar_id: str, robot_name: str) -> None:
68
+ self.cloud_healt_topic: str = f"isar/{isar_id}/cloud_health"
69
+ topic: str
70
+ payload: str
71
+
64
72
  while True:
65
73
  try:
66
- payload: str = self.telemetry_method(
67
- isar_id=isar_id, robot_name=robot_name
68
- )
74
+ payload = self.telemetry_method(isar_id=isar_id, robot_name=robot_name)
75
+ topic = self.topic
69
76
  except RobotTelemetryException:
70
- continue
77
+ payload = json.dumps(
78
+ CloudHealthPayload(isar_id, robot_name, datetime.utcnow()),
79
+ cls=EnhancedJSONEncoder,
80
+ )
81
+ topic = self.cloud_healt_topic
82
+
83
+ self.publish(topic=topic, payload=payload, qos=self.qos, retain=self.retain)
71
84
 
72
- self.publish(
73
- topic=self.topic, payload=payload, qos=self.qos, retain=self.retain
74
- )
75
85
  time.sleep(self.interval)
76
86
 
77
87
  def publish(
@@ -15,6 +15,13 @@ class TelemetryPayload:
15
15
  timestamp: datetime
16
16
 
17
17
 
18
+ @dataclass
19
+ class CloudHealthPayload:
20
+ isar_id: str
21
+ robot_name: str
22
+ timestamp: datetime
23
+
24
+
18
25
  @dataclass
19
26
  class TelemetryPosePayload(TelemetryPayload):
20
27
  pose: Pose
@@ -65,6 +72,7 @@ class RobotInfoPayload:
65
72
  video_streams: List[VideoStream]
66
73
  host: str
67
74
  port: int
75
+ capabilities: List[str]
68
76
  timestamp: datetime
69
77
 
70
78
 
File without changes