isar 1.19.1__py3-none-any.whl → 1.20.2__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.
isar/__init__.py CHANGED
@@ -1,6 +1,3 @@
1
- from importlib.metadata import PackageNotFoundError, distribution
1
+ from importlib.metadata import version
2
2
 
3
- try:
4
- __version__ = distribution(__name__).version
5
- except PackageNotFoundError:
6
- pass # package is not installed
3
+ __version__ = version(__package__ or __name__)
@@ -2,7 +2,7 @@ import time
2
2
  from enum import Enum
3
3
  from typing import Any, Dict, List, Optional, Union
4
4
 
5
- from alitra import Position
5
+ from alitra import Position, Pose, Orientation, Frame
6
6
  from pydantic import BaseModel, Field
7
7
 
8
8
  from isar.apis.models.models import InputPose, InputPosition
@@ -61,6 +61,7 @@ class StartMissionDefinition(BaseModel):
61
61
  tasks: List[StartMissionTaskDefinition]
62
62
  id: Optional[str] = None
63
63
  name: Optional[str] = None
64
+ start_pose: Optional[InputPose] = None
64
65
 
65
66
 
66
67
  def to_isar_mission(mission_definition: StartMissionDefinition) -> Mission:
@@ -92,6 +93,26 @@ def to_isar_mission(mission_definition: StartMissionDefinition) -> Mission:
92
93
  if mission_definition.id:
93
94
  isar_mission.id = mission_definition.id
94
95
 
96
+ if mission_definition.start_pose:
97
+ input_pose: InputPose = mission_definition.start_pose
98
+ input_frame: Frame = Frame(name=input_pose.frame_name)
99
+ input_position: Position = Position(
100
+ input_pose.position.x,
101
+ input_pose.position.y,
102
+ input_pose.position.z,
103
+ input_frame,
104
+ )
105
+ input_orientation: Orientation = Orientation(
106
+ input_pose.orientation.x,
107
+ input_pose.orientation.y,
108
+ input_pose.orientation.z,
109
+ input_pose.orientation.w,
110
+ input_frame,
111
+ )
112
+ isar_mission.start_pose = Pose(
113
+ position=input_position, orientation=input_orientation, frame=input_frame
114
+ )
115
+
95
116
  return isar_mission
96
117
 
97
118
 
isar/script.py ADDED
@@ -0,0 +1,154 @@
1
+ import logging
2
+ import time
3
+ from logging import Logger
4
+ from threading import Thread
5
+ from typing import Any, List
6
+
7
+ from injector import Injector
8
+
9
+ import isar
10
+ from isar.apis.api import API
11
+ from isar.config.keyvault.keyvault_service import Keyvault
12
+ from isar.config.log import setup_loggers
13
+ from isar.config.settings import settings
14
+ from isar.models.communication.queues.queues import Queues
15
+ from isar.modules import get_injector
16
+ from isar.services.service_connections.mqtt.mqtt_client import MqttClient
17
+ from isar.services.service_connections.mqtt.robot_heartbeat_publisher import (
18
+ RobotHeartbeatPublisher,
19
+ )
20
+ from isar.services.service_connections.mqtt.robot_info_publisher import (
21
+ RobotInfoPublisher,
22
+ )
23
+ from isar.state_machine.state_machine import StateMachine, main
24
+ from isar.storage.uploader import Uploader
25
+ from robot_interface.robot_interface import RobotInterface
26
+
27
+
28
+ def print_setting(
29
+ setting: str = "", value: Any = "", fillchar: str = " ", width: int = 48
30
+ ):
31
+ separator = ": " if value != "" else ""
32
+ text = setting.ljust(22, fillchar) + separator + str(value)
33
+ print("*", text.ljust(width - 4, fillchar), "*")
34
+
35
+
36
+ def print_startup_info():
37
+ print(
38
+ """
39
+ __ ________ ___ ________
40
+ / / / ______/ / | / ____ /
41
+ / / / /_____ / /| | / /___/ /
42
+ / / /_____ / / __ | / __ __/
43
+ / / ______/ / / / | | / / | |
44
+ /_/ /_______/ /_/ |_| /_/ |_|
45
+
46
+ """
47
+ )
48
+
49
+ WIDTH = 48
50
+
51
+ def print_setting(setting: str = "", value: Any = "", fillchar: str = " "):
52
+ separator = ": " if value != "" else ""
53
+ text = setting.ljust(22, fillchar) + separator + str(value)
54
+ print("*", text.ljust(WIDTH - 4, fillchar), "*")
55
+
56
+ print("Integration and Supervisory control".center(WIDTH, " "))
57
+ print("of Autonomous Robots".center(WIDTH, " "))
58
+ print()
59
+ print(f"Version: {isar.__version__}\n".center(WIDTH, " "))
60
+
61
+ print_setting(fillchar="*")
62
+ print_setting("ISAR settings")
63
+ print_setting(fillchar="-")
64
+ print_setting("Robot package", settings.ROBOT_PACKAGE)
65
+ print_setting("Robot name", settings.ROBOT_NAME)
66
+ print_setting("Run mission stepwise", settings.RUN_MISSION_STEPWISE)
67
+ print_setting("Running on port", settings.API_PORT)
68
+ print_setting("Mission planner", settings.MISSION_PLANNER)
69
+ print_setting("Using local storage", settings.STORAGE_LOCAL_ENABLED)
70
+ print_setting("Using blob storage", settings.STORAGE_BLOB_ENABLED)
71
+ print_setting("Using SLIMM storage", settings.STORAGE_SLIMM_ENABLED)
72
+ print_setting("Plant code", settings.PLANT_CODE)
73
+ print_setting("Plant name", settings.PLANT_NAME)
74
+ print_setting("Plant shortname", settings.PLANT_SHORT_NAME)
75
+ print_setting(fillchar="*")
76
+ print()
77
+
78
+
79
+ def start():
80
+ injector: Injector = get_injector()
81
+
82
+ keyvault_client = injector.get(Keyvault)
83
+ setup_loggers(keyvault=keyvault_client)
84
+ logger: Logger = logging.getLogger("main")
85
+
86
+ print_startup_info()
87
+
88
+ state_machine: StateMachine = injector.get(StateMachine)
89
+ uploader: Uploader = injector.get(Uploader)
90
+ robot: RobotInterface = injector.get(RobotInterface)
91
+ queues: Queues = injector.get(Queues)
92
+
93
+ threads: List[Thread] = []
94
+
95
+ state_machine_thread: Thread = Thread(
96
+ target=main, name="ISAR State Machine", args=[state_machine], daemon=True
97
+ )
98
+ threads.append(state_machine_thread)
99
+
100
+ uploader_thread: Thread = Thread(
101
+ target=uploader.run, name="ISAR Uploader", daemon=True
102
+ )
103
+ threads.append(uploader_thread)
104
+ if settings.MQTT_ENABLED:
105
+ mqtt_client: MqttClient = MqttClient(mqtt_queue=queues.mqtt_queue)
106
+
107
+ mqtt_thread: Thread = Thread(
108
+ target=mqtt_client.run, name="ISAR MQTT Client", daemon=True
109
+ )
110
+ threads.append(mqtt_thread)
111
+
112
+ robot_info_publisher: RobotInfoPublisher = RobotInfoPublisher(
113
+ mqtt_queue=queues.mqtt_queue
114
+ )
115
+ robot_info_thread: Thread = Thread(
116
+ target=robot_info_publisher.run,
117
+ name="ISAR Robot Info Publisher",
118
+ daemon=True,
119
+ )
120
+ threads.append(robot_info_thread)
121
+
122
+ robot_heartbeat_publisher: RobotHeartbeatPublisher = RobotHeartbeatPublisher(
123
+ mqtt_queue=queues.mqtt_queue
124
+ )
125
+
126
+ robot_heartbeat_thread: Thread = Thread(
127
+ target=robot_heartbeat_publisher.run,
128
+ name="ISAR Robot Heartbeat Publisher",
129
+ daemon=True,
130
+ )
131
+ threads.append(robot_heartbeat_thread)
132
+
133
+ publishers: List[Thread] = robot.get_telemetry_publishers(
134
+ queue=queues.mqtt_queue,
135
+ robot_name=settings.ROBOT_NAME,
136
+ isar_id=settings.ISAR_ID,
137
+ )
138
+ if publishers:
139
+ threads.extend(publishers)
140
+
141
+ api: API = injector.get(API)
142
+ api_thread: Thread = Thread(target=api.run_app, name="ISAR API", daemon=True)
143
+ threads.append(api_thread)
144
+
145
+ for thread in threads:
146
+ thread.start()
147
+ logger.info(f"Started thread: {thread.name}")
148
+
149
+ while True:
150
+ for thread in threads:
151
+ if not thread.is_alive():
152
+ logger.critical("Thread '%s' failed - ISAR shutting down", thread.name)
153
+ exit(1)
154
+ time.sleep(state_machine.sleep_time)
@@ -1,6 +1,6 @@
1
1
  import logging
2
2
  import time
3
- from typing import Callable, Optional, TYPE_CHECKING
3
+ from typing import TYPE_CHECKING, Callable, Optional
4
4
 
5
5
  from injector import inject
6
6
  from transitions import State
@@ -1,6 +1,6 @@
1
1
  import logging
2
2
  import time
3
- from typing import Any, Callable, Optional, TYPE_CHECKING
3
+ from typing import TYPE_CHECKING, Any, Callable, Optional
4
4
 
5
5
  from transitions import State
6
6
 
@@ -6,8 +6,8 @@ from typing import TYPE_CHECKING, Callable, Optional, Sequence, 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
10
9
  from isar.config.settings import settings
10
+ from isar.mission_planner.task_selector_interface import TaskSelectorStop
11
11
  from isar.services.utilities.threaded_request import (
12
12
  ThreadedRequest,
13
13
  ThreadedRequestNotFinishedError,
@@ -156,6 +156,10 @@ class Monitor(State):
156
156
  else:
157
157
  if isinstance(status, StepStatus):
158
158
  if self._step_finished(self.state_machine.current_step):
159
+ self.state_machine.update_current_task()
160
+ if self.state_machine.current_task == None:
161
+ transition = self.state_machine.full_mission_finished # type: ignore
162
+ break
159
163
  self.state_machine.update_current_step()
160
164
  self.state_machine.current_task.update_task_status()
161
165
  else: # If not all steps are done
@@ -1,6 +1,6 @@
1
1
  import logging
2
2
  import time
3
- from typing import Callable, TYPE_CHECKING
3
+ from typing import TYPE_CHECKING, Callable
4
4
 
5
5
  from transitions import State
6
6
 
@@ -1,6 +1,6 @@
1
1
  import logging
2
2
  import time
3
- from typing import Callable, Optional, TYPE_CHECKING
3
+ from typing import TYPE_CHECKING, Callable, Optional
4
4
 
5
5
  from transitions import State
6
6
 
@@ -2,10 +2,10 @@ import logging
2
2
  from pathlib import Path
3
3
 
4
4
  from isar.config.settings import settings
5
- from robot_interface.models.mission.mission import Mission
6
5
  from isar.storage.storage_interface import StorageException, StorageInterface
7
6
  from isar.storage.utilities import construct_metadata_file, construct_paths
8
7
  from robot_interface.models.inspection.inspection import Inspection
8
+ from robot_interface.models.mission.mission import Mission
9
9
 
10
10
 
11
11
  class LocalStorage(StorageInterface):
@@ -27,9 +27,10 @@ class LocalStorage(StorageInterface):
27
27
  inspection=inspection, mission=mission, filename=local_path.name
28
28
  )
29
29
  try:
30
- with open(absolute_path, "wb") as file, open(
31
- absolute_metadata_path, "wb"
32
- ) as metadata_file:
30
+ with (
31
+ open(absolute_path, "wb") as file,
32
+ open(absolute_metadata_path, "wb") as metadata_file,
33
+ ):
33
34
  file.write(inspection.data)
34
35
  metadata_file.write(metadata_bytes)
35
36
  except IOError as e: