isar 1.25.2__tar.gz → 1.25.4__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.25.4/.github/PULL_REQUEST_TEMPLATE.md +11 -0
- {isar-1.25.2 → isar-1.25.4}/.github/workflows/pythonpackage.yml +9 -2
- {isar-1.25.2 → isar-1.25.4}/PKG-INFO +3 -5
- {isar-1.25.2 → isar-1.25.4}/pyproject.toml +1 -3
- {isar-1.25.2 → isar-1.25.4}/requirements.txt +16 -16
- {isar-1.25.2 → isar-1.25.4}/src/isar/apis/models/start_mission_definition.py +9 -9
- {isar-1.25.2 → isar-1.25.4}/src/isar/apis/robot_control/robot_controller.py +1 -3
- {isar-1.25.2 → isar-1.25.4}/src/isar/apis/schedule/scheduling_controller.py +2 -2
- {isar-1.25.2 → isar-1.25.4}/src/isar/mission_planner/sequential_task_selector.py +1 -1
- {isar-1.25.2 → isar-1.25.4}/src/isar/mission_planner/task_selector_interface.py +1 -1
- {isar-1.25.2 → isar-1.25.4}/src/isar/models/communication/queues/status_queue.py +2 -2
- {isar-1.25.2 → isar-1.25.4}/src/isar/modules.py +6 -5
- {isar-1.25.2 → isar-1.25.4}/src/isar/script.py +1 -1
- {isar-1.25.2 → isar-1.25.4}/src/isar/services/utilities/scheduling_utilities.py +6 -2
- {isar-1.25.2 → isar-1.25.4}/src/isar/state_machine/state_machine.py +68 -49
- isar-1.25.4/src/isar/state_machine/states/blocked_protective_stop.py +65 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/state_machine/states/idle.py +21 -10
- {isar-1.25.2 → isar-1.25.4}/src/isar/state_machine/states/monitor.py +2 -1
- {isar-1.25.2 → isar-1.25.4}/src/isar/state_machine/states_enum.py +1 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/storage/blob_storage.py +1 -1
- {isar-1.25.2 → isar-1.25.4}/src/isar/storage/uploader.py +12 -13
- {isar-1.25.2 → isar-1.25.4}/src/isar.egg-info/PKG-INFO +3 -5
- {isar-1.25.2 → isar-1.25.4}/src/isar.egg-info/SOURCES.txt +2 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar.egg-info/requires.txt +1 -3
- {isar-1.25.2 → isar-1.25.4}/src/robot_interface/models/exceptions/robot_exceptions.py +20 -22
- isar-1.25.4/src/robot_interface/models/mission/status.py +29 -0
- {isar-1.25.2 → isar-1.25.4}/src/robot_interface/models/mission/task.py +1 -1
- isar-1.25.4/src/robot_interface/models/robots/battery_state.py +6 -0
- {isar-1.25.2 → isar-1.25.4}/src/robot_interface/models/robots/media.py +1 -1
- isar-1.25.4/src/robot_interface/models/robots/robot_model.py +13 -0
- {isar-1.25.2 → isar-1.25.4}/src/robot_interface/robot_interface.py +1 -1
- {isar-1.25.2 → isar-1.25.4}/src/robot_interface/telemetry/payloads.py +40 -9
- {isar-1.25.2 → isar-1.25.4}/tests/conftest.py +3 -1
- isar-1.25.4/tests/integration/turtlebot/config/missions/default.json +89 -0
- {isar-1.25.2 → isar-1.25.4}/tests/isar/models/communication/test_queues.py +1 -1
- isar-1.25.4/tests/isar/services/service_connections/echo/__init__.py +0 -0
- isar-1.25.4/tests/isar/services/utilities/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/isar/services/utilities/test_scheduling_utilities.py +2 -1
- isar-1.25.4/tests/isar/state_machine/__init__.py +0 -0
- isar-1.25.4/tests/isar/state_machine/states/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/isar/state_machine/test_state_machine.py +44 -7
- isar-1.25.4/tests/mocks/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/mocks/robot_interface.py +13 -1
- isar-1.25.4/tests/test_data/test_mission_not_working.json +45 -0
- isar-1.25.2/src/isar/apis/models/__init__.py +0 -1
- isar-1.25.2/src/isar/models/communication/queues/__init__.py +0 -4
- isar-1.25.2/src/isar/state_machine/states/__init__.py +0 -8
- isar-1.25.2/src/robot_interface/models/initialize/__init__.py +0 -1
- isar-1.25.2/src/robot_interface/models/inspection/__init__.py +0 -13
- isar-1.25.2/src/robot_interface/models/mission/status.py +0 -28
- isar-1.25.2/src/robot_interface/models/robots/battery_state.py +0 -6
- isar-1.25.2/src/robot_interface/models/robots/robot_model.py +0 -13
- isar-1.25.2/tests/integration/turtlebot/config/missions/default.json +0 -104
- isar-1.25.2/tests/test_data/test_mission_not_working.json +0 -61
- {isar-1.25.2 → isar-1.25.4}/.dockerignore +0 -0
- {isar-1.25.2 → isar-1.25.4}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {isar-1.25.2 → isar-1.25.4}/.github/ISSUE_TEMPLATE/feature.md +0 -0
- {isar-1.25.2 → isar-1.25.4}/.github/ISSUE_TEMPLATE/improvement.md +0 -0
- {isar-1.25.2 → isar-1.25.4}/.github/release.yml +0 -0
- {isar-1.25.2 → isar-1.25.4}/.github/workflows/compile_requirements.yml +0 -0
- {isar-1.25.2 → isar-1.25.4}/.github/workflows/project_automations.yml +0 -0
- {isar-1.25.2 → isar-1.25.4}/.github/workflows/publish_isar_base_image.yml +0 -0
- {isar-1.25.2 → isar-1.25.4}/.github/workflows/pythonpublish.yml +0 -0
- {isar-1.25.2 → isar-1.25.4}/.github/workflows/stale.yml +0 -0
- {isar-1.25.2 → isar-1.25.4}/.gitignore +0 -0
- {isar-1.25.2 → isar-1.25.4}/.pre-commit-config.yaml +0 -0
- {isar-1.25.2 → isar-1.25.4}/Dockerfile +0 -0
- {isar-1.25.2 → isar-1.25.4}/LICENSE +0 -0
- {isar-1.25.2 → isar-1.25.4}/README.md +0 -0
- {isar-1.25.2 → isar-1.25.4}/SECURITY.md +0 -0
- {isar-1.25.2 → isar-1.25.4}/docker-compose-turtlebot.yml +0 -0
- {isar-1.25.2 → isar-1.25.4}/docker-compose.yml +0 -0
- {isar-1.25.2 → isar-1.25.4}/docs/Makefile +0 -0
- {isar-1.25.2 → isar-1.25.4}/docs/make.bat +0 -0
- {isar-1.25.2 → isar-1.25.4}/docs/rst_processing.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/docs/source/conf.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/docs/source/index.rst +0 -0
- {isar-1.25.2 → isar-1.25.4}/docs/source/readme_link.md +0 -0
- {isar-1.25.2 → isar-1.25.4}/docs/state_machine_diagram.png +0 -0
- {isar-1.25.2 → isar-1.25.4}/main.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/radixconfig.yml +0 -0
- {isar-1.25.2 → isar-1.25.4}/setup.cfg +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/apis/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/apis/api.py +0 -0
- {isar-1.25.2/src/isar/apis/schedule → isar-1.25.4/src/isar/apis/models}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/apis/models/models.py +0 -0
- {isar-1.25.2/src/isar/apis/security → isar-1.25.4/src/isar/apis/schedule}/__init__.py +0 -0
- {isar-1.25.2/src/isar/config → isar-1.25.4/src/isar/apis/security}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/apis/security/authentication.py +0 -0
- {isar-1.25.2/src/isar/config/keyvault → isar-1.25.4/src/isar/config}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/config/certs/ca-cert.pem +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/config/configuration_error.py +0 -0
- {isar-1.25.2/src/isar/config/predefined_mission_definition → isar-1.25.4/src/isar/config/keyvault}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/config/keyvault/keyvault_error.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/config/keyvault/keyvault_service.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/config/log.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/config/logging.conf +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/config/maps/JSP1_intermediate_deck.json +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/config/maps/JSP1_weather_deck.json +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/config/maps/default_map.json +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/config/maps/klab_b.json +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/config/maps/klab_compressor.json +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/config/maps/klab_turtlebot.json +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/config/maps/turtleworld.json +0 -0
- {isar-1.25.2/src/isar/config/predefined_missions → isar-1.25.4/src/isar/config/predefined_mission_definition}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/config/predefined_mission_definition/default_exr.json +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/config/predefined_mission_definition/default_mission.json +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/config/predefined_mission_definition/default_turtlebot.json +0 -0
- {isar-1.25.2/src/isar/mission_planner → isar-1.25.4/src/isar/config/predefined_missions}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/config/predefined_missions/default.json +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/config/predefined_missions/default_turtlebot.json +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/config/settings.env +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/config/settings.py +0 -0
- {isar-1.25.2/src/isar/models → isar-1.25.4/src/isar/mission_planner}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/mission_planner/local_planner.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/mission_planner/mission_planner_interface.py +0 -0
- {isar-1.25.2/src/isar/models/communication → isar-1.25.4/src/isar/models}/__init__.py +0 -0
- {isar-1.25.2/src/isar/models/mission_metadata → isar-1.25.4/src/isar/models/communication}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/models/communication/message.py +0 -0
- {isar-1.25.2/src/isar/services → isar-1.25.4/src/isar/models/communication/queues}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/models/communication/queues/queue_io.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/models/communication/queues/queue_timeout_error.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/models/communication/queues/queues.py +0 -0
- {isar-1.25.2/src/isar/services/auth → isar-1.25.4/src/isar/models/mission_metadata}/__init__.py +0 -0
- {isar-1.25.2/src/isar/services/service_connections → isar-1.25.4/src/isar/services}/__init__.py +0 -0
- {isar-1.25.2/src/isar/services/service_connections/mqtt → isar-1.25.4/src/isar/services/auth}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/services/auth/azure_credentials.py +0 -0
- {isar-1.25.2/src/isar/services/service_connections/stid → isar-1.25.4/src/isar/services/service_connections}/__init__.py +0 -0
- {isar-1.25.2/src/isar/services/utilities → isar-1.25.4/src/isar/services/service_connections/mqtt}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/services/service_connections/mqtt/mqtt_client.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/services/service_connections/mqtt/robot_heartbeat_publisher.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/services/service_connections/mqtt/robot_info_publisher.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/services/service_connections/request_handler.py +0 -0
- {isar-1.25.2/src/isar/state_machine → isar-1.25.4/src/isar/services/service_connections/stid}/__init__.py +0 -0
- {isar-1.25.2/src/isar/storage → isar-1.25.4/src/isar/services/utilities}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/services/utilities/queue_utilities.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/services/utilities/robot_utilities.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/services/utilities/threaded_request.py +0 -0
- {isar-1.25.2/src/robot_interface → isar-1.25.4/src/isar/state_machine}/__init__.py +0 -0
- {isar-1.25.2/src/robot_interface/models → isar-1.25.4/src/isar/state_machine/states}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/state_machine/states/initialize.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/state_machine/states/initiate.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/state_machine/states/off.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/state_machine/states/offline.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/state_machine/states/paused.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/state_machine/states/stop.py +0 -0
- {isar-1.25.2/src/robot_interface/models/exceptions → isar-1.25.4/src/isar/storage}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/storage/local_storage.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/storage/slimm_storage.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/storage/storage_interface.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar/storage/utilities.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar.egg-info/dependency_links.txt +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar.egg-info/entry_points.txt +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/isar.egg-info/top_level.txt +0 -0
- {isar-1.25.2/src/robot_interface/models/mission → isar-1.25.4/src/robot_interface}/__init__.py +0 -0
- {isar-1.25.2/src/robot_interface/models/robots → isar-1.25.4/src/robot_interface/models}/__init__.py +0 -0
- {isar-1.25.2/src/robot_interface/telemetry → isar-1.25.4/src/robot_interface/models/exceptions}/__init__.py +0 -0
- {isar-1.25.2/src/robot_interface/utilities → isar-1.25.4/src/robot_interface/models/initialize}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/robot_interface/models/initialize/initialize_params.py +0 -0
- {isar-1.25.2/tests → isar-1.25.4/src/robot_interface/models/inspection}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/robot_interface/models/inspection/inspection.py +0 -0
- {isar-1.25.2/tests/integration → isar-1.25.4/src/robot_interface/models/mission}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/robot_interface/models/mission/mission.py +0 -0
- {isar-1.25.2/tests/integration/turtlebot → isar-1.25.4/src/robot_interface/models/robots}/__init__.py +0 -0
- {isar-1.25.2/tests/integration/turtlebot/config → isar-1.25.4/src/robot_interface/telemetry}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/robot_interface/telemetry/mqtt_client.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/robot_interface/test_robot_interface.py +0 -0
- {isar-1.25.2/tests/integration/turtlebot/config/maps → isar-1.25.4/src/robot_interface/utilities}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/robot_interface/utilities/json_service.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/src/robot_interface/utilities/uuid_string_factory.py +0 -0
- {isar-1.25.2/tests/integration/turtlebot/config/missions → isar-1.25.4/tests}/__init__.py +0 -0
- {isar-1.25.2/tests/isar → isar-1.25.4/tests/integration}/__init__.py +0 -0
- {isar-1.25.2/tests/isar/apis → isar-1.25.4/tests/integration/turtlebot}/__init__.py +0 -0
- {isar-1.25.2/tests/isar/apis/models → isar-1.25.4/tests/integration/turtlebot/config}/__init__.py +0 -0
- {isar-1.25.2/tests/isar/apis/scheduler → isar-1.25.4/tests/integration/turtlebot/config/maps}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/integration/turtlebot/config/maps/turtleworld.json +0 -0
- {isar-1.25.2/tests/isar/apis/security → isar-1.25.4/tests/integration/turtlebot/config/missions}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/integration/turtlebot/test_successful_mission.py +0 -0
- {isar-1.25.2/tests/isar/mission → isar-1.25.4/tests/isar}/__init__.py +0 -0
- {isar-1.25.2/tests/isar/models → isar-1.25.4/tests/isar/apis}/__init__.py +0 -0
- {isar-1.25.2/tests/isar/models/communication → isar-1.25.4/tests/isar/apis/models}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/isar/apis/models/example_mission_definition.json +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/isar/apis/models/test_start_mission_definition.py +0 -0
- {isar-1.25.2/tests/isar/services → isar-1.25.4/tests/isar/apis/scheduler}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/isar/apis/scheduler/test_scheduler_router.py +0 -0
- {isar-1.25.2/tests/isar/services/readers → isar-1.25.4/tests/isar/apis/security}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/isar/apis/security/test_authentication.py +0 -0
- {isar-1.25.2/tests/isar/services/service_connections → isar-1.25.4/tests/isar/mission}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/isar/mission/test_mission.py +0 -0
- {isar-1.25.2/tests/isar/services/service_connections/echo → isar-1.25.4/tests/isar/models}/__init__.py +0 -0
- {isar-1.25.2/tests/isar/services/utilities → isar-1.25.4/tests/isar/models/communication}/__init__.py +0 -0
- {isar-1.25.2/tests/isar/state_machine → isar-1.25.4/tests/isar/services}/__init__.py +0 -0
- {isar-1.25.2/tests/isar/state_machine/states → isar-1.25.4/tests/isar/services/readers}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/isar/services/readers/test_mission_reader.py +0 -0
- {isar-1.25.2/tests/mocks → isar-1.25.4/tests/isar/services/service_connections}/__init__.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/isar/services/service_connections/test_base_request_handler.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/isar/services/utilities/test_queue_utilities.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/isar/state_machine/states/test_monitor.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/isar/storage/test_blob_storage.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/isar/storage/test_uploader.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/mocks/blob_storage.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/mocks/mission_definition.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/mocks/mqtt_client.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/mocks/pose.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/mocks/request.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/mocks/status.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/mocks/task.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/mocks/token.py +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/test_data/test_map_config/test_map_config.json +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/test_data/test_mission_working.json +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/test_data/test_mission_working_no_tasks.json +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/test_data/test_thermal_image_mission.json +0 -0
- {isar-1.25.2 → isar-1.25.4}/tests/test_modules.py +0 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
## Ready for review checklist:
|
|
2
|
+
- [ ] A self-review has been performed
|
|
3
|
+
- [ ] All commits run individually
|
|
4
|
+
- [ ] Temporary changes have been removed, like logging, TODO, etc.
|
|
5
|
+
- [ ] The PR has been tested locally
|
|
6
|
+
- [ ] A test has been written
|
|
7
|
+
- [ ] This change doesn't need a new test
|
|
8
|
+
- [ ] Relevant issues are linked
|
|
9
|
+
- [ ] Remaining work is documented in issues
|
|
10
|
+
- [ ] There is no remaining work from this PR that requires new issues
|
|
11
|
+
- [ ] The changes do not introduce dead code as unused imports, functions etc.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: isar
|
|
3
|
-
Version: 1.25.
|
|
3
|
+
Version: 1.25.4
|
|
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
|
|
@@ -127,9 +127,7 @@ Requires-Dist: transitions
|
|
|
127
127
|
Requires-Dist: uvicorn
|
|
128
128
|
Provides-Extra: dev
|
|
129
129
|
Requires-Dist: black; extra == "dev"
|
|
130
|
-
Requires-Dist: flake8; extra == "dev"
|
|
131
130
|
Requires-Dist: mypy; extra == "dev"
|
|
132
|
-
Requires-Dist: myst-parser; extra == "dev"
|
|
133
131
|
Requires-Dist: pip-tools; extra == "dev"
|
|
134
132
|
Requires-Dist: pre-commit; extra == "dev"
|
|
135
133
|
Requires-Dist: pytest-dotenv; extra == "dev"
|
|
@@ -137,7 +135,7 @@ Requires-Dist: pytest-mock; extra == "dev"
|
|
|
137
135
|
Requires-Dist: pytest-xdist; extra == "dev"
|
|
138
136
|
Requires-Dist: pytest; extra == "dev"
|
|
139
137
|
Requires-Dist: requests-mock; extra == "dev"
|
|
140
|
-
Requires-Dist:
|
|
138
|
+
Requires-Dist: ruff; extra == "dev"
|
|
141
139
|
|
|
142
140
|
# ISAR
|
|
143
141
|
|
|
@@ -60,9 +60,7 @@ repository = "https://github.com/equinor/isar.git"
|
|
|
60
60
|
[project.optional-dependencies]
|
|
61
61
|
dev = [
|
|
62
62
|
"black",
|
|
63
|
-
"flake8",
|
|
64
63
|
"mypy",
|
|
65
|
-
"myst-parser",
|
|
66
64
|
"pip-tools",
|
|
67
65
|
"pre-commit",
|
|
68
66
|
"pytest-dotenv",
|
|
@@ -70,7 +68,7 @@ dev = [
|
|
|
70
68
|
"pytest-xdist",
|
|
71
69
|
"pytest",
|
|
72
70
|
"requests-mock",
|
|
73
|
-
"
|
|
71
|
+
"ruff",
|
|
74
72
|
]
|
|
75
73
|
|
|
76
74
|
[tool.setuptools_scm]
|
|
@@ -8,7 +8,7 @@ alitra==1.1.3
|
|
|
8
8
|
# via isar (pyproject.toml)
|
|
9
9
|
annotated-types==0.7.0
|
|
10
10
|
# via pydantic
|
|
11
|
-
anyio==4.
|
|
11
|
+
anyio==4.8.0
|
|
12
12
|
# via
|
|
13
13
|
# httpx
|
|
14
14
|
# starlette
|
|
@@ -30,16 +30,16 @@ backoff==2.2.1
|
|
|
30
30
|
# via isar (pyproject.toml)
|
|
31
31
|
cachetools==5.5.0
|
|
32
32
|
# via google-auth
|
|
33
|
-
certifi==2024.
|
|
33
|
+
certifi==2024.12.14
|
|
34
34
|
# via
|
|
35
35
|
# httpcore
|
|
36
36
|
# httpx
|
|
37
37
|
# requests
|
|
38
38
|
cffi==1.17.1
|
|
39
39
|
# via cryptography
|
|
40
|
-
charset-normalizer==3.4.
|
|
40
|
+
charset-normalizer==3.4.1
|
|
41
41
|
# via requests
|
|
42
|
-
click==8.1.
|
|
42
|
+
click==8.1.8
|
|
43
43
|
# via
|
|
44
44
|
# isar (pyproject.toml)
|
|
45
45
|
# uvicorn
|
|
@@ -62,7 +62,7 @@ fastapi-azure-auth==5.0.1
|
|
|
62
62
|
# via isar (pyproject.toml)
|
|
63
63
|
google-api-core==2.24.0
|
|
64
64
|
# via opencensus
|
|
65
|
-
google-auth==2.
|
|
65
|
+
google-auth==2.37.0
|
|
66
66
|
# via google-api-core
|
|
67
67
|
googleapis-common-protos==1.66.0
|
|
68
68
|
# via google-api-core
|
|
@@ -91,7 +91,7 @@ msal==1.31.1
|
|
|
91
91
|
# msal-extensions
|
|
92
92
|
msal-extensions==1.2.0
|
|
93
93
|
# via azure-identity
|
|
94
|
-
numpy==2.2.
|
|
94
|
+
numpy==2.2.1
|
|
95
95
|
# via
|
|
96
96
|
# alitra
|
|
97
97
|
# isar (pyproject.toml)
|
|
@@ -103,7 +103,7 @@ opencensus==0.11.4
|
|
|
103
103
|
# opencensus-ext-requests
|
|
104
104
|
opencensus-context==0.1.3
|
|
105
105
|
# via opencensus
|
|
106
|
-
opencensus-ext-azure==1.1.
|
|
106
|
+
opencensus-ext-azure==1.1.14
|
|
107
107
|
# via isar (pyproject.toml)
|
|
108
108
|
opencensus-ext-logging==0.1.1
|
|
109
109
|
# via isar (pyproject.toml)
|
|
@@ -115,12 +115,12 @@ portalocker==2.10.1
|
|
|
115
115
|
# via msal-extensions
|
|
116
116
|
proto-plus==1.25.0
|
|
117
117
|
# via google-api-core
|
|
118
|
-
protobuf==5.29.
|
|
118
|
+
protobuf==5.29.3
|
|
119
119
|
# via
|
|
120
120
|
# google-api-core
|
|
121
121
|
# googleapis-common-protos
|
|
122
122
|
# proto-plus
|
|
123
|
-
psutil==6.1.
|
|
123
|
+
psutil==6.1.1
|
|
124
124
|
# via opencensus-ext-azure
|
|
125
125
|
pyasn1==0.6.1
|
|
126
126
|
# via
|
|
@@ -130,14 +130,14 @@ pyasn1-modules==0.4.1
|
|
|
130
130
|
# via google-auth
|
|
131
131
|
pycparser==2.22
|
|
132
132
|
# via cffi
|
|
133
|
-
pydantic==2.10.
|
|
133
|
+
pydantic==2.10.5
|
|
134
134
|
# via
|
|
135
135
|
# fastapi
|
|
136
136
|
# isar (pyproject.toml)
|
|
137
137
|
# pydantic-settings
|
|
138
|
-
pydantic-core==2.27.
|
|
138
|
+
pydantic-core==2.27.2
|
|
139
139
|
# via pydantic
|
|
140
|
-
pydantic-settings==2.
|
|
140
|
+
pydantic-settings==2.7.1
|
|
141
141
|
# via isar (pyproject.toml)
|
|
142
142
|
pyjwt[crypto]==2.10.1
|
|
143
143
|
# via
|
|
@@ -163,7 +163,7 @@ requests-toolbelt==1.0.0
|
|
|
163
163
|
# via isar (pyproject.toml)
|
|
164
164
|
rsa==4.9
|
|
165
165
|
# via google-auth
|
|
166
|
-
scipy==1.
|
|
166
|
+
scipy==1.15.1
|
|
167
167
|
# via alitra
|
|
168
168
|
six==1.17.0
|
|
169
169
|
# via
|
|
@@ -186,9 +186,9 @@ typing-extensions==4.12.2
|
|
|
186
186
|
# fastapi
|
|
187
187
|
# pydantic
|
|
188
188
|
# pydantic-core
|
|
189
|
-
urllib3==2.
|
|
189
|
+
urllib3==2.3.0
|
|
190
190
|
# via requests
|
|
191
|
-
uvicorn==0.
|
|
191
|
+
uvicorn==0.34.0
|
|
192
192
|
# via isar (pyproject.toml)
|
|
193
|
-
wrapt==1.17.
|
|
193
|
+
wrapt==1.17.1
|
|
194
194
|
# via opencensus-ext-requests
|
|
@@ -23,18 +23,18 @@ from robot_interface.models.mission.task import (
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
class InspectionTypes(str, Enum):
|
|
26
|
-
image
|
|
27
|
-
thermal_image
|
|
28
|
-
video
|
|
29
|
-
thermal_video
|
|
30
|
-
audio
|
|
26
|
+
image = "Image"
|
|
27
|
+
thermal_image = "ThermalImage"
|
|
28
|
+
video = "Video"
|
|
29
|
+
thermal_video = "ThermalVideo"
|
|
30
|
+
audio = "Audio"
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
class TaskType(str, Enum):
|
|
34
|
-
Inspection
|
|
35
|
-
Localization
|
|
36
|
-
ReturnToHome
|
|
37
|
-
Dock
|
|
34
|
+
Inspection = "inspection"
|
|
35
|
+
Localization = "localization"
|
|
36
|
+
ReturnToHome = "return_to_home"
|
|
37
|
+
Dock = "dock"
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
class StartMissionInspectionDefinition(BaseModel):
|
|
@@ -2,9 +2,7 @@ import logging
|
|
|
2
2
|
|
|
3
3
|
from injector import inject
|
|
4
4
|
|
|
5
|
-
from isar.apis.models.models import
|
|
6
|
-
RobotInfoResponse,
|
|
7
|
-
)
|
|
5
|
+
from isar.apis.models.models import RobotInfoResponse
|
|
8
6
|
from isar.config.settings import robot_settings, settings
|
|
9
7
|
from isar.services.utilities.robot_utilities import RobotUtilities
|
|
10
8
|
|
|
@@ -6,11 +6,11 @@ from alitra import Pose
|
|
|
6
6
|
from fastapi import Body, HTTPException, Path
|
|
7
7
|
from injector import inject
|
|
8
8
|
|
|
9
|
-
from isar.apis.models import InputPose, StartMissionResponse
|
|
10
9
|
from isar.apis.models.models import (
|
|
11
10
|
ControlMissionResponse,
|
|
12
|
-
RobotInfoResponse,
|
|
13
11
|
TaskResponse,
|
|
12
|
+
InputPose,
|
|
13
|
+
StartMissionResponse,
|
|
14
14
|
)
|
|
15
15
|
from isar.apis.models.start_mission_definition import (
|
|
16
16
|
StartMissionDefinition,
|
|
@@ -4,7 +4,7 @@ from isar.mission_planner.task_selector_interface import (
|
|
|
4
4
|
TaskSelectorInterface,
|
|
5
5
|
TaskSelectorStop,
|
|
6
6
|
)
|
|
7
|
-
from robot_interface.models.mission.task import TASKS
|
|
7
|
+
from robot_interface.models.mission.task import TASKS
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class SequentialTaskSelector(TaskSelectorInterface):
|
|
@@ -7,8 +7,8 @@ from typing import Dict, List, Tuple, Union
|
|
|
7
7
|
from injector import Injector, Module, multiprovider, provider, singleton
|
|
8
8
|
|
|
9
9
|
from isar.apis.api import API
|
|
10
|
-
from isar.apis.schedule.scheduling_controller import SchedulingController
|
|
11
10
|
from isar.apis.robot_control.robot_controller import RobotController
|
|
11
|
+
from isar.apis.schedule.scheduling_controller import SchedulingController
|
|
12
12
|
from isar.apis.security.authentication import Authenticator
|
|
13
13
|
from isar.config.keyvault.keyvault_service import Keyvault
|
|
14
14
|
from isar.config.settings import settings
|
|
@@ -18,8 +18,8 @@ from isar.mission_planner.sequential_task_selector import SequentialTaskSelector
|
|
|
18
18
|
from isar.mission_planner.task_selector_interface import TaskSelectorInterface
|
|
19
19
|
from isar.models.communication.queues.queues import Queues
|
|
20
20
|
from isar.services.service_connections.request_handler import RequestHandler
|
|
21
|
-
from isar.services.utilities.scheduling_utilities import SchedulingUtilities
|
|
22
21
|
from isar.services.utilities.robot_utilities import RobotUtilities
|
|
22
|
+
from isar.services.utilities.scheduling_utilities import SchedulingUtilities
|
|
23
23
|
from isar.state_machine.state_machine import StateMachine
|
|
24
24
|
from isar.storage.blob_storage import BlobStorage
|
|
25
25
|
from isar.storage.local_storage import LocalStorage
|
|
@@ -70,9 +70,10 @@ class RobotModule(Module):
|
|
|
70
70
|
@provider
|
|
71
71
|
@singleton
|
|
72
72
|
def provide_robot_interface(self) -> RobotInterface:
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
robot_interface: ModuleType = import_module(
|
|
74
|
+
f"{settings.ROBOT_PACKAGE}.robotinterface"
|
|
75
|
+
)
|
|
76
|
+
return robot_interface.Robot() # type: ignore
|
|
76
77
|
|
|
77
78
|
|
|
78
79
|
class QueuesModule(Module):
|
|
@@ -66,7 +66,7 @@ def print_startup_info():
|
|
|
66
66
|
print_setting(fillchar="-")
|
|
67
67
|
print_setting("Robot package", settings.ROBOT_PACKAGE)
|
|
68
68
|
print_setting("Robot name", settings.ROBOT_NAME)
|
|
69
|
-
print_setting("Run mission
|
|
69
|
+
print_setting("Run mission taskwise", settings.RUN_MISSION_BY_TASK)
|
|
70
70
|
print_setting("Running on port", settings.API_PORT)
|
|
71
71
|
print_setting("Mission planner", settings.MISSION_PLANNER)
|
|
72
72
|
print_setting("Using local storage", settings.STORAGE_LOCAL_ENABLED)
|
|
@@ -17,7 +17,11 @@ from isar.mission_planner.mission_planner_interface import (
|
|
|
17
17
|
MissionPlannerInterface,
|
|
18
18
|
)
|
|
19
19
|
from isar.models.communication.message import StartMissionMessage
|
|
20
|
-
from isar.models.communication.queues import QueueIO
|
|
20
|
+
from isar.models.communication.queues.queue_io import QueueIO
|
|
21
|
+
from isar.models.communication.queues.queues import Queues
|
|
22
|
+
from isar.models.communication.queues.queue_timeout_error import (
|
|
23
|
+
QueueTimeoutError,
|
|
24
|
+
)
|
|
21
25
|
from isar.services.utilities.queue_utilities import QueueUtilities
|
|
22
26
|
from isar.state_machine.states_enum import States
|
|
23
27
|
from robot_interface.models.mission.mission import Mission
|
|
@@ -101,7 +105,7 @@ class SchedulingUtilities:
|
|
|
101
105
|
is_capable: bool = True
|
|
102
106
|
missing_capabilities: Set[str] = set()
|
|
103
107
|
for task in mission.tasks:
|
|
104
|
-
if
|
|
108
|
+
if task.type not in robot_capabilities:
|
|
105
109
|
is_capable = False
|
|
106
110
|
missing_capabilities.add(task.type)
|
|
107
111
|
|
|
@@ -18,16 +18,15 @@ from isar.mission_planner.task_selector_interface import (
|
|
|
18
18
|
)
|
|
19
19
|
from isar.models.communication.message import StartMissionMessage
|
|
20
20
|
from isar.models.communication.queues.queues import Queues
|
|
21
|
-
from isar.state_machine.states import
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
)
|
|
21
|
+
from isar.state_machine.states.idle import Idle
|
|
22
|
+
from isar.state_machine.states.initialize import Initialize
|
|
23
|
+
from isar.state_machine.states.initiate import Initiate
|
|
24
|
+
from isar.state_machine.states.monitor import Monitor
|
|
25
|
+
from isar.state_machine.states.off import Off
|
|
26
|
+
from isar.state_machine.states.offline import Offline
|
|
27
|
+
from isar.state_machine.states.blocked_protective_stop import BlockedProtectiveStop
|
|
28
|
+
from isar.state_machine.states.paused import Paused
|
|
29
|
+
from isar.state_machine.states.stop import Stop
|
|
31
30
|
from isar.state_machine.states_enum import States
|
|
32
31
|
from robot_interface.models.exceptions.robot_exceptions import ErrorMessage
|
|
33
32
|
from robot_interface.models.initialize.initialize_params import InitializeParams
|
|
@@ -36,6 +35,11 @@ from robot_interface.models.mission.status import MissionStatus, RobotStatus, Ta
|
|
|
36
35
|
from robot_interface.models.mission.task import TASKS
|
|
37
36
|
from robot_interface.robot_interface import RobotInterface
|
|
38
37
|
from robot_interface.telemetry.mqtt_client import MqttClientInterface
|
|
38
|
+
from robot_interface.telemetry.payloads import (
|
|
39
|
+
RobotStatusPayload,
|
|
40
|
+
MissionPayload,
|
|
41
|
+
TaskPayload,
|
|
42
|
+
)
|
|
39
43
|
from robot_interface.utilities.json_service import EnhancedJSONEncoder
|
|
40
44
|
|
|
41
45
|
|
|
@@ -89,6 +93,7 @@ class StateMachine(object):
|
|
|
89
93
|
self.initiate_state: State = Initiate(self)
|
|
90
94
|
self.off_state: State = Off(self)
|
|
91
95
|
self.offline_state: State = Offline(self)
|
|
96
|
+
self.blocked_protective_stop: State = BlockedProtectiveStop(self)
|
|
92
97
|
|
|
93
98
|
self.states: List[State] = [
|
|
94
99
|
self.off_state,
|
|
@@ -99,6 +104,7 @@ class StateMachine(object):
|
|
|
99
104
|
self.stop_state,
|
|
100
105
|
self.paused_state,
|
|
101
106
|
self.offline_state,
|
|
107
|
+
self.blocked_protective_stop,
|
|
102
108
|
]
|
|
103
109
|
|
|
104
110
|
self.machine = Machine(self, states=self.states, initial="off", queued=True)
|
|
@@ -224,6 +230,18 @@ class StateMachine(object):
|
|
|
224
230
|
"dest": self.idle_state,
|
|
225
231
|
"before": self._online,
|
|
226
232
|
},
|
|
233
|
+
{
|
|
234
|
+
"trigger": "robot_protective_stop_engaged",
|
|
235
|
+
"source": [self.idle_state],
|
|
236
|
+
"dest": self.blocked_protective_stop,
|
|
237
|
+
"before": self._protective_stop_engaged,
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
"trigger": "robot_protective_stop_disengaged",
|
|
241
|
+
"source": self.blocked_protective_stop,
|
|
242
|
+
"dest": self.idle_state,
|
|
243
|
+
"before": self._protective_stop_disengaged,
|
|
244
|
+
},
|
|
227
245
|
]
|
|
228
246
|
)
|
|
229
247
|
|
|
@@ -272,6 +290,12 @@ class StateMachine(object):
|
|
|
272
290
|
def _online(self) -> None:
|
|
273
291
|
return
|
|
274
292
|
|
|
293
|
+
def _protective_stop_engaged(self) -> None:
|
|
294
|
+
return
|
|
295
|
+
|
|
296
|
+
def _protective_stop_disengaged(self) -> None:
|
|
297
|
+
return
|
|
298
|
+
|
|
275
299
|
def _resume(self) -> None:
|
|
276
300
|
self.logger.info(f"Resuming mission: {self.current_mission.id}")
|
|
277
301
|
self.current_mission.status = MissionStatus.InProgress
|
|
@@ -484,24 +508,22 @@ class StateMachine(object):
|
|
|
484
508
|
if self.current_mission:
|
|
485
509
|
if self.current_mission.error_message:
|
|
486
510
|
error_message = self.current_mission.error_message
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
},
|
|
499
|
-
cls=EnhancedJSONEncoder,
|
|
511
|
+
|
|
512
|
+
payload: MissionPayload = MissionPayload(
|
|
513
|
+
isar_id=settings.ISAR_ID,
|
|
514
|
+
robot_name=settings.ROBOT_NAME,
|
|
515
|
+
mission_id=self.current_mission.id if self.current_mission else None,
|
|
516
|
+
status=self.current_mission.status if self.current_mission else None,
|
|
517
|
+
error_reason=error_message.error_reason if error_message else None,
|
|
518
|
+
error_description=(
|
|
519
|
+
error_message.error_description if error_message else None
|
|
520
|
+
),
|
|
521
|
+
timestamp=datetime.now(timezone.utc),
|
|
500
522
|
)
|
|
501
523
|
|
|
502
524
|
self.mqtt_publisher.publish(
|
|
503
525
|
topic=settings.TOPIC_ISAR_MISSION,
|
|
504
|
-
payload=payload,
|
|
526
|
+
payload=json.dumps(payload, cls=EnhancedJSONEncoder),
|
|
505
527
|
qos=1,
|
|
506
528
|
retain=True,
|
|
507
529
|
)
|
|
@@ -516,26 +538,23 @@ class StateMachine(object):
|
|
|
516
538
|
if task.error_message:
|
|
517
539
|
error_message = task.error_message
|
|
518
540
|
|
|
519
|
-
payload:
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
"timestamp": datetime.now(timezone.utc),
|
|
532
|
-
},
|
|
533
|
-
cls=EnhancedJSONEncoder,
|
|
541
|
+
payload: TaskPayload = TaskPayload(
|
|
542
|
+
isar_id=settings.ISAR_ID,
|
|
543
|
+
robot_name=settings.ROBOT_NAME,
|
|
544
|
+
mission_id=self.current_mission.id if self.current_mission else None,
|
|
545
|
+
task_id=task.id if task else None,
|
|
546
|
+
status=task.status if task else None,
|
|
547
|
+
task_type=task.type if task else None,
|
|
548
|
+
error_reason=error_message.error_reason if error_message else None,
|
|
549
|
+
error_description=(
|
|
550
|
+
error_message.error_description if error_message else None
|
|
551
|
+
),
|
|
552
|
+
timestamp=datetime.now(timezone.utc),
|
|
534
553
|
)
|
|
535
554
|
|
|
536
555
|
self.mqtt_publisher.publish(
|
|
537
556
|
topic=settings.TOPIC_ISAR_TASK,
|
|
538
|
-
payload=payload,
|
|
557
|
+
payload=json.dumps(payload, cls=EnhancedJSONEncoder),
|
|
539
558
|
qos=1,
|
|
540
559
|
retain=True,
|
|
541
560
|
)
|
|
@@ -543,19 +562,17 @@ class StateMachine(object):
|
|
|
543
562
|
def publish_status(self) -> None:
|
|
544
563
|
if not self.mqtt_publisher:
|
|
545
564
|
return
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
},
|
|
553
|
-
cls=EnhancedJSONEncoder,
|
|
565
|
+
|
|
566
|
+
payload: RobotStatusPayload = RobotStatusPayload(
|
|
567
|
+
isar_id=settings.ISAR_ID,
|
|
568
|
+
robot_name=settings.ROBOT_NAME,
|
|
569
|
+
status=self._current_status(),
|
|
570
|
+
timestamp=datetime.now(timezone.utc),
|
|
554
571
|
)
|
|
555
572
|
|
|
556
573
|
self.mqtt_publisher.publish(
|
|
557
574
|
topic=settings.TOPIC_ISAR_STATUS,
|
|
558
|
-
payload=payload,
|
|
575
|
+
payload=json.dumps(payload, cls=EnhancedJSONEncoder),
|
|
559
576
|
qos=1,
|
|
560
577
|
retain=True,
|
|
561
578
|
)
|
|
@@ -565,6 +582,8 @@ class StateMachine(object):
|
|
|
565
582
|
return RobotStatus.Available
|
|
566
583
|
elif self.current_state == States.Offline:
|
|
567
584
|
return RobotStatus.Offline
|
|
585
|
+
elif self.current_state == States.BlockedProtectiveStop:
|
|
586
|
+
return RobotStatus.BlockedProtectiveStop
|
|
568
587
|
else:
|
|
569
588
|
return RobotStatus.Busy
|
|
570
589
|
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import time
|
|
3
|
+
from typing import TYPE_CHECKING, Optional
|
|
4
|
+
|
|
5
|
+
from transitions import State
|
|
6
|
+
|
|
7
|
+
from isar.config.settings import settings
|
|
8
|
+
from isar.services.utilities.threaded_request import (
|
|
9
|
+
ThreadedRequest,
|
|
10
|
+
ThreadedRequestNotFinishedError,
|
|
11
|
+
)
|
|
12
|
+
from robot_interface.models.exceptions.robot_exceptions import RobotException
|
|
13
|
+
from robot_interface.models.mission.status import RobotStatus
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from isar.state_machine.state_machine import StateMachine
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class BlockedProtectiveStop(State):
|
|
20
|
+
def __init__(self, state_machine: "StateMachine") -> None:
|
|
21
|
+
super().__init__(
|
|
22
|
+
name="blocked_protective_stop", on_enter=self.start, on_exit=self.stop
|
|
23
|
+
)
|
|
24
|
+
self.state_machine: "StateMachine" = state_machine
|
|
25
|
+
self.logger = logging.getLogger("state_machine")
|
|
26
|
+
self.robot_status_thread: Optional[ThreadedRequest] = None
|
|
27
|
+
|
|
28
|
+
def start(self) -> None:
|
|
29
|
+
self.state_machine.update_state()
|
|
30
|
+
self._run()
|
|
31
|
+
|
|
32
|
+
def stop(self) -> None:
|
|
33
|
+
if self.robot_status_thread:
|
|
34
|
+
self.robot_status_thread.wait_for_thread()
|
|
35
|
+
self.robot_status_thread = None
|
|
36
|
+
|
|
37
|
+
def _run(self) -> None:
|
|
38
|
+
while True:
|
|
39
|
+
if not self.robot_status_thread:
|
|
40
|
+
self.robot_status_thread = ThreadedRequest(
|
|
41
|
+
request_func=self.state_machine.robot.robot_status
|
|
42
|
+
)
|
|
43
|
+
self.robot_status_thread.start_thread(
|
|
44
|
+
name="State Machine BlockedProtectiveStop Get Robot Status"
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
try:
|
|
48
|
+
robot_status: RobotStatus = self.robot_status_thread.get_output()
|
|
49
|
+
except ThreadedRequestNotFinishedError:
|
|
50
|
+
time.sleep(self.state_machine.sleep_time)
|
|
51
|
+
continue
|
|
52
|
+
|
|
53
|
+
except RobotException as e:
|
|
54
|
+
self.logger.error(
|
|
55
|
+
f"Failed to get robot status because: {e.error_description}"
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
if robot_status != RobotStatus.BlockedProtectiveStop:
|
|
59
|
+
transition = self.state_machine.robot_protective_stop_disengaged # type: ignore
|
|
60
|
+
break
|
|
61
|
+
|
|
62
|
+
self.robot_status_thread = None
|
|
63
|
+
time.sleep(settings.ROBOT_API_STATUS_POLL_INTERVAL)
|
|
64
|
+
|
|
65
|
+
transition()
|
|
@@ -24,6 +24,7 @@ class Idle(State):
|
|
|
24
24
|
self.logger = logging.getLogger("state_machine")
|
|
25
25
|
self.robot_status_thread: Optional[ThreadedRequest] = None
|
|
26
26
|
self.last_robot_status_poll_time: float = time.time()
|
|
27
|
+
self.status_checked_at_least_once: bool = False
|
|
27
28
|
|
|
28
29
|
def start(self) -> None:
|
|
29
30
|
self.state_machine.update_state()
|
|
@@ -33,8 +34,12 @@ class Idle(State):
|
|
|
33
34
|
if self.robot_status_thread:
|
|
34
35
|
self.robot_status_thread.wait_for_thread()
|
|
35
36
|
self.robot_status_thread = None
|
|
37
|
+
self.status_checked_at_least_once = False
|
|
36
38
|
|
|
37
39
|
def _is_ready_to_poll_for_status(self) -> bool:
|
|
40
|
+
if not self.status_checked_at_least_once:
|
|
41
|
+
return True
|
|
42
|
+
|
|
38
43
|
time_since_last_robot_status_poll = (
|
|
39
44
|
time.time() - self.last_robot_status_poll_time
|
|
40
45
|
)
|
|
@@ -47,17 +52,19 @@ class Idle(State):
|
|
|
47
52
|
if self.state_machine.should_stop_mission():
|
|
48
53
|
transition = self.state_machine.stop # type: ignore
|
|
49
54
|
break
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
self.state_machine.start_mission(
|
|
55
|
-
mission=start_mission.mission,
|
|
56
|
-
initial_pose=start_mission.initial_pose,
|
|
55
|
+
|
|
56
|
+
if self.status_checked_at_least_once:
|
|
57
|
+
start_mission: Optional[StartMissionMessage] = (
|
|
58
|
+
self.state_machine.should_start_mission()
|
|
57
59
|
)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
if start_mission:
|
|
61
|
+
self.state_machine.start_mission(
|
|
62
|
+
mission=start_mission.mission,
|
|
63
|
+
initial_pose=start_mission.initial_pose,
|
|
64
|
+
)
|
|
65
|
+
transition = self.state_machine.mission_started # type: ignore
|
|
66
|
+
break
|
|
67
|
+
time.sleep(self.state_machine.sleep_time)
|
|
61
68
|
|
|
62
69
|
if not self._is_ready_to_poll_for_status():
|
|
63
70
|
continue
|
|
@@ -72,6 +79,7 @@ class Idle(State):
|
|
|
72
79
|
|
|
73
80
|
try:
|
|
74
81
|
robot_status: RobotStatus = self.robot_status_thread.get_output()
|
|
82
|
+
self.status_checked_at_least_once = True
|
|
75
83
|
except ThreadedRequestNotFinishedError:
|
|
76
84
|
time.sleep(self.state_machine.sleep_time)
|
|
77
85
|
continue
|
|
@@ -86,6 +94,9 @@ class Idle(State):
|
|
|
86
94
|
if robot_status == RobotStatus.Offline:
|
|
87
95
|
transition = self.state_machine.robot_turned_offline # type: ignore
|
|
88
96
|
break
|
|
97
|
+
elif robot_status == RobotStatus.BlockedProtectiveStop:
|
|
98
|
+
transition = self.state_machine.robot_protective_stop_engaged # type: ignore
|
|
99
|
+
break
|
|
89
100
|
|
|
90
101
|
self.robot_status_thread = None
|
|
91
102
|
|