isar 1.19.1__py3-none-any.whl → 1.20.1__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/__init__.py +2 -5
- isar/apis/models/start_mission_definition.py +22 -1
- isar/script.py +154 -0
- isar/state_machine/states/initialize.py +1 -1
- isar/state_machine/states/initiate.py +1 -1
- isar/state_machine/states/monitor.py +5 -1
- isar/state_machine/states/paused.py +1 -1
- isar/state_machine/states/stop.py +1 -1
- isar/storage/local_storage.py +5 -4
- isar-1.20.1.dist-info/METADATA +533 -0
- {isar-1.19.1.dist-info → isar-1.20.1.dist-info}/RECORD +17 -15
- isar-1.20.1.dist-info/entry_points.txt +2 -0
- robot_interface/models/mission/mission.py +3 -0
- robot_interface/models/mission/task.py +11 -2
- isar-1.19.1.dist-info/METADATA +0 -433
- {isar-1.19.1.dist-info → isar-1.20.1.dist-info}/LICENSE +0 -0
- {isar-1.19.1.dist-info → isar-1.20.1.dist-info}/WHEEL +0 -0
- {isar-1.19.1.dist-info → isar-1.20.1.dist-info}/top_level.txt +0 -0
isar/__init__.py
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
from importlib.metadata import
|
|
1
|
+
from importlib.metadata import version
|
|
2
2
|
|
|
3
|
-
|
|
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)
|
|
@@ -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
|
isar/storage/local_storage.py
CHANGED
|
@@ -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
|
|
31
|
-
|
|
32
|
-
|
|
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:
|