isar 1.31.0__tar.gz → 1.32.0__tar.gz
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-1.31.0 → isar-1.32.0}/PKG-INFO +1 -1
- {isar-1.31.0 → isar-1.32.0}/requirements.txt +21 -21
- {isar-1.31.0 → isar-1.32.0}/src/isar/apis/api.py +18 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/apis/schedule/scheduling_controller.py +16 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/config/log.py +1 -2
- isar-1.32.0/src/isar/config/logging.conf +37 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/config/open_telemetry.py +2 -8
- {isar-1.31.0 → isar-1.32.0}/src/isar/config/settings.py +4 -0
- isar-1.32.0/src/isar/eventhandlers/eventhandler.py +93 -0
- isar-1.32.0/src/isar/models/events.py +119 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/modules.py +1 -1
- {isar-1.31.0 → isar-1.32.0}/src/isar/robot/robot.py +16 -18
- {isar-1.31.0 → isar-1.32.0}/src/isar/robot/robot_start_mission.py +8 -14
- {isar-1.31.0 → isar-1.32.0}/src/isar/robot/robot_status.py +2 -3
- {isar-1.31.0 → isar-1.32.0}/src/isar/robot/robot_stop_mission.py +3 -9
- {isar-1.31.0 → isar-1.32.0}/src/isar/robot/robot_task_status.py +3 -7
- {isar-1.31.0 → isar-1.32.0}/src/isar/script.py +9 -17
- {isar-1.31.0 → isar-1.32.0}/src/isar/services/utilities/scheduling_utilities.py +45 -23
- {isar-1.31.0 → isar-1.32.0}/src/isar/state_machine/state_machine.py +104 -9
- isar-1.32.0/src/isar/state_machine/states/await_next_mission.py +55 -0
- isar-1.32.0/src/isar/state_machine/states/blocked_protective_stop.py +33 -0
- isar-1.32.0/src/isar/state_machine/states/home.py +50 -0
- isar-1.32.0/src/isar/state_machine/states/intervention_needed.py +43 -0
- isar-1.32.0/src/isar/state_machine/states/monitor.py +93 -0
- isar-1.32.0/src/isar/state_machine/states/offline.py +34 -0
- isar-1.32.0/src/isar/state_machine/states/paused.py +30 -0
- isar-1.32.0/src/isar/state_machine/states/returning_home.py +85 -0
- isar-1.32.0/src/isar/state_machine/states/robot_standing_still.py +50 -0
- isar-1.32.0/src/isar/state_machine/states/stopping.py +60 -0
- isar-1.32.0/src/isar/state_machine/states/unknown_status.py +47 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/state_machine/states_enum.py +1 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/state_machine/transitions/functions/fail_mission.py +7 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/state_machine/transitions/functions/robot_status.py +4 -5
- {isar-1.31.0 → isar-1.32.0}/src/isar/state_machine/transitions/functions/stop.py +3 -12
- {isar-1.31.0 → isar-1.32.0}/src/isar/state_machine/transitions/mission.py +0 -6
- {isar-1.31.0 → isar-1.32.0}/src/isar/state_machine/transitions/return_home.py +14 -2
- isar-1.32.0/src/isar/state_machine/utils/common_event_handlers.py +166 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/storage/uploader.py +1 -1
- {isar-1.31.0 → isar-1.32.0}/src/isar.egg-info/PKG-INFO +1 -1
- {isar-1.31.0 → isar-1.32.0}/src/isar.egg-info/SOURCES.txt +5 -15
- {isar-1.31.0 → isar-1.32.0}/src/robot_interface/models/mission/status.py +1 -0
- {isar-1.31.0 → isar-1.32.0}/src/robot_interface/telemetry/payloads.py +8 -0
- {isar-1.31.0 → isar-1.32.0}/tests/isar/apis/scheduler/test_scheduler_router.py +2 -2
- isar-1.32.0/tests/isar/models/communication/test_events.py +44 -0
- isar-1.32.0/tests/isar/services/utilities/test_queue_utilities.py +34 -0
- {isar-1.31.0 → isar-1.32.0}/tests/isar/services/utilities/test_scheduling_utilities.py +4 -6
- {isar-1.31.0 → isar-1.32.0}/tests/isar/state_machine/states/test_monitor.py +9 -5
- {isar-1.31.0 → isar-1.32.0}/tests/isar/state_machine/test_state_machine.py +19 -11
- {isar-1.31.0 → isar-1.32.0}/tests/test_double/robot_interface.py +39 -40
- isar-1.31.0/src/isar/config/logging.conf +0 -58
- isar-1.31.0/src/isar/models/communication/message.py +0 -8
- isar-1.31.0/src/isar/models/communication/queues/events.py +0 -58
- isar-1.31.0/src/isar/models/communication/queues/queue_io.py +0 -12
- isar-1.31.0/src/isar/models/communication/queues/queue_timeout_error.py +0 -2
- isar-1.31.0/src/isar/models/communication/queues/queue_utils.py +0 -38
- isar-1.31.0/src/isar/models/communication/queues/status_queue.py +0 -22
- isar-1.31.0/src/isar/services/utilities/queue_utilities.py +0 -39
- isar-1.31.0/src/isar/state_machine/generic_states/idle.py +0 -133
- isar-1.31.0/src/isar/state_machine/generic_states/ongoing_mission.py +0 -309
- isar-1.31.0/src/isar/state_machine/generic_states/robot_unavailable.py +0 -61
- isar-1.31.0/src/isar/state_machine/states/await_next_mission.py +0 -20
- isar-1.31.0/src/isar/state_machine/states/blocked_protective_stop.py +0 -24
- isar-1.31.0/src/isar/state_machine/states/home.py +0 -19
- isar-1.31.0/src/isar/state_machine/states/monitor.py +0 -22
- isar-1.31.0/src/isar/state_machine/states/offline.py +0 -22
- isar-1.31.0/src/isar/state_machine/states/paused.py +0 -44
- isar-1.31.0/src/isar/state_machine/states/returning_home.py +0 -24
- isar-1.31.0/src/isar/state_machine/states/robot_standing_still.py +0 -20
- isar-1.31.0/src/isar/state_machine/states/stopping.py +0 -75
- isar-1.31.0/src/isar/state_machine/states/unknown_status.py +0 -74
- isar-1.31.0/tests/isar/models/communication/test_queues.py +0 -49
- isar-1.31.0/tests/isar/services/utilities/__init__.py +0 -0
- isar-1.31.0/tests/isar/services/utilities/test_queue_utilities.py +0 -38
- isar-1.31.0/tests/isar/state_machine/__init__.py +0 -0
- isar-1.31.0/tests/isar/state_machine/states/__init__.py +0 -0
- isar-1.31.0/tests/test_double/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/.dockerignore +0 -0
- {isar-1.31.0 → isar-1.32.0}/.env.test +0 -0
- {isar-1.31.0 → isar-1.32.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {isar-1.31.0 → isar-1.32.0}/.github/ISSUE_TEMPLATE/feature.md +0 -0
- {isar-1.31.0 → isar-1.32.0}/.github/ISSUE_TEMPLATE/improvement.md +0 -0
- {isar-1.31.0 → isar-1.32.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {isar-1.31.0 → isar-1.32.0}/.github/release.yml +0 -0
- {isar-1.31.0 → isar-1.32.0}/.github/workflows/compile_requirements.yml +0 -0
- {isar-1.31.0 → isar-1.32.0}/.github/workflows/project_automations.yml +0 -0
- {isar-1.31.0 → isar-1.32.0}/.github/workflows/pythonpackage.yml +0 -0
- {isar-1.31.0 → isar-1.32.0}/.github/workflows/pythonpublish.yml +0 -0
- {isar-1.31.0 → isar-1.32.0}/.github/workflows/stale.yml +0 -0
- {isar-1.31.0 → isar-1.32.0}/.gitignore +0 -0
- {isar-1.31.0 → isar-1.32.0}/.pre-commit-config.yaml +0 -0
- {isar-1.31.0 → isar-1.32.0}/LICENSE +0 -0
- {isar-1.31.0 → isar-1.32.0}/README.md +0 -0
- {isar-1.31.0 → isar-1.32.0}/SECURITY.md +0 -0
- {isar-1.31.0 → isar-1.32.0}/docs/Makefile +0 -0
- {isar-1.31.0 → isar-1.32.0}/docs/full_state_machine_diagram.png +0 -0
- {isar-1.31.0 → isar-1.32.0}/docs/make.bat +0 -0
- {isar-1.31.0 → isar-1.32.0}/docs/mission_state_machine_diagram.png +0 -0
- {isar-1.31.0 → isar-1.32.0}/docs/robot_status_state_machine_diagram.png +0 -0
- {isar-1.31.0 → isar-1.32.0}/docs/rst_processing.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/docs/source/conf.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/docs/source/index.rst +0 -0
- {isar-1.31.0 → isar-1.32.0}/docs/source/readme_link.md +0 -0
- {isar-1.31.0 → isar-1.32.0}/docs/update_state_diagram.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/main.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/pyproject.toml +0 -0
- {isar-1.31.0 → isar-1.32.0}/radixconfig.yml +0 -0
- {isar-1.31.0 → isar-1.32.0}/setup.cfg +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/apis/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/apis/models/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/apis/models/models.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/apis/models/start_mission_definition.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/apis/robot_control/robot_controller.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/apis/schedule/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/apis/security/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/apis/security/authentication.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/config/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/config/certs/ca-cert.pem +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/config/configuration_error.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/config/keyvault/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/config/keyvault/keyvault_error.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/config/keyvault/keyvault_service.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/config/maps/JSP1_intermediate_deck.json +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/config/maps/JSP1_weather_deck.json +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/config/maps/default_map.json +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/config/maps/klab_b.json +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/config/maps/klab_compressor.json +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/config/maps/klab_turtlebot.json +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/config/maps/turtleworld.json +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/config/predefined_mission_definition/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/config/predefined_mission_definition/default_exr.json +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/config/predefined_mission_definition/default_mission.json +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/config/predefined_mission_definition/default_turtlebot.json +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/config/predefined_missions/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/config/predefined_missions/default.json +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/config/predefined_missions/default_turtlebot.json +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/mission_planner/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/mission_planner/local_planner.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/mission_planner/mission_planner_interface.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/mission_planner/sequential_task_selector.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/mission_planner/task_selector_interface.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/models/__init__.py +0 -0
- {isar-1.31.0/src/isar/models/communication → isar-1.32.0/src/isar/services}/__init__.py +0 -0
- {isar-1.31.0/src/isar/models/communication/queues → isar-1.32.0/src/isar/services/auth}/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/services/auth/azure_credentials.py +0 -0
- {isar-1.31.0/src/isar/models/mission_metadata → isar-1.32.0/src/isar/services/service_connections}/__init__.py +0 -0
- {isar-1.31.0/src/isar/services → isar-1.32.0/src/isar/services/service_connections/mqtt}/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/services/service_connections/mqtt/mqtt_client.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/services/service_connections/mqtt/robot_heartbeat_publisher.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/services/service_connections/mqtt/robot_info_publisher.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/services/service_connections/request_handler.py +0 -0
- {isar-1.31.0/src/isar/services/auth → isar-1.32.0/src/isar/services/utilities}/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/services/utilities/robot_utilities.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/services/utilities/threaded_request.py +0 -0
- {isar-1.31.0/src/isar/services/service_connections → isar-1.32.0/src/isar/state_machine}/__init__.py +0 -0
- {isar-1.31.0/src/isar/services/service_connections/mqtt → isar-1.32.0/src/isar/state_machine/states}/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/state_machine/transitions/functions/finish_mission.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/state_machine/transitions/functions/pause.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/state_machine/transitions/functions/resume.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/state_machine/transitions/functions/return_home.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/state_machine/transitions/functions/start_mission.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/state_machine/transitions/functions/utils.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/state_machine/transitions/robot_status.py +0 -0
- {isar-1.31.0/src/isar/services/service_connections/stid → isar-1.32.0/src/isar/storage}/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/storage/blob_storage.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/storage/local_storage.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/storage/storage_interface.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar/storage/utilities.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar.egg-info/dependency_links.txt +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar.egg-info/entry_points.txt +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar.egg-info/requires.txt +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/isar.egg-info/top_level.txt +0 -0
- {isar-1.31.0/src/isar/services/utilities → isar-1.32.0/src/robot_interface}/__init__.py +0 -0
- {isar-1.31.0/src/isar/state_machine → isar-1.32.0/src/robot_interface/models}/__init__.py +0 -0
- {isar-1.31.0/src/isar/state_machine/states → isar-1.32.0/src/robot_interface/models/exceptions}/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/robot_interface/models/exceptions/robot_exceptions.py +0 -0
- {isar-1.31.0/src/isar/storage → isar-1.32.0/src/robot_interface/models/initialize}/__init__.py +0 -0
- {isar-1.31.0/src/robot_interface → isar-1.32.0/src/robot_interface/models/inspection}/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/robot_interface/models/inspection/inspection.py +0 -0
- {isar-1.31.0/src/robot_interface/models → isar-1.32.0/src/robot_interface/models/mission}/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/robot_interface/models/mission/mission.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/robot_interface/models/mission/task.py +0 -0
- {isar-1.31.0/src/robot_interface/models/exceptions → isar-1.32.0/src/robot_interface/models/robots}/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/robot_interface/models/robots/battery_state.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/robot_interface/models/robots/media.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/robot_interface/models/robots/robot_model.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/robot_interface/robot_interface.py +0 -0
- {isar-1.31.0/src/robot_interface/models/initialize → isar-1.32.0/src/robot_interface/telemetry}/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/robot_interface/telemetry/mqtt_client.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/robot_interface/test_robot_interface.py +0 -0
- {isar-1.31.0/src/robot_interface/models/inspection → isar-1.32.0/src/robot_interface/utilities}/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/robot_interface/utilities/json_service.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/src/robot_interface/utilities/uuid_string_factory.py +0 -0
- {isar-1.31.0/src/robot_interface/models/mission → isar-1.32.0/tests}/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/tests/conftest.py +0 -0
- {isar-1.31.0/src/robot_interface/models/robots → isar-1.32.0/tests/integration}/__init__.py +0 -0
- {isar-1.31.0/src/robot_interface/telemetry → isar-1.32.0/tests/integration/turtlebot}/__init__.py +0 -0
- {isar-1.31.0/src/robot_interface/utilities → isar-1.32.0/tests/integration/turtlebot/config}/__init__.py +0 -0
- {isar-1.31.0/tests → isar-1.32.0/tests/integration/turtlebot/config/maps}/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/tests/integration/turtlebot/config/maps/turtleworld.json +0 -0
- {isar-1.31.0/tests/integration → isar-1.32.0/tests/integration/turtlebot/config/missions}/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/tests/integration/turtlebot/config/missions/default.json +0 -0
- {isar-1.31.0 → isar-1.32.0}/tests/integration/turtlebot/test_successful_mission.py +0 -0
- {isar-1.31.0/tests/integration/turtlebot → isar-1.32.0/tests/isar}/__init__.py +0 -0
- {isar-1.31.0/tests/integration/turtlebot/config → isar-1.32.0/tests/isar/apis}/__init__.py +0 -0
- {isar-1.31.0/tests/integration/turtlebot/config/maps → isar-1.32.0/tests/isar/apis/models}/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/tests/isar/apis/models/example_mission_definition.json +0 -0
- {isar-1.31.0 → isar-1.32.0}/tests/isar/apis/models/test_start_mission_definition.py +0 -0
- {isar-1.31.0/tests/integration/turtlebot/config/missions → isar-1.32.0/tests/isar/apis/scheduler}/__init__.py +0 -0
- {isar-1.31.0/tests/isar → isar-1.32.0/tests/isar/apis/security}/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/tests/isar/apis/security/test_authentication.py +0 -0
- {isar-1.31.0/tests/isar/apis → isar-1.32.0/tests/isar/mission}/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/tests/isar/mission/test_mission.py +0 -0
- {isar-1.31.0/tests/isar/apis → isar-1.32.0/tests/isar}/models/__init__.py +0 -0
- {isar-1.31.0/tests/isar/apis/scheduler → isar-1.32.0/tests/isar/models/communication}/__init__.py +0 -0
- {isar-1.31.0/tests/isar/apis/security → isar-1.32.0/tests/isar/services}/__init__.py +0 -0
- {isar-1.31.0/tests/isar/mission → isar-1.32.0/tests/isar/services/readers}/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/tests/isar/services/readers/test_mission_reader.py +0 -0
- {isar-1.31.0/tests/isar/models → isar-1.32.0/tests/isar/services/service_connections}/__init__.py +0 -0
- {isar-1.31.0/tests/isar/models/communication → isar-1.32.0/tests/isar/services/service_connections/echo}/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/tests/isar/services/service_connections/test_base_request_handler.py +0 -0
- {isar-1.31.0/tests/isar/services → isar-1.32.0/tests/isar/services/utilities}/__init__.py +0 -0
- {isar-1.31.0/tests/isar/services/readers → isar-1.32.0/tests/isar/state_machine}/__init__.py +0 -0
- {isar-1.31.0/tests/isar/services/service_connections → isar-1.32.0/tests/isar/state_machine/states}/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/tests/isar/storage/test_blob_storage.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/tests/isar/storage/test_uploader.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/tests/test_data/test_map_config/test_map_config.json +0 -0
- {isar-1.31.0 → isar-1.32.0}/tests/test_data/test_mission_not_working.json +0 -0
- {isar-1.31.0 → isar-1.32.0}/tests/test_data/test_mission_working.json +0 -0
- {isar-1.31.0 → isar-1.32.0}/tests/test_data/test_mission_working_no_tasks.json +0 -0
- {isar-1.31.0 → isar-1.32.0}/tests/test_data/test_thermal_image_mission.json +0 -0
- {isar-1.31.0/tests/isar/services/service_connections/echo → isar-1.32.0/tests/test_double}/__init__.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/tests/test_double/blob_storage.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/tests/test_double/mission_definition.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/tests/test_double/mqtt_client.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/tests/test_double/pose.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/tests/test_double/request.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/tests/test_double/status.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/tests/test_double/task.py +0 -0
- {isar-1.31.0 → isar-1.32.0}/tests/test_double/token.py +0 -0
|
@@ -31,7 +31,7 @@ azure-identity==1.23.1
|
|
|
31
31
|
# isar (pyproject.toml)
|
|
32
32
|
azure-keyvault-secrets==4.10.0
|
|
33
33
|
# via isar (pyproject.toml)
|
|
34
|
-
azure-monitor-opentelemetry==1.6.
|
|
34
|
+
azure-monitor-opentelemetry==1.6.13
|
|
35
35
|
# via isar (pyproject.toml)
|
|
36
36
|
azure-monitor-opentelemetry-exporter==1.0.0b40
|
|
37
37
|
# via
|
|
@@ -117,7 +117,7 @@ numpy==2.3.2
|
|
|
117
117
|
# scipy
|
|
118
118
|
oauthlib==3.3.1
|
|
119
119
|
# via requests-oauthlib
|
|
120
|
-
opentelemetry-api==1.
|
|
120
|
+
opentelemetry-api==1.36.0
|
|
121
121
|
# via
|
|
122
122
|
# azure-core-tracing-opentelemetry
|
|
123
123
|
# azure-monitor-opentelemetry-exporter
|
|
@@ -137,17 +137,17 @@ opentelemetry-api==1.35.0
|
|
|
137
137
|
# opentelemetry-instrumentation-wsgi
|
|
138
138
|
# opentelemetry-sdk
|
|
139
139
|
# opentelemetry-semantic-conventions
|
|
140
|
-
opentelemetry-exporter-otlp==1.
|
|
140
|
+
opentelemetry-exporter-otlp==1.36.0
|
|
141
141
|
# via isar (pyproject.toml)
|
|
142
|
-
opentelemetry-exporter-otlp-proto-common==1.
|
|
142
|
+
opentelemetry-exporter-otlp-proto-common==1.36.0
|
|
143
143
|
# via
|
|
144
144
|
# opentelemetry-exporter-otlp-proto-grpc
|
|
145
145
|
# opentelemetry-exporter-otlp-proto-http
|
|
146
|
-
opentelemetry-exporter-otlp-proto-grpc==1.
|
|
146
|
+
opentelemetry-exporter-otlp-proto-grpc==1.36.0
|
|
147
147
|
# via opentelemetry-exporter-otlp
|
|
148
|
-
opentelemetry-exporter-otlp-proto-http==1.
|
|
148
|
+
opentelemetry-exporter-otlp-proto-http==1.36.0
|
|
149
149
|
# via opentelemetry-exporter-otlp
|
|
150
|
-
opentelemetry-instrumentation==0.
|
|
150
|
+
opentelemetry-instrumentation==0.57b0
|
|
151
151
|
# via
|
|
152
152
|
# opentelemetry-instrumentation-asgi
|
|
153
153
|
# opentelemetry-instrumentation-dbapi
|
|
@@ -159,38 +159,38 @@ opentelemetry-instrumentation==0.56b0
|
|
|
159
159
|
# opentelemetry-instrumentation-urllib
|
|
160
160
|
# opentelemetry-instrumentation-urllib3
|
|
161
161
|
# opentelemetry-instrumentation-wsgi
|
|
162
|
-
opentelemetry-instrumentation-asgi==0.
|
|
162
|
+
opentelemetry-instrumentation-asgi==0.57b0
|
|
163
163
|
# via opentelemetry-instrumentation-fastapi
|
|
164
|
-
opentelemetry-instrumentation-dbapi==0.
|
|
164
|
+
opentelemetry-instrumentation-dbapi==0.57b0
|
|
165
165
|
# via opentelemetry-instrumentation-psycopg2
|
|
166
|
-
opentelemetry-instrumentation-django==0.
|
|
166
|
+
opentelemetry-instrumentation-django==0.57b0
|
|
167
167
|
# via azure-monitor-opentelemetry
|
|
168
|
-
opentelemetry-instrumentation-fastapi==0.
|
|
168
|
+
opentelemetry-instrumentation-fastapi==0.57b0
|
|
169
169
|
# via
|
|
170
170
|
# azure-monitor-opentelemetry
|
|
171
171
|
# isar (pyproject.toml)
|
|
172
|
-
opentelemetry-instrumentation-flask==0.
|
|
172
|
+
opentelemetry-instrumentation-flask==0.57b0
|
|
173
173
|
# via azure-monitor-opentelemetry
|
|
174
|
-
opentelemetry-instrumentation-psycopg2==0.
|
|
174
|
+
opentelemetry-instrumentation-psycopg2==0.57b0
|
|
175
175
|
# via azure-monitor-opentelemetry
|
|
176
|
-
opentelemetry-instrumentation-requests==0.
|
|
176
|
+
opentelemetry-instrumentation-requests==0.57b0
|
|
177
177
|
# via azure-monitor-opentelemetry
|
|
178
|
-
opentelemetry-instrumentation-urllib==0.
|
|
178
|
+
opentelemetry-instrumentation-urllib==0.57b0
|
|
179
179
|
# via azure-monitor-opentelemetry
|
|
180
|
-
opentelemetry-instrumentation-urllib3==0.
|
|
180
|
+
opentelemetry-instrumentation-urllib3==0.57b0
|
|
181
181
|
# via azure-monitor-opentelemetry
|
|
182
|
-
opentelemetry-instrumentation-wsgi==0.
|
|
182
|
+
opentelemetry-instrumentation-wsgi==0.57b0
|
|
183
183
|
# via
|
|
184
184
|
# opentelemetry-instrumentation-django
|
|
185
185
|
# opentelemetry-instrumentation-flask
|
|
186
|
-
opentelemetry-proto==1.
|
|
186
|
+
opentelemetry-proto==1.36.0
|
|
187
187
|
# via
|
|
188
188
|
# opentelemetry-exporter-otlp-proto-common
|
|
189
189
|
# opentelemetry-exporter-otlp-proto-grpc
|
|
190
190
|
# opentelemetry-exporter-otlp-proto-http
|
|
191
191
|
opentelemetry-resource-detector-azure==0.1.5
|
|
192
192
|
# via azure-monitor-opentelemetry
|
|
193
|
-
opentelemetry-sdk==1.
|
|
193
|
+
opentelemetry-sdk==1.36.0
|
|
194
194
|
# via
|
|
195
195
|
# azure-monitor-opentelemetry
|
|
196
196
|
# azure-monitor-opentelemetry-exporter
|
|
@@ -198,7 +198,7 @@ opentelemetry-sdk==1.35.0
|
|
|
198
198
|
# opentelemetry-exporter-otlp-proto-grpc
|
|
199
199
|
# opentelemetry-exporter-otlp-proto-http
|
|
200
200
|
# opentelemetry-resource-detector-azure
|
|
201
|
-
opentelemetry-semantic-conventions==0.
|
|
201
|
+
opentelemetry-semantic-conventions==0.57b0
|
|
202
202
|
# via
|
|
203
203
|
# opentelemetry-instrumentation
|
|
204
204
|
# opentelemetry-instrumentation-asgi
|
|
@@ -211,7 +211,7 @@ opentelemetry-semantic-conventions==0.56b0
|
|
|
211
211
|
# opentelemetry-instrumentation-urllib3
|
|
212
212
|
# opentelemetry-instrumentation-wsgi
|
|
213
213
|
# opentelemetry-sdk
|
|
214
|
-
opentelemetry-util-http==0.
|
|
214
|
+
opentelemetry-util-http==0.57b0
|
|
215
215
|
# via
|
|
216
216
|
# opentelemetry-instrumentation-asgi
|
|
217
217
|
# opentelemetry-instrumentation-django
|
|
@@ -245,6 +245,24 @@ class API:
|
|
|
245
245
|
},
|
|
246
246
|
},
|
|
247
247
|
)
|
|
248
|
+
router.add_api_route(
|
|
249
|
+
path="/schedule/release-intervention-needed",
|
|
250
|
+
endpoint=self.scheduling_controller.release_intervention_needed,
|
|
251
|
+
methods=["POST"],
|
|
252
|
+
dependencies=[authentication_dependency],
|
|
253
|
+
summary="Release the intervention needed state",
|
|
254
|
+
responses={
|
|
255
|
+
HTTPStatus.OK.value: {
|
|
256
|
+
"description": "Robot released from intervention needed state"
|
|
257
|
+
},
|
|
258
|
+
HTTPStatus.CONFLICT.value: {
|
|
259
|
+
"description": "Conflict - Invalid command in the current state"
|
|
260
|
+
},
|
|
261
|
+
HTTPStatus.INTERNAL_SERVER_ERROR.value: {
|
|
262
|
+
"description": "Internal Server Error - Current state of state machine unknown"
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
)
|
|
248
266
|
router.add_api_route(
|
|
249
267
|
path="/schedule/move_arm/{arm_pose_literal}",
|
|
250
268
|
endpoint=self.scheduling_controller.start_move_arm_mission,
|
|
@@ -256,6 +256,22 @@ class SchedulingController:
|
|
|
256
256
|
self.scheduling_utilities.start_mission(mission=mission)
|
|
257
257
|
return self._api_response(mission)
|
|
258
258
|
|
|
259
|
+
def release_intervention_needed(self) -> None:
|
|
260
|
+
self.logger.info("Received request to release intervention needed state")
|
|
261
|
+
|
|
262
|
+
state: States = self.scheduling_utilities.get_state()
|
|
263
|
+
|
|
264
|
+
if state != States.InterventionNeeded:
|
|
265
|
+
error_message = f"Conflict - Release intervention needed command received in invalid state - State: {state}"
|
|
266
|
+
self.logger.warning(error_message)
|
|
267
|
+
raise HTTPException(
|
|
268
|
+
status_code=HTTPStatus.CONFLICT,
|
|
269
|
+
detail=error_message,
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
self.scheduling_utilities.release_intervention_needed()
|
|
273
|
+
self.logger.info("Released intervention needed state successfully")
|
|
274
|
+
|
|
259
275
|
def _api_response(self, mission: Mission) -> StartMissionResponse:
|
|
260
276
|
return StartMissionResponse(
|
|
261
277
|
id=mission.id,
|
|
@@ -5,11 +5,10 @@ from importlib.resources import as_file, files
|
|
|
5
5
|
import yaml
|
|
6
6
|
from uvicorn.logging import ColourizedFormatter
|
|
7
7
|
|
|
8
|
-
from isar.config.keyvault.keyvault_service import Keyvault
|
|
9
8
|
from isar.config.settings import settings
|
|
10
9
|
|
|
11
10
|
|
|
12
|
-
def setup_loggers(
|
|
11
|
+
def setup_loggers() -> None:
|
|
13
12
|
log_levels: dict = settings.LOG_LEVELS
|
|
14
13
|
log_config = load_log_config()
|
|
15
14
|
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
version: 1
|
|
2
|
+
formatters:
|
|
3
|
+
simple:
|
|
4
|
+
format: '%(asctime)s - %(levelname)s - %(name)s - %(message)s'
|
|
5
|
+
colourized:
|
|
6
|
+
style: "{"
|
|
7
|
+
format: "{asctime} - {levelprefix:<8} - {name} - {message}"
|
|
8
|
+
loggers:
|
|
9
|
+
console:
|
|
10
|
+
handlers: []
|
|
11
|
+
propagate: no
|
|
12
|
+
main:
|
|
13
|
+
handlers: []
|
|
14
|
+
propagate: no
|
|
15
|
+
api:
|
|
16
|
+
handlers: []
|
|
17
|
+
propagate: no
|
|
18
|
+
mqtt:
|
|
19
|
+
handlers: []
|
|
20
|
+
propagate: no
|
|
21
|
+
state_machine:
|
|
22
|
+
handlers: []
|
|
23
|
+
propagate: no
|
|
24
|
+
uploader:
|
|
25
|
+
handlers: []
|
|
26
|
+
propagate: no
|
|
27
|
+
urllib3:
|
|
28
|
+
handlers: []
|
|
29
|
+
uvicorn:
|
|
30
|
+
handlers: []
|
|
31
|
+
propagate: no
|
|
32
|
+
azure:
|
|
33
|
+
handlers: []
|
|
34
|
+
propagate: no
|
|
35
|
+
root:
|
|
36
|
+
level: DEBUG
|
|
37
|
+
handlers: []
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
|
|
3
|
-
from azure.identity import ManagedIdentityCredential
|
|
4
3
|
from azure.monitor.opentelemetry.exporter import (
|
|
5
4
|
AzureMonitorLogExporter,
|
|
6
5
|
AzureMonitorTraceExporter,
|
|
@@ -57,12 +56,7 @@ def get_azure_monitor_exporters() -> (
|
|
|
57
56
|
Else use Azure Managed Identity to create Azure Monitor Exporters.
|
|
58
57
|
"""
|
|
59
58
|
connection_string = settings.APPLICATIONINSIGHTS_CONNECTION_STRING
|
|
60
|
-
|
|
61
|
-
|
|
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)
|
|
59
|
+
trace_exporter = AzureMonitorTraceExporter(connection_string=connection_string)
|
|
60
|
+
log_exporter = AzureMonitorLogExporter(connection_string=connection_string)
|
|
67
61
|
|
|
68
62
|
return trace_exporter, log_exporter
|
|
@@ -224,6 +224,9 @@ class Settings(BaseSettings):
|
|
|
224
224
|
default="robot_heartbeat", validate_default=True
|
|
225
225
|
)
|
|
226
226
|
TOPIC_ISAR_STARTUP: str = Field(default="startup", validate_default=True)
|
|
227
|
+
TOPIC_ISAR_INTERVENTION_NEEDED: str = Field(
|
|
228
|
+
default="intervention_needed", validate_default=True
|
|
229
|
+
)
|
|
227
230
|
|
|
228
231
|
# Logging
|
|
229
232
|
|
|
@@ -275,6 +278,7 @@ class Settings(BaseSettings):
|
|
|
275
278
|
"TOPIC_ISAR_INSPECTION_RESULT",
|
|
276
279
|
"TOPIC_ISAR_INSPECTION_VALUE",
|
|
277
280
|
"TOPIC_ISAR_STARTUP",
|
|
281
|
+
"TOPIC_ISAR_INTERVENTION_NEEDED",
|
|
278
282
|
)
|
|
279
283
|
@classmethod
|
|
280
284
|
def prefix_isar_topics(cls, v: Any, info: ValidationInfo):
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import time
|
|
3
|
+
from copy import deepcopy
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from threading import Event as ThreadEvent
|
|
6
|
+
from typing import TYPE_CHECKING, Callable, Generic, List, Optional, TypeVar
|
|
7
|
+
|
|
8
|
+
from transitions import State
|
|
9
|
+
|
|
10
|
+
from isar.config.settings import settings
|
|
11
|
+
from isar.models.events import Event
|
|
12
|
+
|
|
13
|
+
T = TypeVar("T")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class EventHandlerMapping(Generic[T]):
|
|
18
|
+
name: str
|
|
19
|
+
event: Event[T]
|
|
20
|
+
handler: Callable[[Event[T]], Optional[Callable]]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass
|
|
24
|
+
class TimeoutHandlerMapping:
|
|
25
|
+
name: str
|
|
26
|
+
timeout_in_seconds: float
|
|
27
|
+
handler: Callable[[], Optional[Callable]]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
if TYPE_CHECKING:
|
|
31
|
+
from isar.state_machine.state_machine import StateMachine
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class EventHandlerBase(State):
|
|
35
|
+
def __init__(
|
|
36
|
+
self,
|
|
37
|
+
state_machine: "StateMachine",
|
|
38
|
+
state_name: str,
|
|
39
|
+
event_handler_mappings: List[EventHandlerMapping],
|
|
40
|
+
timers: List[TimeoutHandlerMapping] = [],
|
|
41
|
+
) -> None:
|
|
42
|
+
|
|
43
|
+
super().__init__(name=state_name, on_enter=self.start)
|
|
44
|
+
self.state_machine: "StateMachine" = state_machine
|
|
45
|
+
self.logger = logging.getLogger("state_machine")
|
|
46
|
+
self.events = state_machine.events
|
|
47
|
+
self.signal_state_machine_to_stop: ThreadEvent = (
|
|
48
|
+
state_machine.signal_state_machine_to_stop
|
|
49
|
+
)
|
|
50
|
+
self.event_handler_mappings = event_handler_mappings
|
|
51
|
+
self.state_name: str = state_name
|
|
52
|
+
self.timers = timers
|
|
53
|
+
|
|
54
|
+
def start(self) -> None:
|
|
55
|
+
self.state_machine.update_state()
|
|
56
|
+
self._run()
|
|
57
|
+
|
|
58
|
+
def stop(self) -> None:
|
|
59
|
+
return
|
|
60
|
+
|
|
61
|
+
def _run(self) -> None:
|
|
62
|
+
should_exit_state: bool = False
|
|
63
|
+
timers = deepcopy(self.timers)
|
|
64
|
+
entered_time = time.time()
|
|
65
|
+
while True:
|
|
66
|
+
if self.signal_state_machine_to_stop.is_set():
|
|
67
|
+
self.logger.info(
|
|
68
|
+
"Stopping state machine from %s state", self.state_name
|
|
69
|
+
)
|
|
70
|
+
break
|
|
71
|
+
|
|
72
|
+
for timer in timers:
|
|
73
|
+
if time.time() - entered_time > timer.timeout_in_seconds:
|
|
74
|
+
transition_func = timer.handler()
|
|
75
|
+
timers.remove(timer)
|
|
76
|
+
if transition_func is not None:
|
|
77
|
+
transition_func()
|
|
78
|
+
should_exit_state = True
|
|
79
|
+
break
|
|
80
|
+
|
|
81
|
+
if should_exit_state:
|
|
82
|
+
break
|
|
83
|
+
|
|
84
|
+
for handler_mapping in self.event_handler_mappings:
|
|
85
|
+
transition_func = handler_mapping.handler(handler_mapping.event)
|
|
86
|
+
if transition_func is not None:
|
|
87
|
+
transition_func()
|
|
88
|
+
should_exit_state = True
|
|
89
|
+
break
|
|
90
|
+
|
|
91
|
+
if should_exit_state:
|
|
92
|
+
break
|
|
93
|
+
time.sleep(settings.FSM_SLEEP_TIME)
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
from collections import deque
|
|
2
|
+
from queue import Empty, Queue
|
|
3
|
+
from typing import Generic, Optional, TypeVar
|
|
4
|
+
|
|
5
|
+
from transitions import State
|
|
6
|
+
|
|
7
|
+
from isar.apis.models.models import ControlMissionResponse
|
|
8
|
+
from isar.config.settings import settings
|
|
9
|
+
from robot_interface.models.exceptions.robot_exceptions import ErrorMessage
|
|
10
|
+
from robot_interface.models.mission.mission import Mission
|
|
11
|
+
from robot_interface.models.mission.status import RobotStatus, TaskStatus
|
|
12
|
+
from robot_interface.models.mission.task import TASKS
|
|
13
|
+
|
|
14
|
+
T = TypeVar("T")
|
|
15
|
+
T1 = TypeVar("T1")
|
|
16
|
+
T2 = TypeVar("T2")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Event(Queue[T]):
|
|
20
|
+
def __init__(self) -> None:
|
|
21
|
+
super().__init__(maxsize=1)
|
|
22
|
+
|
|
23
|
+
def trigger_event(self, data: T) -> None:
|
|
24
|
+
self.put(data)
|
|
25
|
+
|
|
26
|
+
def consume_event(self, timeout: int = None) -> Optional[T]:
|
|
27
|
+
try:
|
|
28
|
+
return self.get(block=timeout is not None, timeout=timeout)
|
|
29
|
+
except Empty:
|
|
30
|
+
if timeout is not None:
|
|
31
|
+
raise EventTimeoutError
|
|
32
|
+
return None
|
|
33
|
+
|
|
34
|
+
def clear_event(self) -> None:
|
|
35
|
+
while True:
|
|
36
|
+
try:
|
|
37
|
+
self.get(block=False)
|
|
38
|
+
except Empty:
|
|
39
|
+
break
|
|
40
|
+
|
|
41
|
+
def has_event(self) -> bool:
|
|
42
|
+
return (
|
|
43
|
+
self.qsize() != 0
|
|
44
|
+
) # Queue size is not reliable, but should be sufficient for this case
|
|
45
|
+
|
|
46
|
+
def check(self) -> Optional[T]:
|
|
47
|
+
if not self._qsize():
|
|
48
|
+
return None
|
|
49
|
+
with self.mutex:
|
|
50
|
+
queueList = list(self.queue)
|
|
51
|
+
return queueList.pop()
|
|
52
|
+
|
|
53
|
+
def update(self, item: T):
|
|
54
|
+
with self.mutex:
|
|
55
|
+
self.queue: deque[T] = deque()
|
|
56
|
+
self.queue.append(item)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class Events:
|
|
60
|
+
def __init__(self) -> None:
|
|
61
|
+
self.api_requests: APIRequests = APIRequests()
|
|
62
|
+
self.state_machine_events: StateMachineEvents = StateMachineEvents()
|
|
63
|
+
self.robot_service_events: RobotServiceEvents = RobotServiceEvents()
|
|
64
|
+
|
|
65
|
+
self.upload_queue: Queue = Queue(maxsize=10)
|
|
66
|
+
|
|
67
|
+
if settings.MQTT_ENABLED:
|
|
68
|
+
self.mqtt_queue: Queue = Queue()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class APIEvent(Generic[T1, T2]):
|
|
72
|
+
"""
|
|
73
|
+
Creates input and output event. The events are defined such that the input is from
|
|
74
|
+
api to state machine while the output is from state machine to api.
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
def __init__(self):
|
|
78
|
+
self.input: Event[T1] = Event()
|
|
79
|
+
self.output: Event[T2] = Event()
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class APIRequests:
|
|
83
|
+
def __init__(self) -> None:
|
|
84
|
+
self.start_mission: APIEvent[Mission, bool] = APIEvent()
|
|
85
|
+
self.stop_mission: APIEvent[str, ControlMissionResponse] = APIEvent()
|
|
86
|
+
self.pause_mission: APIEvent[bool, ControlMissionResponse] = APIEvent()
|
|
87
|
+
self.resume_mission: APIEvent[bool, ControlMissionResponse] = APIEvent()
|
|
88
|
+
self.return_home: APIEvent[bool, bool] = APIEvent()
|
|
89
|
+
self.release_intervention_needed: APIEvent[bool, bool] = APIEvent()
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class StateMachineEvents:
|
|
93
|
+
def __init__(self) -> None:
|
|
94
|
+
self.start_mission: Event[Mission] = Event()
|
|
95
|
+
self.stop_mission: Event[bool] = Event()
|
|
96
|
+
self.pause_mission: Event[bool] = Event()
|
|
97
|
+
self.task_status_request: Event[str] = Event()
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class RobotServiceEvents:
|
|
101
|
+
def __init__(self) -> None:
|
|
102
|
+
self.task_status_updated: Event[TaskStatus] = Event()
|
|
103
|
+
self.task_status_failed: Event[ErrorMessage] = Event()
|
|
104
|
+
self.mission_started: Event[bool] = Event()
|
|
105
|
+
self.mission_failed: Event[ErrorMessage] = Event()
|
|
106
|
+
self.robot_status_changed: Event[bool] = Event()
|
|
107
|
+
self.mission_failed_to_stop: Event[ErrorMessage] = Event()
|
|
108
|
+
self.mission_successfully_stopped: Event[bool] = Event()
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class SharedState:
|
|
112
|
+
def __init__(self) -> None:
|
|
113
|
+
self.state: Event[State] = Event()
|
|
114
|
+
self.robot_status: Event[RobotStatus] = Event()
|
|
115
|
+
self.state_machine_current_task: Event[TASKS] = Event()
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class EventTimeoutError(Exception):
|
|
119
|
+
pass
|
|
@@ -12,7 +12,7 @@ from isar.config.settings import settings
|
|
|
12
12
|
from isar.mission_planner.local_planner import LocalPlanner
|
|
13
13
|
from isar.mission_planner.sequential_task_selector import SequentialTaskSelector
|
|
14
14
|
from isar.mission_planner.task_selector_interface import TaskSelectorInterface
|
|
15
|
-
from isar.models.
|
|
15
|
+
from isar.models.events import Events, SharedState
|
|
16
16
|
from isar.robot.robot import Robot
|
|
17
17
|
from isar.services.utilities.robot_utilities import RobotUtilities
|
|
18
18
|
from isar.services.utilities.scheduling_utilities import SchedulingUtilities
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from
|
|
3
|
-
from threading import Event
|
|
2
|
+
from threading import Event as ThreadEvent
|
|
4
3
|
from typing import Optional
|
|
5
4
|
|
|
6
|
-
from isar.models.
|
|
5
|
+
from isar.models.events import (
|
|
6
|
+
Event,
|
|
7
7
|
Events,
|
|
8
8
|
RobotServiceEvents,
|
|
9
9
|
SharedState,
|
|
10
10
|
StateMachineEvents,
|
|
11
11
|
)
|
|
12
|
-
from isar.models.communication.queues.queue_utils import check_for_event, trigger_event
|
|
13
12
|
from isar.robot.robot_start_mission import RobotStartMissionThread
|
|
14
13
|
from isar.robot.robot_status import RobotStatusThread
|
|
15
14
|
from isar.robot.robot_stop_mission import RobotStopMissionThread
|
|
16
15
|
from isar.robot.robot_task_status import RobotTaskStatusThread
|
|
17
16
|
from robot_interface.models.exceptions.robot_exceptions import ErrorMessage, ErrorReason
|
|
17
|
+
from robot_interface.models.mission.mission import Mission
|
|
18
18
|
from robot_interface.robot_interface import RobotInterface
|
|
19
19
|
|
|
20
20
|
|
|
@@ -31,7 +31,7 @@ class Robot(object):
|
|
|
31
31
|
self.robot_status_thread: Optional[RobotStatusThread] = None
|
|
32
32
|
self.robot_task_status_thread: Optional[RobotTaskStatusThread] = None
|
|
33
33
|
self.stop_mission_thread: Optional[RobotStopMissionThread] = None
|
|
34
|
-
self.signal_thread_quitting:
|
|
34
|
+
self.signal_thread_quitting: ThreadEvent = ThreadEvent()
|
|
35
35
|
|
|
36
36
|
def stop(self) -> None:
|
|
37
37
|
self.signal_thread_quitting.set()
|
|
@@ -53,8 +53,8 @@ class Robot(object):
|
|
|
53
53
|
self.robot_task_status_thread = None
|
|
54
54
|
self.start_mission_thread = None
|
|
55
55
|
|
|
56
|
-
def
|
|
57
|
-
start_mission =
|
|
56
|
+
def _start_mission_event_handler(self, event: Event[Mission]) -> None:
|
|
57
|
+
start_mission = event.consume_event()
|
|
58
58
|
if start_mission is not None:
|
|
59
59
|
if (
|
|
60
60
|
self.start_mission_thread is not None
|
|
@@ -72,8 +72,8 @@ class Robot(object):
|
|
|
72
72
|
)
|
|
73
73
|
self.start_mission_thread.start()
|
|
74
74
|
|
|
75
|
-
def
|
|
76
|
-
task_id: str =
|
|
75
|
+
def _task_status_request_handler(self, event: Event[str]) -> None:
|
|
76
|
+
task_id: str = event.consume_event()
|
|
77
77
|
if task_id:
|
|
78
78
|
self.robot_task_status_thread = RobotTaskStatusThread(
|
|
79
79
|
self.robot_service_events,
|
|
@@ -83,8 +83,8 @@ class Robot(object):
|
|
|
83
83
|
)
|
|
84
84
|
self.robot_task_status_thread.start()
|
|
85
85
|
|
|
86
|
-
def
|
|
87
|
-
if
|
|
86
|
+
def _stop_mission_request_handler(self, event: Event[bool]) -> None:
|
|
87
|
+
if event.consume_event():
|
|
88
88
|
if (
|
|
89
89
|
self.stop_mission_thread is not None
|
|
90
90
|
and self.stop_mission_thread.is_alive()
|
|
@@ -102,8 +102,8 @@ class Robot(object):
|
|
|
102
102
|
error_reason=ErrorReason.RobotStillStartingMissionException,
|
|
103
103
|
error_description=error_description,
|
|
104
104
|
)
|
|
105
|
-
trigger_event(
|
|
106
|
-
|
|
105
|
+
self.robot_service_events.mission_failed_to_stop.trigger_event(
|
|
106
|
+
error_message
|
|
107
107
|
)
|
|
108
108
|
return
|
|
109
109
|
self.stop_mission_thread = RobotStopMissionThread(
|
|
@@ -118,14 +118,12 @@ class Robot(object):
|
|
|
118
118
|
self.robot_status_thread.start()
|
|
119
119
|
|
|
120
120
|
while not self.signal_thread_quitting.wait(0):
|
|
121
|
-
self.
|
|
122
|
-
self.state_machine_events.start_mission
|
|
123
|
-
)
|
|
121
|
+
self._start_mission_event_handler(self.state_machine_events.start_mission)
|
|
124
122
|
|
|
125
|
-
self.
|
|
123
|
+
self._task_status_request_handler(
|
|
126
124
|
self.state_machine_events.task_status_request
|
|
127
125
|
)
|
|
128
126
|
|
|
129
|
-
self.
|
|
127
|
+
self._stop_mission_request_handler(self.state_machine_events.stop_mission)
|
|
130
128
|
|
|
131
129
|
self.logger.info("Exiting robot service main thread")
|
|
@@ -2,11 +2,7 @@ import logging
|
|
|
2
2
|
from threading import Event, Thread
|
|
3
3
|
|
|
4
4
|
from isar.config.settings import settings
|
|
5
|
-
from isar.models.
|
|
6
|
-
from isar.models.communication.queues.queue_utils import (
|
|
7
|
-
trigger_event,
|
|
8
|
-
trigger_event_without_data,
|
|
9
|
-
)
|
|
5
|
+
from isar.models.events import RobotServiceEvents
|
|
10
6
|
from robot_interface.models.exceptions.robot_exceptions import (
|
|
11
7
|
ErrorMessage,
|
|
12
8
|
RobotException,
|
|
@@ -44,13 +40,13 @@ class RobotStartMissionThread(Thread):
|
|
|
44
40
|
self.logger.error(
|
|
45
41
|
f"Mission is infeasible and cannot be scheduled because: {e.error_description}"
|
|
46
42
|
)
|
|
47
|
-
trigger_event(
|
|
48
|
-
self.robot_service_events.mission_failed,
|
|
43
|
+
self.robot_service_events.mission_failed.trigger_event(
|
|
49
44
|
ErrorMessage(
|
|
50
45
|
error_reason=e.error_reason,
|
|
51
46
|
error_description=e.error_description,
|
|
52
|
-
)
|
|
47
|
+
)
|
|
53
48
|
)
|
|
49
|
+
|
|
54
50
|
break
|
|
55
51
|
except RobotException as e:
|
|
56
52
|
retries += 1
|
|
@@ -66,12 +62,11 @@ class RobotStartMissionThread(Thread):
|
|
|
66
62
|
f"{e.error_description}"
|
|
67
63
|
)
|
|
68
64
|
|
|
69
|
-
trigger_event(
|
|
70
|
-
self.robot_service_events.mission_failed,
|
|
65
|
+
self.robot_service_events.mission_failed.trigger_event(
|
|
71
66
|
ErrorMessage(
|
|
72
67
|
error_reason=e.error_reason,
|
|
73
68
|
error_description=e.error_description,
|
|
74
|
-
)
|
|
69
|
+
)
|
|
75
70
|
)
|
|
76
71
|
break
|
|
77
72
|
|
|
@@ -79,12 +74,11 @@ class RobotStartMissionThread(Thread):
|
|
|
79
74
|
|
|
80
75
|
started_mission = True
|
|
81
76
|
except RobotInfeasibleMissionException as e:
|
|
82
|
-
trigger_event(
|
|
83
|
-
self.robot_service_events.mission_failed,
|
|
77
|
+
self.robot_service_events.mission_failed.trigger_event(
|
|
84
78
|
ErrorMessage(
|
|
85
79
|
error_reason=e.error_reason, error_description=e.error_description
|
|
86
80
|
),
|
|
87
81
|
)
|
|
88
82
|
|
|
89
83
|
if started_mission:
|
|
90
|
-
|
|
84
|
+
self.robot_service_events.mission_started.trigger_event(True)
|
|
@@ -3,8 +3,7 @@ import time
|
|
|
3
3
|
from threading import Event, Thread
|
|
4
4
|
|
|
5
5
|
from isar.config.settings import settings
|
|
6
|
-
from isar.models.
|
|
7
|
-
from isar.models.communication.queues.queue_utils import update_shared_state
|
|
6
|
+
from isar.models.events import SharedState
|
|
8
7
|
from robot_interface.models.exceptions.robot_exceptions import RobotException
|
|
9
8
|
from robot_interface.robot_interface import RobotInterface
|
|
10
9
|
|
|
@@ -49,7 +48,7 @@ class RobotStatusThread(Thread):
|
|
|
49
48
|
self.last_robot_status_poll_time = time.time()
|
|
50
49
|
|
|
51
50
|
robot_status = self.robot.robot_status()
|
|
52
|
-
|
|
51
|
+
self.shared_state.robot_status.update(robot_status)
|
|
53
52
|
except RobotException as e:
|
|
54
53
|
self.logger.error(f"Failed to retrieve robot status: {e}")
|
|
55
54
|
continue
|