isar 1.30.4__py3-none-any.whl → 1.31.0__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/apis/api.py +7 -51
- isar/apis/models/models.py +5 -4
- isar/apis/models/start_mission_definition.py +4 -0
- isar/apis/robot_control/robot_controller.py +0 -2
- isar/apis/schedule/scheduling_controller.py +12 -4
- isar/config/log.py +8 -29
- isar/config/open_telemetry.py +68 -0
- isar/config/settings.py +12 -0
- isar/mission_planner/local_planner.py +0 -3
- isar/models/communication/queues/events.py +1 -1
- isar/models/communication/queues/queue_utils.py +2 -2
- isar/robot/robot.py +0 -3
- isar/script.py +2 -0
- isar/services/utilities/robot_utilities.py +0 -3
- isar/services/utilities/scheduling_utilities.py +28 -11
- isar/state_machine/generic_states/idle.py +1 -1
- isar/state_machine/generic_states/ongoing_mission.py +22 -7
- isar/state_machine/state_machine.py +7 -12
- isar/state_machine/states/monitor.py +0 -2
- isar/state_machine/states/stopping.py +2 -2
- isar/state_machine/states/unknown_status.py +1 -1
- isar/state_machine/transitions/functions/pause.py +39 -10
- isar/state_machine/transitions/functions/resume.py +44 -15
- isar/state_machine/transitions/functions/stop.py +44 -1
- isar/state_machine/transitions/mission.py +26 -2
- isar/state_machine/transitions/return_home.py +1 -1
- isar/storage/blob_storage.py +0 -2
- isar/storage/uploader.py +0 -3
- {isar-1.30.4.dist-info → isar-1.31.0.dist-info}/METADATA +7 -4
- {isar-1.30.4.dist-info → isar-1.31.0.dist-info}/RECORD +36 -35
- robot_interface/models/mission/task.py +0 -3
- robot_interface/robot_interface.py +1 -4
- {isar-1.30.4.dist-info → isar-1.31.0.dist-info}/WHEEL +0 -0
- {isar-1.30.4.dist-info → isar-1.31.0.dist-info}/entry_points.txt +0 -0
- {isar-1.30.4.dist-info → isar-1.31.0.dist-info}/licenses/LICENSE +0 -0
- {isar-1.30.4.dist-info → isar-1.31.0.dist-info}/top_level.txt +0 -0
isar/apis/api.py
CHANGED
|
@@ -8,35 +8,23 @@ from typing import List, Union
|
|
|
8
8
|
|
|
9
9
|
import click
|
|
10
10
|
import uvicorn
|
|
11
|
-
from
|
|
12
|
-
from fastapi import FastAPI, Request, Security
|
|
11
|
+
from fastapi import FastAPI, Security
|
|
13
12
|
from fastapi.middleware.cors import CORSMiddleware
|
|
14
13
|
from fastapi.routing import APIRouter
|
|
15
|
-
from opencensus.ext.azure.trace_exporter import AzureExporter
|
|
16
|
-
from opencensus.trace.attributes_helper import COMMON_ATTRIBUTES
|
|
17
|
-
from opencensus.trace.samplers import ProbabilitySampler
|
|
18
|
-
from opencensus.trace.span import SpanKind
|
|
19
|
-
from opencensus.trace.tracer import Tracer
|
|
20
14
|
from pydantic import AnyHttpUrl
|
|
21
15
|
|
|
22
16
|
from isar.apis.models.models import ControlMissionResponse, StartMissionResponse
|
|
23
17
|
from isar.apis.robot_control.robot_controller import RobotController
|
|
24
18
|
from isar.apis.schedule.scheduling_controller import SchedulingController
|
|
25
19
|
from isar.apis.security.authentication import Authenticator
|
|
26
|
-
from isar.config.configuration_error import ConfigurationError
|
|
27
|
-
from isar.config.keyvault.keyvault_error import KeyvaultError
|
|
28
20
|
from isar.config.keyvault.keyvault_service import Keyvault
|
|
29
21
|
from isar.config.settings import settings
|
|
30
22
|
from robot_interface.telemetry.mqtt_client import MqttClientInterface
|
|
31
23
|
from robot_interface.telemetry.payloads import StartUpMessagePayload
|
|
32
24
|
from robot_interface.utilities.json_service import EnhancedJSONEncoder
|
|
33
25
|
|
|
34
|
-
HTTP_URL = COMMON_ATTRIBUTES["HTTP_URL"]
|
|
35
|
-
HTTP_STATUS_CODE = COMMON_ATTRIBUTES["HTTP_STATUS_CODE"]
|
|
36
|
-
|
|
37
26
|
|
|
38
27
|
class API:
|
|
39
|
-
@inject
|
|
40
28
|
def __init__(
|
|
41
29
|
self,
|
|
42
30
|
authenticator: Authenticator,
|
|
@@ -45,7 +33,6 @@ class API:
|
|
|
45
33
|
keyvault: Keyvault,
|
|
46
34
|
mqtt_publisher: MqttClientInterface,
|
|
47
35
|
port: int = settings.API_PORT,
|
|
48
|
-
azure_ai_logging_enabled: bool = settings.LOG_HANDLER_APPLICATION_INSIGHTS_ENABLED,
|
|
49
36
|
) -> None:
|
|
50
37
|
self.authenticator: Authenticator = authenticator
|
|
51
38
|
self.scheduling_controller: SchedulingController = scheduling_controller
|
|
@@ -53,7 +40,6 @@ class API:
|
|
|
53
40
|
self.keyvault: Keyvault = keyvault
|
|
54
41
|
self.host: str = "0.0.0.0" # Locking uvicorn to use 0.0.0.0
|
|
55
42
|
self.port: int = port
|
|
56
|
-
self.azure_ai_logging_enabled: bool = azure_ai_logging_enabled
|
|
57
43
|
self.mqtt_publisher: MqttClientInterface = mqtt_publisher
|
|
58
44
|
|
|
59
45
|
self.logger: Logger = logging.getLogger("api")
|
|
@@ -113,9 +99,6 @@ class API:
|
|
|
113
99
|
allow_headers=["*"],
|
|
114
100
|
)
|
|
115
101
|
|
|
116
|
-
if self.azure_ai_logging_enabled:
|
|
117
|
-
self._add_request_logging_middleware(app)
|
|
118
|
-
|
|
119
102
|
app.include_router(router=self._create_scheduler_router())
|
|
120
103
|
|
|
121
104
|
app.include_router(router=self._create_info_router())
|
|
@@ -210,9 +193,15 @@ class API:
|
|
|
210
193
|
"description": "Mission succesfully stopped",
|
|
211
194
|
"model": ControlMissionResponse,
|
|
212
195
|
},
|
|
196
|
+
HTTPStatus.UNPROCESSABLE_ENTITY.value: {
|
|
197
|
+
"description": "Invalid body - The JSON is incorrect",
|
|
198
|
+
},
|
|
213
199
|
HTTPStatus.CONFLICT.value: {
|
|
214
200
|
"description": "Conflict - Invalid command in the current state",
|
|
215
201
|
},
|
|
202
|
+
HTTPStatus.BAD_REQUEST.value: {
|
|
203
|
+
"description": "Bad request - Robot does not have the capabilities to perform the mission",
|
|
204
|
+
},
|
|
216
205
|
HTTPStatus.INTERNAL_SERVER_ERROR.value: {
|
|
217
206
|
"description": "Internal Server Error - Current state of state machine unknown",
|
|
218
207
|
},
|
|
@@ -336,39 +325,6 @@ class API:
|
|
|
336
325
|
extra={"color_message": color_message},
|
|
337
326
|
)
|
|
338
327
|
|
|
339
|
-
def _add_request_logging_middleware(self, app: FastAPI) -> None:
|
|
340
|
-
connection_string: str
|
|
341
|
-
try:
|
|
342
|
-
connection_string = self.keyvault.get_secret(
|
|
343
|
-
"application-insights-connection-string"
|
|
344
|
-
).value
|
|
345
|
-
except KeyvaultError:
|
|
346
|
-
message: str = (
|
|
347
|
-
"Missing connection string for Application Insights in key vault. "
|
|
348
|
-
)
|
|
349
|
-
self.logger.critical(message)
|
|
350
|
-
raise ConfigurationError(message)
|
|
351
|
-
|
|
352
|
-
@app.middleware("http")
|
|
353
|
-
async def middlewareOpencensus(request: Request, call_next):
|
|
354
|
-
tracer = Tracer(
|
|
355
|
-
exporter=AzureExporter(connection_string=connection_string),
|
|
356
|
-
sampler=ProbabilitySampler(1.0),
|
|
357
|
-
)
|
|
358
|
-
with tracer.span("main") as span:
|
|
359
|
-
span.span_kind = SpanKind.SERVER
|
|
360
|
-
|
|
361
|
-
response = await call_next(request)
|
|
362
|
-
|
|
363
|
-
tracer.add_attribute_to_current_span(
|
|
364
|
-
attribute_key=HTTP_STATUS_CODE, attribute_value=response.status_code
|
|
365
|
-
)
|
|
366
|
-
tracer.add_attribute_to_current_span(
|
|
367
|
-
attribute_key=HTTP_URL, attribute_value=str(request.url)
|
|
368
|
-
)
|
|
369
|
-
|
|
370
|
-
return response
|
|
371
|
-
|
|
372
328
|
def _publish_startup_message(self) -> None:
|
|
373
329
|
if not self.mqtt_publisher:
|
|
374
330
|
return
|
isar/apis/models/models.py
CHANGED
|
@@ -19,10 +19,11 @@ class StartMissionResponse(BaseModel):
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class ControlMissionResponse(BaseModel):
|
|
22
|
-
mission_id: str
|
|
23
|
-
mission_status: str
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
mission_id: Optional[str]
|
|
23
|
+
mission_status: Optional[str]
|
|
24
|
+
mission_not_found: Optional[bool] = False
|
|
25
|
+
task_id: Optional[str]
|
|
26
|
+
task_status: Optional[str]
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
class RobotInfoResponse(BaseModel):
|
|
@@ -58,6 +58,10 @@ class StartMissionDefinition(BaseModel):
|
|
|
58
58
|
start_pose: Optional[InputPose] = None
|
|
59
59
|
|
|
60
60
|
|
|
61
|
+
class StopMissionDefinition(BaseModel):
|
|
62
|
+
mission_id: Optional[str] = None
|
|
63
|
+
|
|
64
|
+
|
|
61
65
|
def to_isar_mission(
|
|
62
66
|
start_mission_definition: StartMissionDefinition,
|
|
63
67
|
) -> Mission:
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
|
|
3
|
-
from dependency_injector.wiring import inject
|
|
4
3
|
from fastapi import HTTPException
|
|
5
4
|
|
|
6
5
|
from isar.apis.models.models import RobotInfoResponse
|
|
@@ -10,7 +9,6 @@ from robot_interface.models.robots.media import MediaConfig
|
|
|
10
9
|
|
|
11
10
|
|
|
12
11
|
class RobotController:
|
|
13
|
-
@inject
|
|
14
12
|
def __init__(
|
|
15
13
|
self,
|
|
16
14
|
robot_utilities: RobotUtilities,
|
|
@@ -2,7 +2,6 @@ import logging
|
|
|
2
2
|
from http import HTTPStatus
|
|
3
3
|
from threading import Lock
|
|
4
4
|
|
|
5
|
-
from dependency_injector.wiring import inject
|
|
6
5
|
from fastapi import Body, HTTPException, Path
|
|
7
6
|
|
|
8
7
|
from isar.apis.models.models import (
|
|
@@ -12,6 +11,7 @@ from isar.apis.models.models import (
|
|
|
12
11
|
)
|
|
13
12
|
from isar.apis.models.start_mission_definition import (
|
|
14
13
|
StartMissionDefinition,
|
|
14
|
+
StopMissionDefinition,
|
|
15
15
|
to_isar_mission,
|
|
16
16
|
)
|
|
17
17
|
from isar.config.settings import robot_settings, settings
|
|
@@ -23,7 +23,6 @@ from robot_interface.models.mission.task import TASKS, InspectionTask, MoveArm
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
class SchedulingController:
|
|
26
|
-
@inject
|
|
27
26
|
def __init__(
|
|
28
27
|
self,
|
|
29
28
|
scheduling_utilities: SchedulingUtilities,
|
|
@@ -179,7 +178,16 @@ class SchedulingController:
|
|
|
179
178
|
)
|
|
180
179
|
return resume_mission_response
|
|
181
180
|
|
|
182
|
-
def stop_mission(
|
|
181
|
+
def stop_mission(
|
|
182
|
+
self,
|
|
183
|
+
mission_id: StopMissionDefinition = Body(
|
|
184
|
+
default=None,
|
|
185
|
+
embed=True,
|
|
186
|
+
title="Mission ID to stop",
|
|
187
|
+
description="The mission ID of the mission being stopped, in json format",
|
|
188
|
+
),
|
|
189
|
+
) -> ControlMissionResponse:
|
|
190
|
+
|
|
183
191
|
self.logger.info("Received request to stop current mission")
|
|
184
192
|
|
|
185
193
|
state: States = self.scheduling_utilities.get_state()
|
|
@@ -198,7 +206,7 @@ class SchedulingController:
|
|
|
198
206
|
raise HTTPException(status_code=HTTPStatus.CONFLICT, detail=error_message)
|
|
199
207
|
|
|
200
208
|
stop_mission_response: ControlMissionResponse = (
|
|
201
|
-
self.scheduling_utilities.stop_mission()
|
|
209
|
+
self.scheduling_utilities.stop_mission(mission_id.mission_id)
|
|
202
210
|
)
|
|
203
211
|
return stop_mission_response
|
|
204
212
|
|
isar/config/log.py
CHANGED
|
@@ -3,30 +3,21 @@ import logging.config
|
|
|
3
3
|
from importlib.resources import as_file, files
|
|
4
4
|
|
|
5
5
|
import yaml
|
|
6
|
-
from opencensus.ext.azure.log_exporter import AzureLogHandler
|
|
7
6
|
from uvicorn.logging import ColourizedFormatter
|
|
8
7
|
|
|
9
|
-
from isar.config.configuration_error import ConfigurationError
|
|
10
|
-
from isar.config.keyvault.keyvault_error import KeyvaultError
|
|
11
8
|
from isar.config.keyvault.keyvault_service import Keyvault
|
|
12
9
|
from isar.config.settings import settings
|
|
13
10
|
|
|
14
11
|
|
|
15
12
|
def setup_loggers(keyvault: Keyvault) -> None:
|
|
16
13
|
log_levels: dict = settings.LOG_LEVELS
|
|
17
|
-
|
|
18
|
-
with as_file(source) as f:
|
|
19
|
-
log_config = yaml.safe_load(open(f))
|
|
14
|
+
log_config = load_log_config()
|
|
20
15
|
|
|
21
16
|
logging.config.dictConfig(log_config)
|
|
22
17
|
|
|
23
18
|
handlers = []
|
|
24
19
|
if settings.LOG_HANDLER_LOCAL_ENABLED:
|
|
25
20
|
handlers.append(configure_console_handler(log_config=log_config))
|
|
26
|
-
if settings.LOG_HANDLER_APPLICATION_INSIGHTS_ENABLED:
|
|
27
|
-
handlers.append(
|
|
28
|
-
configure_azure_handler(log_config=log_config, keyvault=keyvault)
|
|
29
|
-
)
|
|
30
21
|
|
|
31
22
|
for log_handler in handlers:
|
|
32
23
|
for loggers in log_config["loggers"].keys():
|
|
@@ -35,6 +26,13 @@ def setup_loggers(keyvault: Keyvault) -> None:
|
|
|
35
26
|
logging.getLogger().addHandler(log_handler)
|
|
36
27
|
|
|
37
28
|
|
|
29
|
+
def load_log_config():
|
|
30
|
+
source = files("isar").joinpath("config").joinpath("logging.conf")
|
|
31
|
+
with as_file(source) as f:
|
|
32
|
+
log_config = yaml.safe_load(open(f))
|
|
33
|
+
return log_config
|
|
34
|
+
|
|
35
|
+
|
|
38
36
|
def configure_console_handler(log_config: dict) -> logging.Handler:
|
|
39
37
|
handler = logging.StreamHandler()
|
|
40
38
|
handler.setLevel(log_config["root"]["level"])
|
|
@@ -46,22 +44,3 @@ def configure_console_handler(log_config: dict) -> logging.Handler:
|
|
|
46
44
|
)
|
|
47
45
|
)
|
|
48
46
|
return handler
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
def configure_azure_handler(log_config: dict, keyvault: Keyvault) -> logging.Handler:
|
|
52
|
-
connection_string: str
|
|
53
|
-
try:
|
|
54
|
-
connection_string = keyvault.get_secret(
|
|
55
|
-
"application-insights-connection-string"
|
|
56
|
-
).value
|
|
57
|
-
except KeyvaultError:
|
|
58
|
-
message: str = (
|
|
59
|
-
"CRITICAL ERROR: Missing connection string for"
|
|
60
|
-
f" Application Insights in key vault '{keyvault.name}'."
|
|
61
|
-
)
|
|
62
|
-
print(f"\n{message} \n")
|
|
63
|
-
raise ConfigurationError(message)
|
|
64
|
-
|
|
65
|
-
handler = AzureLogHandler(connection_string=connection_string)
|
|
66
|
-
handler.setLevel(log_config["root"]["level"])
|
|
67
|
-
return handler
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from azure.identity import ManagedIdentityCredential
|
|
4
|
+
from azure.monitor.opentelemetry.exporter import (
|
|
5
|
+
AzureMonitorLogExporter,
|
|
6
|
+
AzureMonitorTraceExporter,
|
|
7
|
+
)
|
|
8
|
+
from fastapi import FastAPI
|
|
9
|
+
from opentelemetry import trace
|
|
10
|
+
from opentelemetry._logs import set_logger_provider
|
|
11
|
+
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
|
|
12
|
+
from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler
|
|
13
|
+
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
|
|
14
|
+
from opentelemetry.sdk.resources import SERVICE_NAME, Resource
|
|
15
|
+
from opentelemetry.sdk.trace import TracerProvider
|
|
16
|
+
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
|
17
|
+
|
|
18
|
+
from isar.config.log import load_log_config
|
|
19
|
+
from isar.config.settings import settings
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def setup_open_telemetry(app: FastAPI) -> None:
|
|
23
|
+
if not settings.LOG_HANDLER_APPLICATION_INSIGHTS_ENABLED:
|
|
24
|
+
return
|
|
25
|
+
trace_exporter, log_exporter = get_azure_monitor_exporters()
|
|
26
|
+
|
|
27
|
+
service_name = settings.OPEN_TELEMETRY_SERVICE_NAME
|
|
28
|
+
resource = Resource.create({SERVICE_NAME: service_name})
|
|
29
|
+
|
|
30
|
+
tracer_provider = TracerProvider(resource=resource)
|
|
31
|
+
tracer_provider.add_span_processor(BatchSpanProcessor(trace_exporter))
|
|
32
|
+
trace.set_tracer_provider(tracer_provider)
|
|
33
|
+
|
|
34
|
+
log_provider = LoggerProvider(resource=resource)
|
|
35
|
+
set_logger_provider(log_provider)
|
|
36
|
+
log_provider.add_log_record_processor(BatchLogRecordProcessor(log_exporter))
|
|
37
|
+
|
|
38
|
+
handler = LoggingHandler(logger_provider=log_provider)
|
|
39
|
+
attach_loggers_for_open_telemetry(handler)
|
|
40
|
+
|
|
41
|
+
FastAPIInstrumentor.instrument_app(app, tracer_provider=tracer_provider)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def attach_loggers_for_open_telemetry(handler: LoggingHandler):
|
|
45
|
+
log_config = load_log_config()
|
|
46
|
+
|
|
47
|
+
for logger_name in log_config["loggers"].keys():
|
|
48
|
+
logger = logging.getLogger(logger_name)
|
|
49
|
+
logger.addHandler(handler)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def get_azure_monitor_exporters() -> (
|
|
53
|
+
tuple[AzureMonitorTraceExporter, AzureMonitorLogExporter]
|
|
54
|
+
):
|
|
55
|
+
"""
|
|
56
|
+
If connection string is defined in environment variables, then use it to create Azure Monitor Exporters.
|
|
57
|
+
Else use Azure Managed Identity to create Azure Monitor Exporters.
|
|
58
|
+
"""
|
|
59
|
+
connection_string = settings.APPLICATIONINSIGHTS_CONNECTION_STRING
|
|
60
|
+
if connection_string:
|
|
61
|
+
trace_exporter = AzureMonitorTraceExporter(connection_string=connection_string)
|
|
62
|
+
log_exporter = AzureMonitorLogExporter(connection_string=connection_string)
|
|
63
|
+
else:
|
|
64
|
+
credential = ManagedIdentityCredential()
|
|
65
|
+
trace_exporter = AzureMonitorTraceExporter(credential=credential)
|
|
66
|
+
log_exporter = AzureMonitorLogExporter(credential=credential)
|
|
67
|
+
|
|
68
|
+
return trace_exporter, log_exporter
|
isar/config/settings.py
CHANGED
|
@@ -12,6 +12,12 @@ from robot_interface.telemetry.payloads import DocumentInfo
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class Settings(BaseSettings):
|
|
15
|
+
# Name of the OpenTelemetry service
|
|
16
|
+
OPEN_TELEMETRY_SERVICE_NAME: str = Field(default="isar")
|
|
17
|
+
# Connection string for Azure Application Insights
|
|
18
|
+
# This is optional and it will use managed identity if not set
|
|
19
|
+
APPLICATIONINSIGHTS_CONNECTION_STRING: str = Field(default="")
|
|
20
|
+
|
|
15
21
|
# Determines which robot package ISAR will attempt to import
|
|
16
22
|
# Name must match with an installed python package in the local environment
|
|
17
23
|
ROBOT_PACKAGE: str = Field(default="isar_robot")
|
|
@@ -52,6 +58,12 @@ class Settings(BaseSettings):
|
|
|
52
58
|
# issues
|
|
53
59
|
REQUEST_STATUS_COMMUNICATION_RECONNECT_DELAY: float = Field(default=10)
|
|
54
60
|
|
|
61
|
+
# Number of attempts for state transitions resume and pause if failed
|
|
62
|
+
STATE_TRANSITION_NUM_RETIRES: int = Field(default=10)
|
|
63
|
+
|
|
64
|
+
# Interval between attempt of state transition
|
|
65
|
+
STATE_TRANSITION_RETRY_INTERVAL_SEC: float = Field(default=1)
|
|
66
|
+
|
|
55
67
|
# Number of attempts to stop the robot before giving up
|
|
56
68
|
STOP_ROBOT_ATTEMPTS_LIMIT: int = Field(default=3)
|
|
57
69
|
|
|
@@ -2,8 +2,6 @@ import json
|
|
|
2
2
|
import logging
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
|
|
5
|
-
from dependency_injector.wiring import inject
|
|
6
|
-
|
|
7
5
|
from isar.config.settings import settings
|
|
8
6
|
from isar.mission_planner.mission_planner_interface import (
|
|
9
7
|
MissionNotFoundError,
|
|
@@ -16,7 +14,6 @@ logger = logging.getLogger("api")
|
|
|
16
14
|
|
|
17
15
|
|
|
18
16
|
class LocalPlanner(MissionPlannerInterface):
|
|
19
|
-
@inject
|
|
20
17
|
def __init__(self):
|
|
21
18
|
self.predefined_mission_folder = Path(settings.PREDEFINED_MISSIONS_FOLDER)
|
|
22
19
|
|
|
@@ -35,7 +35,7 @@ class APIRequests:
|
|
|
35
35
|
class StateMachineEvents:
|
|
36
36
|
def __init__(self) -> None:
|
|
37
37
|
self.start_mission: Queue[Mission] = Queue(maxsize=1)
|
|
38
|
-
self.stop_mission: Queue[
|
|
38
|
+
self.stop_mission: Queue[str] = Queue(maxsize=1)
|
|
39
39
|
self.pause_mission: Queue[bool] = Queue(maxsize=1)
|
|
40
40
|
self.task_status_request: Queue[str] = Queue(maxsize=1)
|
|
41
41
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
from queue import Empty, Queue
|
|
2
|
-
from typing import Optional, TypeVar
|
|
2
|
+
from typing import Any, Optional, TypeVar
|
|
3
3
|
|
|
4
4
|
from isar.models.communication.queues.status_queue import StatusQueue
|
|
5
5
|
|
|
6
6
|
T = TypeVar("T")
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
def trigger_event_without_data(queue: Queue[
|
|
9
|
+
def trigger_event_without_data(queue: Queue[Any]) -> None:
|
|
10
10
|
queue.put(True)
|
|
11
11
|
|
|
12
12
|
|
isar/robot/robot.py
CHANGED
|
@@ -3,8 +3,6 @@ from queue import Queue
|
|
|
3
3
|
from threading import Event
|
|
4
4
|
from typing import Optional
|
|
5
5
|
|
|
6
|
-
from dependency_injector.wiring import inject
|
|
7
|
-
|
|
8
6
|
from isar.models.communication.queues.events import (
|
|
9
7
|
Events,
|
|
10
8
|
RobotServiceEvents,
|
|
@@ -21,7 +19,6 @@ from robot_interface.robot_interface import RobotInterface
|
|
|
21
19
|
|
|
22
20
|
|
|
23
21
|
class Robot(object):
|
|
24
|
-
@inject
|
|
25
22
|
def __init__(
|
|
26
23
|
self, events: Events, robot: RobotInterface, shared_state: SharedState
|
|
27
24
|
) -> None:
|
isar/script.py
CHANGED
|
@@ -8,6 +8,7 @@ from typing import Any, List, Tuple
|
|
|
8
8
|
import isar
|
|
9
9
|
from isar.apis.api import API
|
|
10
10
|
from isar.config.log import setup_loggers
|
|
11
|
+
from isar.config.open_telemetry import setup_open_telemetry
|
|
11
12
|
from isar.config.settings import robot_settings, settings
|
|
12
13
|
from isar.models.communication.queues.events import Events
|
|
13
14
|
from isar.modules import ApplicationContainer, get_injector
|
|
@@ -83,6 +84,7 @@ def start() -> None:
|
|
|
83
84
|
|
|
84
85
|
keyvault = injector.keyvault()
|
|
85
86
|
setup_loggers(keyvault=keyvault)
|
|
87
|
+
setup_open_telemetry(app=injector.api().app)
|
|
86
88
|
logger: Logger = logging.getLogger("main")
|
|
87
89
|
|
|
88
90
|
print_startup_info()
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
|
|
3
|
-
from dependency_injector.wiring import inject
|
|
4
|
-
|
|
5
3
|
from robot_interface.models.robots.media import MediaConfig
|
|
6
4
|
from robot_interface.robot_interface import RobotInterface
|
|
7
5
|
|
|
@@ -11,7 +9,6 @@ class RobotUtilities:
|
|
|
11
9
|
Contains utility functions for getting robot information from the API.
|
|
12
10
|
"""
|
|
13
11
|
|
|
14
|
-
@inject
|
|
15
12
|
def __init__(
|
|
16
13
|
self,
|
|
17
14
|
robot: RobotInterface,
|
|
@@ -4,7 +4,6 @@ from http import HTTPStatus
|
|
|
4
4
|
from queue import Empty
|
|
5
5
|
from typing import Any, List
|
|
6
6
|
|
|
7
|
-
from dependency_injector.wiring import inject
|
|
8
7
|
from fastapi import HTTPException
|
|
9
8
|
from requests import HTTPError
|
|
10
9
|
|
|
@@ -22,6 +21,7 @@ from isar.models.communication.queues.queue_timeout_error import QueueTimeoutErr
|
|
|
22
21
|
from isar.services.utilities.queue_utilities import QueueUtilities
|
|
23
22
|
from isar.state_machine.states_enum import States
|
|
24
23
|
from robot_interface.models.mission.mission import Mission
|
|
24
|
+
from robot_interface.models.mission.status import MissionStatus
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
class SchedulingUtilities:
|
|
@@ -30,7 +30,6 @@ class SchedulingUtilities:
|
|
|
30
30
|
required thread communication through queues to the state machine.
|
|
31
31
|
"""
|
|
32
32
|
|
|
33
|
-
@inject
|
|
34
33
|
def __init__(
|
|
35
34
|
self,
|
|
36
35
|
events: Events,
|
|
@@ -219,15 +218,15 @@ class SchedulingUtilities:
|
|
|
219
218
|
If there is a timeout while communicating with the state machine
|
|
220
219
|
"""
|
|
221
220
|
try:
|
|
222
|
-
|
|
221
|
+
response = self._send_command(True, self.api_events.pause_mission)
|
|
222
|
+
self.logger.info("OK - Mission successfully paused")
|
|
223
|
+
return response
|
|
223
224
|
except QueueTimeoutError:
|
|
224
225
|
error_message = "Internal Server Error - Failed to pause mission"
|
|
225
226
|
self.logger.error(error_message)
|
|
226
227
|
raise HTTPException(
|
|
227
228
|
status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=error_message
|
|
228
229
|
)
|
|
229
|
-
finally:
|
|
230
|
-
self.logger.info("OK - Mission successfully paused")
|
|
231
230
|
|
|
232
231
|
def resume_mission(self) -> ControlMissionResponse:
|
|
233
232
|
"""Resume mission
|
|
@@ -238,28 +237,46 @@ class SchedulingUtilities:
|
|
|
238
237
|
If there is a timeout while communicating with the state machine
|
|
239
238
|
"""
|
|
240
239
|
try:
|
|
241
|
-
|
|
240
|
+
response = self._send_command(True, self.api_events.resume_mission)
|
|
241
|
+
self.logger.info("OK - Mission successfully resumed")
|
|
242
|
+
return response
|
|
242
243
|
except QueueTimeoutError:
|
|
243
244
|
error_message = "Internal Server Error - Failed to resume mission"
|
|
244
245
|
self.logger.error(error_message)
|
|
245
246
|
raise HTTPException(
|
|
246
247
|
status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=error_message
|
|
247
248
|
)
|
|
248
|
-
finally:
|
|
249
|
-
self.logger.info("OK - Mission successfully resumed")
|
|
250
249
|
|
|
251
|
-
def stop_mission(self) -> ControlMissionResponse:
|
|
250
|
+
def stop_mission(self, mission_id: str = "") -> ControlMissionResponse:
|
|
252
251
|
"""Stop mission
|
|
253
252
|
|
|
254
253
|
Raises
|
|
255
254
|
------
|
|
256
|
-
|
|
255
|
+
HTTPException 404 Not Found
|
|
256
|
+
If the mission_id was not known to Isar
|
|
257
|
+
HTTPException 503 Service Unavailable
|
|
258
|
+
The request was understood, but attempting to stop the mission failed
|
|
259
|
+
HTTPException 408 Request timeout
|
|
257
260
|
If there is a timeout while communicating with the state machine
|
|
258
261
|
"""
|
|
259
262
|
try:
|
|
260
263
|
stop_mission_response: ControlMissionResponse = self._send_command(
|
|
261
|
-
|
|
264
|
+
mission_id, self.api_events.stop_mission
|
|
262
265
|
)
|
|
266
|
+
|
|
267
|
+
if stop_mission_response.mission_not_found:
|
|
268
|
+
error_message = f"Mission ID {stop_mission_response.mission_id} is not currently running"
|
|
269
|
+
self.logger.error(error_message)
|
|
270
|
+
raise HTTPException(
|
|
271
|
+
status_code=HTTPStatus.NOT_FOUND, detail=error_message
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
if stop_mission_response.mission_status != MissionStatus.Cancelled.value:
|
|
275
|
+
error_message = "Failed to stop mission"
|
|
276
|
+
self.logger.error(error_message)
|
|
277
|
+
raise HTTPException(
|
|
278
|
+
status_code=HTTPStatus.CONFLICT, detail=error_message
|
|
279
|
+
)
|
|
263
280
|
except QueueTimeoutError:
|
|
264
281
|
error_message = "Internal Server Error - Failed to stop mission"
|
|
265
282
|
self.logger.error(error_message)
|
|
@@ -6,6 +6,7 @@ from queue import Queue
|
|
|
6
6
|
from threading import Event
|
|
7
7
|
from typing import TYPE_CHECKING, Optional, Tuple
|
|
8
8
|
|
|
9
|
+
from isar.apis.models.models import ControlMissionResponse
|
|
9
10
|
from isar.config.settings import settings
|
|
10
11
|
from isar.models.communication.message import StartMissionMessage
|
|
11
12
|
from isar.models.communication.queues.queue_utils import (
|
|
@@ -16,6 +17,7 @@ from isar.models.communication.queues.queue_utils import (
|
|
|
16
17
|
from isar.services.utilities.threaded_request import ThreadedRequest
|
|
17
18
|
from robot_interface.models.exceptions.robot_exceptions import (
|
|
18
19
|
ErrorMessage,
|
|
20
|
+
ErrorReason,
|
|
19
21
|
RobotException,
|
|
20
22
|
RobotRetrieveInspectionException,
|
|
21
23
|
)
|
|
@@ -54,12 +56,24 @@ class OngoingMission:
|
|
|
54
56
|
self._run()
|
|
55
57
|
|
|
56
58
|
def stop(self) -> None:
|
|
57
|
-
|
|
59
|
+
return
|
|
58
60
|
|
|
59
61
|
def _check_and_handle_stop_mission_event(self, event: Queue) -> bool:
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
62
|
+
mission_id: str = check_for_event(event)
|
|
63
|
+
if mission_id is not None:
|
|
64
|
+
if self.state_machine.current_mission.id == mission_id or mission_id == "":
|
|
65
|
+
self.state_machine.stop() # type: ignore
|
|
66
|
+
return True
|
|
67
|
+
else:
|
|
68
|
+
self.events.api_requests.stop_mission.output.put(
|
|
69
|
+
ControlMissionResponse(
|
|
70
|
+
mission_id=mission_id,
|
|
71
|
+
mission_status=self.state_machine.current_mission.status,
|
|
72
|
+
mission_not_found=True,
|
|
73
|
+
task_id=self.state_machine.current_task.id,
|
|
74
|
+
task_status=self.state_machine.current_task.status,
|
|
75
|
+
)
|
|
76
|
+
)
|
|
63
77
|
return False
|
|
64
78
|
|
|
65
79
|
def _check_and_handle_pause_mission_event(self, event: Queue) -> bool:
|
|
@@ -139,6 +153,10 @@ class OngoingMission:
|
|
|
139
153
|
|
|
140
154
|
if self.state == OngoingMissionStates.ReturningHome:
|
|
141
155
|
if status != TaskStatus.Successful:
|
|
156
|
+
self.state_machine.current_mission.error_message = ErrorMessage(
|
|
157
|
+
error_reason=ErrorReason.RobotActionException,
|
|
158
|
+
error_description="Return home failed.",
|
|
159
|
+
)
|
|
142
160
|
self.state_machine.return_home_failed() # type: ignore
|
|
143
161
|
return True
|
|
144
162
|
self.state_machine.returned_home() # type: ignore
|
|
@@ -159,9 +177,6 @@ class OngoingMission:
|
|
|
159
177
|
self.state_machine.mission_finished() # type: ignore
|
|
160
178
|
return True
|
|
161
179
|
|
|
162
|
-
# Report and update next task
|
|
163
|
-
self.state_machine.current_task.update_task_status()
|
|
164
|
-
self.state_machine.publish_task_status(task=self.state_machine.current_task)
|
|
165
180
|
return False
|
|
166
181
|
|
|
167
182
|
def _check_and_handle_start_mission_event(
|
|
@@ -5,7 +5,6 @@ from datetime import datetime, timezone
|
|
|
5
5
|
from threading import Event
|
|
6
6
|
from typing import Deque, List, Optional
|
|
7
7
|
|
|
8
|
-
from dependency_injector.wiring import inject
|
|
9
8
|
from transitions import Machine
|
|
10
9
|
from transitions.core import State
|
|
11
10
|
|
|
@@ -48,7 +47,6 @@ from robot_interface.utilities.json_service import EnhancedJSONEncoder
|
|
|
48
47
|
class StateMachine(object):
|
|
49
48
|
"""Handles state transitions for supervisory robot control."""
|
|
50
49
|
|
|
51
|
-
@inject
|
|
52
50
|
def __init__(
|
|
53
51
|
self,
|
|
54
52
|
events: Events,
|
|
@@ -194,6 +192,7 @@ class StateMachine(object):
|
|
|
194
192
|
self.current_task = None
|
|
195
193
|
self.send_task_status()
|
|
196
194
|
self.current_mission = None
|
|
195
|
+
self.mission_ongoing = False
|
|
197
196
|
|
|
198
197
|
def start_mission(self, mission: Mission):
|
|
199
198
|
"""Starts a scheduled mission."""
|
|
@@ -316,17 +315,13 @@ class StateMachine(object):
|
|
|
316
315
|
self.logger.info("Mission overview:\n%s", log_statement)
|
|
317
316
|
|
|
318
317
|
def _make_control_mission_response(self) -> ControlMissionResponse:
|
|
319
|
-
if self.current_mission is None:
|
|
320
|
-
raise ValueError("No current mission is set")
|
|
321
|
-
|
|
322
|
-
if self.current_task is None:
|
|
323
|
-
raise ValueError("No current task is set")
|
|
324
|
-
|
|
325
318
|
return ControlMissionResponse(
|
|
326
|
-
mission_id=self.current_mission.id,
|
|
327
|
-
mission_status=
|
|
328
|
-
|
|
329
|
-
|
|
319
|
+
mission_id=self.current_mission.id if self.current_mission else None,
|
|
320
|
+
mission_status=(
|
|
321
|
+
self.current_mission.status if self.current_mission else None
|
|
322
|
+
),
|
|
323
|
+
task_id=self.current_task.id if self.current_task else None,
|
|
324
|
+
task_status=self.current_task.status if self.current_task else None,
|
|
330
325
|
)
|
|
331
326
|
|
|
332
327
|
def _queue_empty_response(self) -> None:
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING
|
|
2
2
|
|
|
3
|
-
from dependency_injector.wiring import inject
|
|
4
3
|
from transitions import State
|
|
5
4
|
|
|
6
5
|
from isar.state_machine.generic_states.ongoing_mission import (
|
|
@@ -13,7 +12,6 @@ if TYPE_CHECKING:
|
|
|
13
12
|
|
|
14
13
|
|
|
15
14
|
class Monitor(State, OngoingMission):
|
|
16
|
-
@inject
|
|
17
15
|
def __init__(self, state_machine: "StateMachine") -> None:
|
|
18
16
|
State.__init__(self, name="monitor", on_enter=self.start, on_exit=self.stop)
|
|
19
17
|
|
|
@@ -39,9 +39,9 @@ class Stopping(State):
|
|
|
39
39
|
if error_message is not None:
|
|
40
40
|
self.logger.warning(error_message.error_description)
|
|
41
41
|
if self.stopping_return_home_mission:
|
|
42
|
-
self.state_machine.
|
|
42
|
+
self.state_machine.return_home_mission_stopping_failed() # type: ignore
|
|
43
43
|
else:
|
|
44
|
-
self.state_machine.
|
|
44
|
+
self.state_machine.mission_stopping_failed() # type: ignore
|
|
45
45
|
return True
|
|
46
46
|
return False
|
|
47
47
|
|
|
@@ -33,7 +33,7 @@ class UnknownStatus(State):
|
|
|
33
33
|
return
|
|
34
34
|
|
|
35
35
|
def _check_and_handle_stop_mission_event(self, event: Queue) -> bool:
|
|
36
|
-
if check_for_event(event):
|
|
36
|
+
if check_for_event(event) is not None:
|
|
37
37
|
self.state_machine.stop() # type: ignore
|
|
38
38
|
return True
|
|
39
39
|
return False
|
|
@@ -3,22 +3,51 @@ from typing import TYPE_CHECKING
|
|
|
3
3
|
if TYPE_CHECKING:
|
|
4
4
|
from isar.state_machine.state_machine import StateMachine
|
|
5
5
|
|
|
6
|
+
import time
|
|
7
|
+
|
|
6
8
|
from isar.apis.models.models import ControlMissionResponse
|
|
9
|
+
from isar.config.settings import settings
|
|
10
|
+
from robot_interface.models.exceptions.robot_exceptions import (
|
|
11
|
+
RobotActionException,
|
|
12
|
+
RobotException,
|
|
13
|
+
)
|
|
7
14
|
from robot_interface.models.mission.status import MissionStatus, TaskStatus
|
|
8
15
|
|
|
9
16
|
|
|
10
17
|
def pause_mission(state_machine: "StateMachine") -> bool:
|
|
11
18
|
state_machine.logger.info("Pausing mission: %s", state_machine.current_mission.id)
|
|
12
|
-
state_machine.current_mission.status = MissionStatus.Paused
|
|
13
|
-
state_machine.current_task.status = TaskStatus.Paused
|
|
14
19
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
max_retries = settings.STATE_TRANSITION_NUM_RETIRES
|
|
21
|
+
retry_interval = settings.STATE_TRANSITION_RETRY_INTERVAL_SEC
|
|
22
|
+
|
|
23
|
+
for attempt in range(max_retries):
|
|
24
|
+
try:
|
|
25
|
+
state_machine.robot.pause()
|
|
26
|
+
state_machine.current_mission.status = MissionStatus.Paused
|
|
27
|
+
state_machine.current_task.status = TaskStatus.Paused
|
|
28
|
+
|
|
29
|
+
paused_mission_response: ControlMissionResponse = (
|
|
30
|
+
state_machine._make_control_mission_response()
|
|
31
|
+
)
|
|
32
|
+
state_machine.events.api_requests.pause_mission.output.put(
|
|
33
|
+
paused_mission_response
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
state_machine.publish_mission_status()
|
|
37
|
+
state_machine.publish_task_status(task=state_machine.current_task)
|
|
19
38
|
|
|
20
|
-
|
|
21
|
-
|
|
39
|
+
state_machine.logger.info("Mission paused successfully.")
|
|
40
|
+
return True
|
|
41
|
+
except RobotActionException as e:
|
|
42
|
+
state_machine.logger.warning(
|
|
43
|
+
f"Attempt {attempt + 1} to pause mission failed: {e.error_description}"
|
|
44
|
+
)
|
|
45
|
+
time.sleep(retry_interval)
|
|
46
|
+
except RobotException as e:
|
|
47
|
+
state_machine.logger.warning(
|
|
48
|
+
f"Attempt {attempt + 1} to pause mission raised a RobotException: {e.error_description}"
|
|
49
|
+
)
|
|
50
|
+
time.sleep(retry_interval)
|
|
22
51
|
|
|
23
|
-
state_machine.
|
|
24
|
-
return
|
|
52
|
+
state_machine.logger.error("Failed to pause mission after multiple attempts.")
|
|
53
|
+
return False
|
|
@@ -3,25 +3,54 @@ from typing import TYPE_CHECKING
|
|
|
3
3
|
if TYPE_CHECKING:
|
|
4
4
|
from isar.state_machine.state_machine import StateMachine
|
|
5
5
|
|
|
6
|
+
import time
|
|
7
|
+
|
|
6
8
|
from isar.apis.models.models import ControlMissionResponse
|
|
9
|
+
from isar.config.settings import settings
|
|
10
|
+
from robot_interface.models.exceptions.robot_exceptions import (
|
|
11
|
+
RobotActionException,
|
|
12
|
+
RobotException,
|
|
13
|
+
)
|
|
7
14
|
from robot_interface.models.mission.status import MissionStatus, TaskStatus
|
|
8
15
|
|
|
9
16
|
|
|
10
17
|
def resume_mission(state_machine: "StateMachine") -> bool:
|
|
11
18
|
state_machine.logger.info("Resuming mission: %s", state_machine.current_mission.id)
|
|
12
|
-
state_machine.current_mission.status = MissionStatus.InProgress
|
|
13
|
-
state_machine.current_mission.error_message = None
|
|
14
|
-
state_machine.current_task.status = TaskStatus.InProgress
|
|
15
|
-
|
|
16
|
-
state_machine.mission_ongoing = True
|
|
17
|
-
|
|
18
|
-
state_machine.publish_mission_status()
|
|
19
|
-
state_machine.publish_task_status(task=state_machine.current_task)
|
|
20
|
-
|
|
21
|
-
resume_mission_response: ControlMissionResponse = (
|
|
22
|
-
state_machine._make_control_mission_response()
|
|
23
|
-
)
|
|
24
|
-
state_machine.events.api_requests.resume_mission.output.put(resume_mission_response)
|
|
25
19
|
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
max_retries = settings.STATE_TRANSITION_NUM_RETIRES
|
|
21
|
+
retry_interval = settings.STATE_TRANSITION_RETRY_INTERVAL_SEC
|
|
22
|
+
|
|
23
|
+
for attempt in range(max_retries):
|
|
24
|
+
try:
|
|
25
|
+
state_machine.robot.resume()
|
|
26
|
+
state_machine.current_mission.status = MissionStatus.InProgress
|
|
27
|
+
state_machine.current_mission.error_message = None
|
|
28
|
+
state_machine.current_task.status = TaskStatus.InProgress
|
|
29
|
+
|
|
30
|
+
state_machine.mission_ongoing = True
|
|
31
|
+
|
|
32
|
+
state_machine.publish_mission_status()
|
|
33
|
+
state_machine.publish_task_status(task=state_machine.current_task)
|
|
34
|
+
|
|
35
|
+
resume_mission_response: ControlMissionResponse = (
|
|
36
|
+
state_machine._make_control_mission_response()
|
|
37
|
+
)
|
|
38
|
+
state_machine.events.api_requests.resume_mission.output.put(
|
|
39
|
+
resume_mission_response
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
state_machine.logger.info("Mission resumed successfully.")
|
|
43
|
+
return True
|
|
44
|
+
except RobotActionException as e:
|
|
45
|
+
state_machine.logger.warning(
|
|
46
|
+
f"Attempt {attempt + 1} to resume mission failed: {e.error_description}"
|
|
47
|
+
)
|
|
48
|
+
time.sleep(retry_interval)
|
|
49
|
+
except RobotException as e:
|
|
50
|
+
state_machine.logger.warning(
|
|
51
|
+
f"Attempt {attempt + 1} to resume mission raised a RobotException: {e.error_description}"
|
|
52
|
+
)
|
|
53
|
+
time.sleep(retry_interval)
|
|
54
|
+
|
|
55
|
+
state_machine.logger.error("Failed to resume mission after multiple attempts.")
|
|
56
|
+
return False
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING
|
|
2
2
|
|
|
3
|
-
from isar.models.communication.queues.queue_utils import
|
|
3
|
+
from isar.models.communication.queues.queue_utils import (
|
|
4
|
+
check_for_event_without_consumption,
|
|
5
|
+
trigger_event_without_data,
|
|
6
|
+
)
|
|
4
7
|
|
|
5
8
|
if TYPE_CHECKING:
|
|
6
9
|
from isar.state_machine.state_machine import StateMachine
|
|
@@ -39,11 +42,51 @@ def stop_mission_cleanup(state_machine: "StateMachine") -> bool:
|
|
|
39
42
|
return True
|
|
40
43
|
|
|
41
44
|
|
|
45
|
+
def stop_mission_failed(state_machine: "StateMachine") -> bool:
|
|
46
|
+
stopped_mission_response: ControlMissionResponse = (
|
|
47
|
+
state_machine._make_control_mission_response()
|
|
48
|
+
)
|
|
49
|
+
state_machine.events.api_requests.stop_mission.output.put(stopped_mission_response)
|
|
50
|
+
return True
|
|
51
|
+
|
|
52
|
+
|
|
42
53
|
def stop_return_home_mission_cleanup(state_machine: "StateMachine") -> bool:
|
|
43
54
|
if state_machine.current_mission is None:
|
|
44
55
|
state_machine._queue_empty_response()
|
|
45
56
|
state_machine.reset_state_machine()
|
|
46
57
|
return True
|
|
47
58
|
|
|
59
|
+
if not check_for_event_without_consumption(
|
|
60
|
+
state_machine.events.api_requests.start_mission.input
|
|
61
|
+
):
|
|
62
|
+
state_machine.current_mission.status = MissionStatus.Cancelled
|
|
63
|
+
|
|
64
|
+
for task in state_machine.current_mission.tasks:
|
|
65
|
+
if task.status in [
|
|
66
|
+
TaskStatus.NotStarted,
|
|
67
|
+
TaskStatus.InProgress,
|
|
68
|
+
TaskStatus.Paused,
|
|
69
|
+
]:
|
|
70
|
+
task.status = TaskStatus.Cancelled
|
|
71
|
+
|
|
72
|
+
stopped_mission_response: ControlMissionResponse = (
|
|
73
|
+
state_machine._make_control_mission_response()
|
|
74
|
+
)
|
|
75
|
+
state_machine.events.api_requests.stop_mission.output.put(
|
|
76
|
+
stopped_mission_response
|
|
77
|
+
)
|
|
78
|
+
|
|
48
79
|
state_machine._finalize()
|
|
49
80
|
return True
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def stop_return_home_mission_failed(state_machine: "StateMachine") -> bool:
|
|
84
|
+
if check_for_event_without_consumption(
|
|
85
|
+
state_machine.events.api_requests.start_mission.input
|
|
86
|
+
):
|
|
87
|
+
return True
|
|
88
|
+
stopped_mission_response: ControlMissionResponse = (
|
|
89
|
+
state_machine._make_control_mission_response()
|
|
90
|
+
)
|
|
91
|
+
state_machine.events.api_requests.stop_mission.output.put(stopped_mission_response)
|
|
92
|
+
return True
|
|
@@ -15,7 +15,9 @@ from isar.state_machine.transitions.functions.start_mission import (
|
|
|
15
15
|
)
|
|
16
16
|
from isar.state_machine.transitions.functions.stop import (
|
|
17
17
|
stop_mission_cleanup,
|
|
18
|
+
stop_mission_failed,
|
|
18
19
|
stop_return_home_mission_cleanup,
|
|
20
|
+
stop_return_home_mission_failed,
|
|
19
21
|
trigger_stop_mission_event,
|
|
20
22
|
)
|
|
21
23
|
from isar.state_machine.transitions.functions.utils import def_transition
|
|
@@ -30,13 +32,23 @@ def get_mission_transitions(state_machine: "StateMachine") -> List[dict]:
|
|
|
30
32
|
"trigger": "pause",
|
|
31
33
|
"source": state_machine.monitor_state,
|
|
32
34
|
"dest": state_machine.paused_state,
|
|
33
|
-
"
|
|
35
|
+
"conditions": def_transition(state_machine, pause_mission),
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"trigger": "pause",
|
|
39
|
+
"source": state_machine.monitor_state,
|
|
40
|
+
"dest": state_machine.monitor_state,
|
|
34
41
|
},
|
|
35
42
|
{
|
|
36
43
|
"trigger": "resume",
|
|
37
44
|
"source": state_machine.paused_state,
|
|
38
45
|
"dest": state_machine.monitor_state,
|
|
39
|
-
"
|
|
46
|
+
"conditions": def_transition(state_machine, resume_mission),
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"trigger": "resume",
|
|
50
|
+
"source": state_machine.paused_state,
|
|
51
|
+
"dest": state_machine.paused_state,
|
|
40
52
|
},
|
|
41
53
|
{
|
|
42
54
|
"trigger": "stop",
|
|
@@ -56,6 +68,18 @@ def get_mission_transitions(state_machine: "StateMachine") -> List[dict]:
|
|
|
56
68
|
"dest": state_machine.await_next_mission_state,
|
|
57
69
|
"before": def_transition(state_machine, stop_mission_cleanup),
|
|
58
70
|
},
|
|
71
|
+
{
|
|
72
|
+
"trigger": "mission_stopping_failed",
|
|
73
|
+
"source": state_machine.stopping_state,
|
|
74
|
+
"dest": state_machine.monitor_state,
|
|
75
|
+
"before": def_transition(state_machine, stop_mission_failed),
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"trigger": "return_home_mission_stopping_failed",
|
|
79
|
+
"source": state_machine.stopping_state,
|
|
80
|
+
"dest": state_machine.returning_home_state,
|
|
81
|
+
"before": def_transition(state_machine, stop_return_home_mission_failed),
|
|
82
|
+
},
|
|
59
83
|
{
|
|
60
84
|
"trigger": "return_home_mission_stopped",
|
|
61
85
|
"source": state_machine.stopping_state,
|
|
@@ -63,7 +63,7 @@ def get_return_home_transitions(state_machine: "StateMachine") -> List[dict]:
|
|
|
63
63
|
"trigger": "return_home_failed",
|
|
64
64
|
"source": state_machine.returning_home_state,
|
|
65
65
|
"dest": state_machine.robot_standing_still_state,
|
|
66
|
-
"before": def_transition(state_machine,
|
|
66
|
+
"before": def_transition(state_machine, report_failed_mission_and_finalize),
|
|
67
67
|
},
|
|
68
68
|
]
|
|
69
69
|
return return_home_transitions
|
isar/storage/blob_storage.py
CHANGED
|
@@ -4,7 +4,6 @@ from typing import Union
|
|
|
4
4
|
|
|
5
5
|
from azure.core.exceptions import ResourceExistsError
|
|
6
6
|
from azure.storage.blob import BlobClient, BlobServiceClient, ContainerClient
|
|
7
|
-
from dependency_injector.wiring import inject
|
|
8
7
|
|
|
9
8
|
from isar.config.keyvault.keyvault_service import Keyvault
|
|
10
9
|
from isar.config.settings import settings
|
|
@@ -15,7 +14,6 @@ from robot_interface.models.mission.mission import Mission
|
|
|
15
14
|
|
|
16
15
|
|
|
17
16
|
class BlobStorage(StorageInterface):
|
|
18
|
-
@inject
|
|
19
17
|
def __init__(
|
|
20
18
|
self, keyvault: Keyvault, container_name: str = settings.BLOB_CONTAINER
|
|
21
19
|
) -> None:
|
isar/storage/uploader.py
CHANGED
|
@@ -6,8 +6,6 @@ from queue import Empty, Queue
|
|
|
6
6
|
from threading import Event
|
|
7
7
|
from typing import List, Union
|
|
8
8
|
|
|
9
|
-
from dependency_injector.wiring import inject
|
|
10
|
-
|
|
11
9
|
from isar.config.settings import settings
|
|
12
10
|
from isar.models.communication.queues.events import Events
|
|
13
11
|
from isar.storage.storage_interface import StorageException, StorageInterface
|
|
@@ -63,7 +61,6 @@ class BlobItem(UploaderQueueItem):
|
|
|
63
61
|
|
|
64
62
|
|
|
65
63
|
class Uploader:
|
|
66
|
-
@inject
|
|
67
64
|
def __init__(
|
|
68
65
|
self,
|
|
69
66
|
events: Events,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: isar
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.31.0
|
|
4
4
|
Summary: Integration and Supervisory control of Autonomous Robots
|
|
5
5
|
Author-email: Equinor ASA <fg_robots_dev@equinor.com>
|
|
6
6
|
License: Eclipse Public License version 2.0
|
|
@@ -113,9 +113,6 @@ Requires-Dist: fastapi-azure-auth
|
|
|
113
113
|
Requires-Dist: fastapi
|
|
114
114
|
Requires-Dist: dependency-injector
|
|
115
115
|
Requires-Dist: numpy
|
|
116
|
-
Requires-Dist: opencensus-ext-azure
|
|
117
|
-
Requires-Dist: opencensus-ext-logging
|
|
118
|
-
Requires-Dist: opencensus-ext-requests
|
|
119
116
|
Requires-Dist: paho-mqtt
|
|
120
117
|
Requires-Dist: pydantic_settings
|
|
121
118
|
Requires-Dist: pydantic
|
|
@@ -126,6 +123,12 @@ Requires-Dist: requests-toolbelt
|
|
|
126
123
|
Requires-Dist: requests
|
|
127
124
|
Requires-Dist: transitions
|
|
128
125
|
Requires-Dist: uvicorn
|
|
126
|
+
Requires-Dist: opentelemetry-api
|
|
127
|
+
Requires-Dist: opentelemetry-sdk
|
|
128
|
+
Requires-Dist: opentelemetry-exporter-otlp
|
|
129
|
+
Requires-Dist: opentelemetry-instrumentation-fastapi
|
|
130
|
+
Requires-Dist: azure-monitor-opentelemetry
|
|
131
|
+
Requires-Dist: azure-monitor-opentelemetry-exporter>=1.0.0b38
|
|
129
132
|
Provides-Extra: dev
|
|
130
133
|
Requires-Dist: black; extra == "dev"
|
|
131
134
|
Requires-Dist: isort; extra == "dev"
|
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
isar/__init__.py,sha256=cH8p8bVveu3FUL6kBhldcSlLaoHgD82Kd0-SwSNfGXw,87
|
|
2
2
|
isar/modules.py,sha256=QBB1pge1i17HVMLA5n-qd9K3APCrX9bFF2vlfjheOhU,4778
|
|
3
|
-
isar/script.py,sha256=
|
|
3
|
+
isar/script.py,sha256=OC0O3y5HO5OAstg7g-tLKgF7mulKfglkpztDRk9PvT0,6159
|
|
4
4
|
isar/apis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
-
isar/apis/api.py,sha256=
|
|
5
|
+
isar/apis/api.py,sha256=B0fVZPKtnvrxzk48xoazGPYsJVjjBH4IL6glDJ3PGWI,13328
|
|
6
6
|
isar/apis/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
-
isar/apis/models/models.py,sha256=
|
|
8
|
-
isar/apis/models/start_mission_definition.py,sha256=
|
|
9
|
-
isar/apis/robot_control/robot_controller.py,sha256=
|
|
7
|
+
isar/apis/models/models.py,sha256=GMOss2C8lBeRFV7E37mLwSOM6RhiyLQLcLBRzm_51d4,1835
|
|
8
|
+
isar/apis/models/start_mission_definition.py,sha256=m9M5dZCmvRM1b4N8xYGquCSplSr4GDk376s2QoVL8F4,6231
|
|
9
|
+
isar/apis/robot_control/robot_controller.py,sha256=0EHjMqOBdfJlMrCItGPz5X-4X2kc-2XlNnUU2LOcLfc,1219
|
|
10
10
|
isar/apis/schedule/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
-
isar/apis/schedule/scheduling_controller.py,sha256=
|
|
11
|
+
isar/apis/schedule/scheduling_controller.py,sha256=yQM2HMgelBnbkzPR_tLHOY2EbThUcSO5jMA6Xtp5FQA,9915
|
|
12
12
|
isar/apis/security/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
13
|
isar/apis/security/authentication.py,sha256=Se2puhe2TUBmfio2RLma52-VSLRhqvWgu0Cd1bhdwMo,2000
|
|
14
14
|
isar/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
15
|
isar/config/configuration_error.py,sha256=rO6WOhafX6xvVib8WxV-eY483Z0PpN-9PxGsq5ATfKc,46
|
|
16
|
-
isar/config/log.py,sha256=
|
|
16
|
+
isar/config/log.py,sha256=_zeHrsI4XqoHc1Um50PLHFjlwGiClM_M5CzcXoqwZuY,1380
|
|
17
17
|
isar/config/logging.conf,sha256=mYO1xf27gAopEMHhGzY7-mwyfN16rwRLkPNMvy3zn2g,1127
|
|
18
|
-
isar/config/
|
|
18
|
+
isar/config/open_telemetry.py,sha256=7hO6lR4lgK3IRZVh0a4shxIuamyt9paLM6d_FwXw5OY,2661
|
|
19
|
+
isar/config/settings.py,sha256=-fBxs0TUGmoCX4nF1Rwg0YMZ-WQ6qsqFZpWHxqwOrlk,13029
|
|
19
20
|
isar/config/certs/ca-cert.pem,sha256=qoNljfad_qcMxhXJIUMLd7nT-Qwf_d4dYSdoOFEOE8I,2179
|
|
20
21
|
isar/config/keyvault/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
22
|
isar/config/keyvault/keyvault_error.py,sha256=zvPCsZLjboxsxthYkxpRERCTFxYV8R5WmACewAUQLwk,41
|
|
@@ -35,7 +36,7 @@ isar/config/predefined_missions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm
|
|
|
35
36
|
isar/config/predefined_missions/default.json,sha256=NWo9y5noPmpjlNUxLnZK95Sz7DIEaUR-ISYlw3MP8i0,1251
|
|
36
37
|
isar/config/predefined_missions/default_turtlebot.json,sha256=8Vk1_0P0BBsG0vwh4vwIYINiiWioErHZ0Ppjq3ctaPM,2143
|
|
37
38
|
isar/mission_planner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
38
|
-
isar/mission_planner/local_planner.py,sha256=
|
|
39
|
+
isar/mission_planner/local_planner.py,sha256=Mkg3vvUBF1jImfQnaFvXLNpKVadR21X4mwDd_wHqJ2w,2520
|
|
39
40
|
isar/mission_planner/mission_planner_interface.py,sha256=UgpPIM4FbrWOD7fGY3Ul64k3uYb8wo0FwSWGewYoVbc,485
|
|
40
41
|
isar/mission_planner/sequential_task_selector.py,sha256=66agRPHuJnEa1vArPyty4muTasAZ50XPjjrSaTdY_Cc,643
|
|
41
42
|
isar/mission_planner/task_selector_interface.py,sha256=pnLeaGPIuyXThcflZ_A7YL2b2xQjFT88hAZidkMomxU,707
|
|
@@ -43,13 +44,13 @@ isar/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
43
44
|
isar/models/communication/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
44
45
|
isar/models/communication/message.py,sha256=ge2EdUXRnYkiEu5TIAYJFQET_5w-N8MRgc2Y31vetno,155
|
|
45
46
|
isar/models/communication/queues/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
46
|
-
isar/models/communication/queues/events.py,sha256=
|
|
47
|
+
isar/models/communication/queues/events.py,sha256=mZt1ZarqmyDW_y42w7aD1Iv-m7HLwrpUyOh3pM4w79Q,2412
|
|
47
48
|
isar/models/communication/queues/queue_io.py,sha256=AnHWUCkZ0tunkxKKeBarq-OUkRM97IaMfA-a1pmf1cQ,394
|
|
48
49
|
isar/models/communication/queues/queue_timeout_error.py,sha256=rF8TlNF7RHS_ueTZ5mp7aFkhLY1j0dcwMwH-Ba6lVpE,45
|
|
49
|
-
isar/models/communication/queues/queue_utils.py,sha256=
|
|
50
|
+
isar/models/communication/queues/queue_utils.py,sha256=3kw7LxMVxCUM7JF7DVQgxbiUzMBMtVa8nwfpr7xDSGc,872
|
|
50
51
|
isar/models/communication/queues/status_queue.py,sha256=on8kvlNsG6MJjEVsyqtBswIpmOdOggQiKr7F5x0T3jw,514
|
|
51
52
|
isar/models/mission_metadata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
52
|
-
isar/robot/robot.py,sha256=
|
|
53
|
+
isar/robot/robot.py,sha256=MmdrJzC4U_dGK3NLA6vgGNi0awNQwFvsPDsr9030fso,5431
|
|
53
54
|
isar/robot/robot_start_mission.py,sha256=vQKsKnrWQuY70jEK-qeeaZYpXxQH4vElorczYZheXTQ,3423
|
|
54
55
|
isar/robot/robot_status.py,sha256=FpkTIAA-O5vKuyU7fnWn2YXtbstq5qbk9XSxbn_0MXU,2015
|
|
55
56
|
isar/robot/robot_stop_mission.py,sha256=jUyfemvbyigxrlIp9aKPn-PvarhagJEgajQPS_LgJ7g,2442
|
|
@@ -66,47 +67,47 @@ isar/services/service_connections/mqtt/robot_info_publisher.py,sha256=AxokGk51hR
|
|
|
66
67
|
isar/services/service_connections/stid/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
67
68
|
isar/services/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
68
69
|
isar/services/utilities/queue_utilities.py,sha256=Pw3hehSwkXJNeDv-bDVDfs58VOwtt3i5hpiJ2ZpphuQ,1225
|
|
69
|
-
isar/services/utilities/robot_utilities.py,sha256=
|
|
70
|
-
isar/services/utilities/scheduling_utilities.py,sha256=
|
|
70
|
+
isar/services/utilities/robot_utilities.py,sha256=4zCigsLXfqDC8POHchktSq81zr1_pTaRve_LQsVr6Mk,514
|
|
71
|
+
isar/services/utilities/scheduling_utilities.py,sha256=eXeTEe4JmP2mgVd77DC5SLGTPjpG6O9IhN330dAyh-4,11122
|
|
71
72
|
isar/services/utilities/threaded_request.py,sha256=py4G-_RjnIdHljmKFAcQ6ddqMmp-ZYV39Ece-dqRqjs,1874
|
|
72
73
|
isar/state_machine/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
73
|
-
isar/state_machine/state_machine.py,sha256=
|
|
74
|
+
isar/state_machine/state_machine.py,sha256=6rksxhG4OLoZYfRSB5wfpqHXQUperbRjqwnY-6ue8Gk,13099
|
|
74
75
|
isar/state_machine/states_enum.py,sha256=Z3dO6k6JmQAZ1lzcR58oVCxoCky_-ZS9MaL3RSaNbZ4,434
|
|
75
|
-
isar/state_machine/generic_states/idle.py,sha256=
|
|
76
|
-
isar/state_machine/generic_states/ongoing_mission.py,sha256=
|
|
76
|
+
isar/state_machine/generic_states/idle.py,sha256=uXVHtKeX3jPZC7iVmic1sKD6nLtSOVynrHNiUCdTDcw,4371
|
|
77
|
+
isar/state_machine/generic_states/ongoing_mission.py,sha256=ns6mbaSJvjM7JAbl1txPA9VdjxTv4iWKGbdYahtTtGc,11571
|
|
77
78
|
isar/state_machine/generic_states/robot_unavailable.py,sha256=pHmed1uRPwCWAR4uBJmdnxi9WX8veTbGG9ephmROhm0,1851
|
|
78
79
|
isar/state_machine/states/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
79
80
|
isar/state_machine/states/await_next_mission.py,sha256=U0oGi-O05S-ZvdhpQRuirrY3ZBbblURo5U95PsscMlQ,573
|
|
80
81
|
isar/state_machine/states/blocked_protective_stop.py,sha256=KDux2lm5kwEEarnDt9FG4MFrWbYUzs1_DX5hu2ILIlI,675
|
|
81
82
|
isar/state_machine/states/home.py,sha256=2v7BFQn4QZ0npOrXpWLWCoHD5IpSyAJr-vQCS3MQWJs,514
|
|
82
|
-
isar/state_machine/states/monitor.py,sha256=
|
|
83
|
+
isar/state_machine/states/monitor.py,sha256=BVrfZb-EWIdNYTC75F8HCi_OOtjBYbphrwki98p1WdE,597
|
|
83
84
|
isar/state_machine/states/offline.py,sha256=vZnBMVDnehZ-0gPsHNVRpZtb8OBBFkeEnq2olo_Ep6M,609
|
|
84
85
|
isar/state_machine/states/paused.py,sha256=IgnWBM6WXj3wjFZMARAPWIpzWGyUSW35DVBvNHuiNP8,1460
|
|
85
86
|
isar/state_machine/states/returning_home.py,sha256=BBQo3PoNP-THlvJa5gQr0fNBhInh_Ox1L2OeH8evUq8,638
|
|
86
87
|
isar/state_machine/states/robot_standing_still.py,sha256=RbOZSiQz72tWAJID5ksgzcb4lND6OniiG35IE1wMUHk,579
|
|
87
|
-
isar/state_machine/states/stopping.py,sha256=
|
|
88
|
-
isar/state_machine/states/unknown_status.py,sha256=
|
|
89
|
-
isar/state_machine/transitions/mission.py,sha256=
|
|
90
|
-
isar/state_machine/transitions/return_home.py,sha256=
|
|
88
|
+
isar/state_machine/states/stopping.py,sha256=yJE7KT1aGo_qd1VTETfg1rTrlM-hKKQYKQp7xu4py_Y,2854
|
|
89
|
+
isar/state_machine/states/unknown_status.py,sha256=qfIoL5f7Hj-aZKq5tCM1FctkuEI6SwgpQuixzKx11Zk,2428
|
|
90
|
+
isar/state_machine/transitions/mission.py,sha256=Lsiee_hSn5wd7KWpmvIdaG-49f6HGdkCdiXAo5L0ciE,5803
|
|
91
|
+
isar/state_machine/transitions/return_home.py,sha256=6aBpKpozT48RJ__w13gv-r7dSz-fEOCzkAuKq5Hwm6k,2728
|
|
91
92
|
isar/state_machine/transitions/robot_status.py,sha256=c1ceyWRGCtx-KTDtxHXRD7oPbt8TQ2ej24A0wyim8vc,2720
|
|
92
93
|
isar/state_machine/transitions/functions/fail_mission.py,sha256=_6HqBMALDinFZ4yh5GMpeqqgV5tw5i8OVMj5UDdqesg,495
|
|
93
94
|
isar/state_machine/transitions/functions/finish_mission.py,sha256=TRQrk7HdllmAkwsp25HRZAFAk46Y1hLx3jmkIAKrHDI,1442
|
|
94
|
-
isar/state_machine/transitions/functions/pause.py,sha256=
|
|
95
|
-
isar/state_machine/transitions/functions/resume.py,sha256=
|
|
95
|
+
isar/state_machine/transitions/functions/pause.py,sha256=oaIFd4aZnbeaHb-EGQE9ozJctskqXKsRKkNc68M8sp0,1975
|
|
96
|
+
isar/state_machine/transitions/functions/resume.py,sha256=HgAEn4jQOPkVPWWZCAh7dqnIerdF8nGcgFcZ1KsCNSQ,2104
|
|
96
97
|
isar/state_machine/transitions/functions/return_home.py,sha256=UlniwYvpz74hxqgN0TyVv3LCmiMsqsosKEtEGLqkNj0,1139
|
|
97
98
|
isar/state_machine/transitions/functions/robot_status.py,sha256=xhKZ5u_X8uDvnhvGnAIABuKaPXeVqFjkgj4H2Om-j_A,1013
|
|
98
99
|
isar/state_machine/transitions/functions/start_mission.py,sha256=ricRfhLH1_lNpqWxneMZcm7ps2YfY6sQGHkiT0Glf6M,2564
|
|
99
|
-
isar/state_machine/transitions/functions/stop.py,sha256=
|
|
100
|
+
isar/state_machine/transitions/functions/stop.py,sha256=JK4hjGc3QtgSzvCWeOr1YG61SH1QOhmVNjw_jOnahQg,3123
|
|
100
101
|
isar/state_machine/transitions/functions/utils.py,sha256=Wa72Ocq4QT1E6qkpEJZQ3h5o33pGvx7Tlkt2JZ2Grbk,314
|
|
101
102
|
isar/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
102
|
-
isar/storage/blob_storage.py,sha256=
|
|
103
|
+
isar/storage/blob_storage.py,sha256=D67y3Z939iXoRxs8npOuKOhgs2o6dYz2ivTm5IXXhJE,3168
|
|
103
104
|
isar/storage/local_storage.py,sha256=Bnmoi5gyN8r-oRh0aHrOdGqaH3JqRScFKMRXYojW5kY,1855
|
|
104
105
|
isar/storage/storage_interface.py,sha256=DYDry4I7aZpDHJhsBF6s8zrgokFAc7fdKJKfA8AvL7o,828
|
|
105
|
-
isar/storage/uploader.py,sha256=
|
|
106
|
+
isar/storage/uploader.py,sha256=1F4M34aVnD828WV62muTIE04vj3D52lrTOOh8r6SgwA,9464
|
|
106
107
|
isar/storage/utilities.py,sha256=oLH0Rp7UtrQQdilfITnmXO1Z0ExdeDhBImYHid55vBA,3449
|
|
107
|
-
isar-1.
|
|
108
|
+
isar-1.31.0.dist-info/licenses/LICENSE,sha256=3fc2-ebLwHWwzfQbulGNRdcNob3SBQeCfEVUDYxsuqw,14058
|
|
108
109
|
robot_interface/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
109
|
-
robot_interface/robot_interface.py,sha256
|
|
110
|
+
robot_interface/robot_interface.py,sha256=-jCAKkZ2eiyzUyHVQmOzw4hMgLWR7pE8MHj-WZo85ZY,7978
|
|
110
111
|
robot_interface/test_robot_interface.py,sha256=FV1urn7SbsMyWBIcTKjsBwAG4IsXeZ6pLHE0mA9EGGs,692
|
|
111
112
|
robot_interface/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
112
113
|
robot_interface/models/exceptions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -117,7 +118,7 @@ robot_interface/models/inspection/inspection.py,sha256=2T8czQcNt9J1M96tKGQA6P3s5
|
|
|
117
118
|
robot_interface/models/mission/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
118
119
|
robot_interface/models/mission/mission.py,sha256=MQ9p5cuclLXexaZu9bkDh5-aN99eunvYC0vP-Z_kUwI,960
|
|
119
120
|
robot_interface/models/mission/status.py,sha256=UOCARLfLxLFXJEjfIH7aXYXO7xajOKBJsxz-Wd6gZQ4,740
|
|
120
|
-
robot_interface/models/mission/task.py,sha256=
|
|
121
|
+
robot_interface/models/mission/task.py,sha256=YzaqJ_KIIm-3S2Y2-BG4Pdkc8sjFMzMx5jj8FtXSmFg,4744
|
|
121
122
|
robot_interface/models/robots/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
122
123
|
robot_interface/models/robots/battery_state.py,sha256=ktOtJ8ltdK0k_i7BoqYfhc5dbOzIG6Oo-uWC67fCWio,98
|
|
123
124
|
robot_interface/models/robots/media.py,sha256=8A-CuuubfngzPprs6zWB9hSaqe3jzgsE8rcCzRX2Uto,227
|
|
@@ -128,8 +129,8 @@ robot_interface/telemetry/payloads.py,sha256=PpvmV7XeGgfhc_aRUYFOdwBTwV2x8TwTBIN
|
|
|
128
129
|
robot_interface/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
129
130
|
robot_interface/utilities/json_service.py,sha256=qkzVkb60Gi_pto-b5n1vNzCrQze2yqgIJqSLNLYj1Fg,1034
|
|
130
131
|
robot_interface/utilities/uuid_string_factory.py,sha256=_NQIbBQ56w0qqO0MUDP6aPpHbxW7ATRhK8HnQiBSLkc,76
|
|
131
|
-
isar-1.
|
|
132
|
-
isar-1.
|
|
133
|
-
isar-1.
|
|
134
|
-
isar-1.
|
|
135
|
-
isar-1.
|
|
132
|
+
isar-1.31.0.dist-info/METADATA,sha256=RZo3tvmuEPeEdu1CQeqgKAQyWysrlJExNPMVn8zjqPs,31217
|
|
133
|
+
isar-1.31.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
134
|
+
isar-1.31.0.dist-info/entry_points.txt,sha256=TFam7uNNw7J0iiDYzsH2gfG0u1eV1wh3JTw_HkhgKLk,49
|
|
135
|
+
isar-1.31.0.dist-info/top_level.txt,sha256=UwIML2RtuQKCyJJkatcSnyp6-ldDjboB9k9JgKipO-U,21
|
|
136
|
+
isar-1.31.0.dist-info/RECORD,,
|
|
@@ -221,10 +221,7 @@ class RobotInterface(metaclass=ABCMeta):
|
|
|
221
221
|
@abstractmethod
|
|
222
222
|
def robot_status(self) -> RobotStatus:
|
|
223
223
|
"""
|
|
224
|
-
Method which returns an enum indicating
|
|
225
|
-
the interface which is used to communicate with the robot. This is further used
|
|
226
|
-
by ISAR to indicate whether the ISAR instance is fully functional and may be
|
|
227
|
-
used by other systems.
|
|
224
|
+
Method which returns an enum indicating the status of the robot.
|
|
228
225
|
|
|
229
226
|
Returns
|
|
230
227
|
-------
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|