isar 1.18.0__tar.gz → 1.19.1__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.18.0 → isar-1.19.1}/.github/workflows/project_automations.yml +5 -5
- {isar-1.18.0 → isar-1.19.1}/.github/workflows/publish_isar_base_image.yml +4 -4
- {isar-1.18.0 → isar-1.19.1}/.github/workflows/pythonpackage.yml +3 -3
- {isar-1.18.0 → isar-1.19.1}/.github/workflows/pythonpublish.yml +2 -2
- isar-1.19.1/.github/workflows/stale.yml +32 -0
- {isar-1.18.0 → isar-1.19.1}/Dockerfile +2 -2
- {isar-1.18.0 → isar-1.19.1}/PKG-INFO +13 -2
- {isar-1.18.0 → isar-1.19.1}/README.md +11 -0
- {isar-1.18.0 → isar-1.19.1}/main.py +0 -12
- {isar-1.18.0 → isar-1.19.1}/setup.py +1 -1
- isar-1.19.1/src/isar/__init__.py +6 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/config/log.py +4 -3
- {isar-1.18.0 → isar-1.19.1}/src/isar/config/settings.py +17 -15
- {isar-1.18.0 → isar-1.19.1}/src/isar/services/service_connections/mqtt/robot_heartbeat_publisher.py +2 -2
- {isar-1.18.0 → isar-1.19.1}/src/isar/services/service_connections/mqtt/robot_info_publisher.py +2 -2
- {isar-1.18.0 → isar-1.19.1}/src/isar/state_machine/state_machine.py +52 -14
- {isar-1.18.0 → isar-1.19.1}/src/isar/state_machine/states/__init__.py +1 -0
- isar-1.19.1/src/isar/state_machine/states/idle.py +85 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/state_machine/states/monitor.py +3 -5
- isar-1.19.1/src/isar/state_machine/states/offline.py +62 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/state_machine/states_enum.py +1 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/storage/uploader.py +8 -7
- {isar-1.18.0 → isar-1.19.1}/src/isar/storage/utilities.py +3 -3
- {isar-1.18.0 → isar-1.19.1}/src/isar.egg-info/PKG-INFO +13 -2
- {isar-1.18.0 → isar-1.19.1}/src/isar.egg-info/SOURCES.txt +1 -1
- {isar-1.18.0 → isar-1.19.1}/src/robot_interface/telemetry/mqtt_client.py +5 -7
- {isar-1.18.0 → isar-1.19.1}/tests/integration/turtlebot/test_successful_mission.py +3 -3
- {isar-1.18.0 → isar-1.19.1}/tests/isar/state_machine/test_state_machine.py +28 -1
- {isar-1.18.0 → isar-1.19.1}/tests/mocks/robot_interface.py +12 -0
- isar-1.18.0/.github/workflows/stale.yml +0 -33
- isar-1.18.0/src/isar/__init__.py +0 -6
- isar-1.18.0/src/isar/services/service_connections/mqtt/robot_status_publisher.py +0 -119
- isar-1.18.0/src/isar/state_machine/states/idle.py +0 -40
- {isar-1.18.0 → isar-1.19.1}/.dockerignore +0 -0
- {isar-1.18.0 → isar-1.19.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {isar-1.18.0 → isar-1.19.1}/.github/ISSUE_TEMPLATE/feature.md +0 -0
- {isar-1.18.0 → isar-1.19.1}/.github/ISSUE_TEMPLATE/improvement.md +0 -0
- {isar-1.18.0 → isar-1.19.1}/.github/release.yml +0 -0
- {isar-1.18.0 → isar-1.19.1}/.gitignore +0 -0
- {isar-1.18.0 → isar-1.19.1}/.pre-commit-config.yaml +0 -0
- {isar-1.18.0 → isar-1.19.1}/LICENSE +0 -0
- {isar-1.18.0 → isar-1.19.1}/SECURITY.md +0 -0
- {isar-1.18.0 → isar-1.19.1}/docker-compose-turtlebot.yml +0 -0
- {isar-1.18.0 → isar-1.19.1}/docker-compose.yml +0 -0
- {isar-1.18.0 → isar-1.19.1}/docs/Makefile +0 -0
- {isar-1.18.0 → isar-1.19.1}/docs/make.bat +0 -0
- {isar-1.18.0 → isar-1.19.1}/docs/rst_processing.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/docs/source/conf.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/docs/source/index.rst +0 -0
- {isar-1.18.0 → isar-1.19.1}/docs/source/readme_link.md +0 -0
- {isar-1.18.0 → isar-1.19.1}/docs/state_machine_diagram.png +0 -0
- {isar-1.18.0 → isar-1.19.1}/pyproject.toml +0 -0
- {isar-1.18.0 → isar-1.19.1}/radixconfig.yml +0 -0
- {isar-1.18.0 → isar-1.19.1}/setup.cfg +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/apis/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/apis/api.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/apis/models/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/apis/models/models.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/apis/models/start_mission_definition.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/apis/schedule/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/apis/schedule/scheduling_controller.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/apis/security/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/apis/security/authentication.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/config/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/config/certs/ca-cert.pem +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/config/configuration_error.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/config/keyvault/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/config/keyvault/keyvault_error.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/config/keyvault/keyvault_service.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/config/logging.conf +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/config/maps/JSP1_intermediate_deck.json +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/config/maps/JSP1_weather_deck.json +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/config/maps/default_map.json +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/config/maps/klab_b.json +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/config/maps/klab_compressor.json +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/config/maps/klab_turtlebot.json +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/config/maps/turtleworld.json +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/config/predefined_mission_definition/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/config/predefined_mission_definition/default_exr.json +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/config/predefined_mission_definition/default_mission.json +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/config/predefined_mission_definition/default_turtlebot.json +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/config/predefined_missions/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/config/predefined_missions/default.json +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/config/predefined_missions/default_turtlebot.json +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/config/predefined_poses/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/config/predefined_poses/predefined_poses.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/config/settings.env +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/mission_planner/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/mission_planner/local_planner.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/mission_planner/mission_planner_interface.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/mission_planner/sequential_task_selector.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/mission_planner/task_selector_interface.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/models/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/models/communication/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/models/communication/message.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/models/communication/queues/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/models/communication/queues/queue_io.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/models/communication/queues/queue_timeout_error.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/models/communication/queues/queues.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/models/communication/queues/status_queue.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/models/mission_metadata/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/modules.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/services/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/services/auth/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/services/auth/azure_credentials.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/services/readers/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/services/readers/base_reader.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/services/service_connections/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/services/service_connections/mqtt/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/services/service_connections/mqtt/mqtt_client.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/services/service_connections/request_handler.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/services/service_connections/stid/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/services/utilities/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/services/utilities/queue_utilities.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/services/utilities/scheduling_utilities.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/services/utilities/threaded_request.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/state_machine/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/state_machine/states/initialize.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/state_machine/states/initiate.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/state_machine/states/off.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/state_machine/states/paused.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/state_machine/states/stop.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/storage/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/storage/blob_storage.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/storage/local_storage.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/storage/slimm_storage.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar/storage/storage_interface.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar.egg-info/dependency_links.txt +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar.egg-info/requires.txt +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/isar.egg-info/top_level.txt +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/robot_interface/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/robot_interface/models/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/robot_interface/models/exceptions/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/robot_interface/models/exceptions/robot_exceptions.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/robot_interface/models/initialize/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/robot_interface/models/initialize/initialize_params.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/robot_interface/models/inspection/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/robot_interface/models/inspection/inspection.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/robot_interface/models/mission/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/robot_interface/models/mission/mission.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/robot_interface/models/mission/status.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/robot_interface/models/mission/step.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/robot_interface/models/mission/task.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/robot_interface/models/robots/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/robot_interface/models/robots/robot_model.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/robot_interface/robot_interface.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/robot_interface/telemetry/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/robot_interface/telemetry/payloads.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/robot_interface/test_robot_interface.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/robot_interface/utilities/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/robot_interface/utilities/json_service.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/src/robot_interface/utilities/uuid_string_factory.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/conftest.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/integration/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/integration/turtlebot/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/integration/turtlebot/config/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/integration/turtlebot/config/maps/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/integration/turtlebot/config/maps/turtleworld.json +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/integration/turtlebot/config/missions/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/integration/turtlebot/config/missions/default.json +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/apis/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/apis/scheduler/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/apis/scheduler/test_scheduler_router.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/apis/security/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/apis/security/test_authentication.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/mission/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/mission/test_mission.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/models/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/models/communication/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/models/communication/test_queues.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/models/example_mission_definition.json +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/models/test_start_mission_definition.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/services/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/services/readers/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/services/readers/test_base_reader.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/services/readers/test_mission_reader.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/services/service_connections/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/services/service_connections/echo/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/services/service_connections/test_base_request_handler.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/services/utilities/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/services/utilities/test_queue_utilities.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/services/utilities/test_scheduling_utilities.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/state_machine/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/state_machine/states/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/state_machine/states/test_monitor.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/storage/test_blob_storage.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/isar/storage/test_uploader.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/mocks/__init__.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/mocks/blob_storage.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/mocks/mission_definition.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/mocks/mqtt_client.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/mocks/pose.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/mocks/request.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/mocks/status.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/mocks/step.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/mocks/task.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/mocks/token.py +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/test_data/test_json_file.json +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/test_data/test_map_config/test_map_config.json +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/test_data/test_mission_not_working.json +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/test_data/test_mission_working.json +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/test_data/test_mission_working_no_tasks.json +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/test_data/test_thermal_image_mission.json +0 -0
- {isar-1.18.0 → isar-1.19.1}/tests/test_modules.py +0 -0
|
@@ -19,7 +19,7 @@ jobs:
|
|
|
19
19
|
if: github.event_name == 'issues' && github.event.action == 'opened' || github.event.action == 'reopened'
|
|
20
20
|
steps:
|
|
21
21
|
- name: 'Move issue to "Todo"'
|
|
22
|
-
uses: leonsteinhaeuser/project-beta-automations@
|
|
22
|
+
uses: leonsteinhaeuser/project-beta-automations@v2.1.0
|
|
23
23
|
with:
|
|
24
24
|
gh_token: ${{ secrets.MY_GITHUB_TOKEN }}
|
|
25
25
|
organization: equinor
|
|
@@ -32,7 +32,7 @@ jobs:
|
|
|
32
32
|
if: github.event_name == 'issues' && github.event.action == 'closed'
|
|
33
33
|
steps:
|
|
34
34
|
- name: 'Moved issue to "Done"'
|
|
35
|
-
uses: leonsteinhaeuser/project-beta-automations@
|
|
35
|
+
uses: leonsteinhaeuser/project-beta-automations@v2.1.0
|
|
36
36
|
with:
|
|
37
37
|
gh_token: ${{ secrets.MY_GITHUB_TOKEN }}
|
|
38
38
|
organization: equinor
|
|
@@ -45,7 +45,7 @@ jobs:
|
|
|
45
45
|
if: github.event_name == 'pull_request' && github.event.action == 'opened' || github.event.action == 'reopened' || github.event.action == 'review_requested'
|
|
46
46
|
steps:
|
|
47
47
|
- name: 'Move PR to "In Progress"'
|
|
48
|
-
uses: leonsteinhaeuser/project-beta-automations@
|
|
48
|
+
uses: leonsteinhaeuser/project-beta-automations@v2.1.0
|
|
49
49
|
with:
|
|
50
50
|
gh_token: ${{ secrets.MY_GITHUB_TOKEN }}
|
|
51
51
|
organization: equinor
|
|
@@ -58,7 +58,7 @@ jobs:
|
|
|
58
58
|
if: github.event_name == 'pull_request' && github.event.action == 'ready_for_review'
|
|
59
59
|
steps:
|
|
60
60
|
- name: 'Move PR to "Review"'
|
|
61
|
-
uses: leonsteinhaeuser/project-beta-automations@
|
|
61
|
+
uses: leonsteinhaeuser/project-beta-automations@v2.1.0
|
|
62
62
|
with:
|
|
63
63
|
gh_token: ${{ secrets.MY_GITHUB_TOKEN }}
|
|
64
64
|
organization: equinor
|
|
@@ -71,7 +71,7 @@ jobs:
|
|
|
71
71
|
if: github.event_name == 'pull_request' && github.event.action == 'closed'
|
|
72
72
|
steps:
|
|
73
73
|
- name: 'Move PR to "Done"'
|
|
74
|
-
uses: leonsteinhaeuser/project-beta-automations@
|
|
74
|
+
uses: leonsteinhaeuser/project-beta-automations@v2.1.0
|
|
75
75
|
with:
|
|
76
76
|
gh_token: ${{ secrets.MY_GITHUB_TOKEN }}
|
|
77
77
|
organization: equinor
|
|
@@ -27,10 +27,10 @@ jobs:
|
|
|
27
27
|
|
|
28
28
|
steps:
|
|
29
29
|
- name: Checkout repository
|
|
30
|
-
uses: actions/checkout@
|
|
30
|
+
uses: actions/checkout@v4
|
|
31
31
|
|
|
32
32
|
- name: Log in to the Container registry
|
|
33
|
-
uses: docker/login-action@
|
|
33
|
+
uses: docker/login-action@v3
|
|
34
34
|
with:
|
|
35
35
|
registry: ${{ env.REGISTRY }}
|
|
36
36
|
username: ${{ github.actor }}
|
|
@@ -38,12 +38,12 @@ jobs:
|
|
|
38
38
|
|
|
39
39
|
- name: Extract metadata (tags, labels) for Docker
|
|
40
40
|
id: meta
|
|
41
|
-
uses: docker/metadata-action@
|
|
41
|
+
uses: docker/metadata-action@v5
|
|
42
42
|
with:
|
|
43
43
|
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
44
44
|
|
|
45
45
|
- name: Build and push Docker image
|
|
46
|
-
uses: docker/build-push-action@
|
|
46
|
+
uses: docker/build-push-action@v5
|
|
47
47
|
with:
|
|
48
48
|
context: .
|
|
49
49
|
file: Dockerfile
|
|
@@ -14,13 +14,13 @@ jobs:
|
|
|
14
14
|
strategy:
|
|
15
15
|
fail-fast: false
|
|
16
16
|
matrix:
|
|
17
|
-
python-version: ["3.
|
|
17
|
+
python-version: ["3.11", "3.12"]
|
|
18
18
|
|
|
19
19
|
steps:
|
|
20
|
-
- uses: actions/checkout@
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
21
|
|
|
22
22
|
- name: Set up Python ${{ matrix.python-version }}
|
|
23
|
-
uses: actions/setup-python@
|
|
23
|
+
uses: actions/setup-python@v5
|
|
24
24
|
with:
|
|
25
25
|
python-version: ${{ matrix.python-version }}
|
|
26
26
|
|
|
@@ -8,9 +8,9 @@ jobs:
|
|
|
8
8
|
deploy:
|
|
9
9
|
runs-on: ubuntu-latest
|
|
10
10
|
steps:
|
|
11
|
-
- uses: actions/checkout@
|
|
11
|
+
- uses: actions/checkout@v4
|
|
12
12
|
- name: Set up Python
|
|
13
|
-
uses: actions/setup-python@
|
|
13
|
+
uses: actions/setup-python@v5
|
|
14
14
|
with:
|
|
15
15
|
python-version: "3.x"
|
|
16
16
|
- name: Install dependencies
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time.
|
|
2
|
+
#
|
|
3
|
+
# You can adjust the behavior by modifying this file.
|
|
4
|
+
# For more information, see:
|
|
5
|
+
# https://github.com/actions/stale
|
|
6
|
+
name: Mark stale issues and pull requests
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
schedule:
|
|
11
|
+
- cron: "35 8 * * *"
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
stale:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
permissions:
|
|
17
|
+
issues: write
|
|
18
|
+
pull-requests: write
|
|
19
|
+
|
|
20
|
+
steps:
|
|
21
|
+
- name: Close Stale Issues
|
|
22
|
+
uses: actions/stale@v9
|
|
23
|
+
with:
|
|
24
|
+
repo-token: ${{ secrets.STALE_ISSUE_TOKEN }}
|
|
25
|
+
stale-issue-message: "This issue has automatically been marked as stale as there has been no activity for 60 days."
|
|
26
|
+
stale-pr-message: "This pull request has automatically been marked as stale as there has been no activity for 30 days."
|
|
27
|
+
stale-issue-label: "stale"
|
|
28
|
+
stale-pr-label: "stale"
|
|
29
|
+
close-issue-message: "This issue has been closed automatically due to a lack of activity."
|
|
30
|
+
close-pr-message: "This pull request has been closed automatically due to a lack of activity."
|
|
31
|
+
days-before-pr-stale: 30
|
|
32
|
+
days-before-close: -1
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
FROM python:3.
|
|
1
|
+
FROM python:3.12-slim AS builder
|
|
2
2
|
|
|
3
3
|
WORKDIR /app
|
|
4
4
|
RUN apt-get update
|
|
@@ -15,7 +15,7 @@ RUN pip install .
|
|
|
15
15
|
# Install the base isar-robot package
|
|
16
16
|
RUN pip install isar-robot
|
|
17
17
|
|
|
18
|
-
FROM python:3.
|
|
18
|
+
FROM python:3.12-slim
|
|
19
19
|
WORKDIR /app
|
|
20
20
|
COPY --from=builder /opt/venv /opt/venv
|
|
21
21
|
ENV PATH="/opt/venv/bin:$PATH"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: isar
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.19.1
|
|
4
4
|
Summary: Integration and Supervisory control of Autonomous Robots
|
|
5
5
|
Home-page: https://github.com/equinor/isar
|
|
6
6
|
Author: Equinor ASA
|
|
@@ -12,7 +12,7 @@ Classifier: Programming Language :: Python
|
|
|
12
12
|
Classifier: Topic :: Scientific/Engineering
|
|
13
13
|
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
14
14
|
Classifier: Topic :: Software Development :: Libraries
|
|
15
|
-
Requires-Python: >=3.
|
|
15
|
+
Requires-Python: >=3.11
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
17
|
License-File: LICENSE
|
|
18
18
|
Requires-Dist: alitra>=1.1.3
|
|
@@ -415,6 +415,17 @@ ISAR_MQTT_PASSWORD
|
|
|
415
415
|
|
|
416
416
|
If not specified the password will default to an empty string.
|
|
417
417
|
|
|
418
|
+
## Running several ISAR instances locally
|
|
419
|
+
|
|
420
|
+
To run several ISAR instances in parallel locally:
|
|
421
|
+
1. Generate a guid: https://www.guidgenerator.com/
|
|
422
|
+
2. Open a new terminal in the isar folder
|
|
423
|
+
3. Run the following command before running main.py:
|
|
424
|
+
|
|
425
|
+
```
|
|
426
|
+
export ISAR_API_PORT=port_name_higher_than_1024 ISAR_ISAR_ID=guid ISAR_ROBOT_NAME=random_robot_name
|
|
427
|
+
```
|
|
428
|
+
|
|
418
429
|
# Contributions
|
|
419
430
|
|
|
420
431
|
Equinor welcomes all kinds of contributions, including code, bug reports, issues, feature requests, and documentation
|
|
@@ -361,6 +361,17 @@ ISAR_MQTT_PASSWORD
|
|
|
361
361
|
|
|
362
362
|
If not specified the password will default to an empty string.
|
|
363
363
|
|
|
364
|
+
## Running several ISAR instances locally
|
|
365
|
+
|
|
366
|
+
To run several ISAR instances in parallel locally:
|
|
367
|
+
1. Generate a guid: https://www.guidgenerator.com/
|
|
368
|
+
2. Open a new terminal in the isar folder
|
|
369
|
+
3. Run the following command before running main.py:
|
|
370
|
+
|
|
371
|
+
```
|
|
372
|
+
export ISAR_API_PORT=port_name_higher_than_1024 ISAR_ISAR_ID=guid ISAR_ROBOT_NAME=random_robot_name
|
|
373
|
+
```
|
|
374
|
+
|
|
364
375
|
# Contributions
|
|
365
376
|
|
|
366
377
|
Equinor welcomes all kinds of contributions, including code, bug reports, issues, feature requests, and documentation
|
|
@@ -19,9 +19,6 @@ from isar.services.service_connections.mqtt.robot_heartbeat_publisher import (
|
|
|
19
19
|
from isar.services.service_connections.mqtt.robot_info_publisher import (
|
|
20
20
|
RobotInfoPublisher,
|
|
21
21
|
)
|
|
22
|
-
from isar.services.service_connections.mqtt.robot_status_publisher import (
|
|
23
|
-
RobotStatusPublisher,
|
|
24
|
-
)
|
|
25
22
|
from isar.state_machine.state_machine import StateMachine, main
|
|
26
23
|
from isar.storage.uploader import Uploader
|
|
27
24
|
from robot_interface.robot_interface import RobotInterface
|
|
@@ -56,15 +53,6 @@ if __name__ == "__main__":
|
|
|
56
53
|
target=mqtt_client.run, name="ISAR MQTT Client", daemon=True
|
|
57
54
|
)
|
|
58
55
|
threads.append(mqtt_thread)
|
|
59
|
-
robot_status_publisher: RobotStatusPublisher = RobotStatusPublisher(
|
|
60
|
-
mqtt_queue=queues.mqtt_queue, robot=robot, state_machine=state_machine
|
|
61
|
-
)
|
|
62
|
-
robot_status_thread: Thread = Thread(
|
|
63
|
-
target=robot_status_publisher.run,
|
|
64
|
-
name="ISAR Robot Status Publisher",
|
|
65
|
-
daemon=True,
|
|
66
|
-
)
|
|
67
|
-
threads.append(robot_status_thread)
|
|
68
56
|
|
|
69
57
|
robot_info_publisher: RobotInfoPublisher = RobotInfoPublisher(
|
|
70
58
|
mqtt_queue=queues.mqtt_queue
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import importlib.resources as pkg_resources
|
|
2
1
|
import logging
|
|
3
2
|
import logging.config
|
|
3
|
+
from importlib.resources import as_file, files
|
|
4
4
|
|
|
5
5
|
import yaml
|
|
6
6
|
from opencensus.ext.azure.log_exporter import AzureLogHandler
|
|
@@ -14,8 +14,9 @@ from isar.config.settings import settings
|
|
|
14
14
|
|
|
15
15
|
def setup_loggers(keyvault: Keyvault) -> None:
|
|
16
16
|
log_levels: dict = settings.LOG_LEVELS
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
source = files("isar").joinpath("config").joinpath("logging.conf")
|
|
18
|
+
with as_file(source) as f:
|
|
19
|
+
log_config = yaml.safe_load(open(f))
|
|
19
20
|
|
|
20
21
|
logging.config.dictConfig(log_config)
|
|
21
22
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import importlib.resources as pkg_resources
|
|
2
1
|
import os
|
|
2
|
+
from importlib.resources import as_file, files
|
|
3
3
|
from typing import Any, List, Optional
|
|
4
4
|
|
|
5
5
|
from dotenv import load_dotenv
|
|
@@ -14,11 +14,12 @@ from robot_interface.telemetry.payloads import VideoStream
|
|
|
14
14
|
class Settings(BaseSettings):
|
|
15
15
|
def __init__(self) -> None:
|
|
16
16
|
try:
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
source = files("isar").joinpath("config").joinpath("settings.env")
|
|
18
|
+
with as_file(source) as eml:
|
|
19
|
+
env_file = eml
|
|
19
20
|
except ModuleNotFoundError:
|
|
20
|
-
|
|
21
|
-
super().__init__(_env_file=
|
|
21
|
+
env_file = None
|
|
22
|
+
super().__init__(_env_file=env_file)
|
|
22
23
|
|
|
23
24
|
# Determines which robot package ISAR will attempt to import
|
|
24
25
|
# Name must match with an installed python package in the local environment
|
|
@@ -229,14 +230,13 @@ class Settings(BaseSettings):
|
|
|
229
230
|
DATA_CLASSIFICATION: str = Field(default="internal")
|
|
230
231
|
|
|
231
232
|
# List of MQTT Topics
|
|
232
|
-
|
|
233
|
+
TOPIC_ISAR_STATUS: str = Field(default="status", validate_default=True)
|
|
233
234
|
TOPIC_ISAR_MISSION: str = Field(default="mission", validate_default=True)
|
|
234
235
|
TOPIC_ISAR_TASK: str = Field(default="task", validate_default=True)
|
|
235
236
|
TOPIC_ISAR_STEP: str = Field(default="step", validate_default=True)
|
|
236
237
|
TOPIC_ISAR_INSPECTION_RESULT: str = Field(
|
|
237
238
|
default="inspection_result", validate_default=True
|
|
238
239
|
)
|
|
239
|
-
TOPIC_ISAR_ROBOT_STATUS: str = Field(default="robot_status", validate_default=True)
|
|
240
240
|
TOPIC_ISAR_ROBOT_INFO: str = Field(default="robot_info", validate_default=True)
|
|
241
241
|
TOPIC_ISAR_ROBOT_HEARTBEAT: str = Field(
|
|
242
242
|
default="robot_heartbeat", validate_default=True
|
|
@@ -284,11 +284,10 @@ class Settings(BaseSettings):
|
|
|
284
284
|
}
|
|
285
285
|
|
|
286
286
|
@field_validator(
|
|
287
|
-
"
|
|
287
|
+
"TOPIC_ISAR_STATUS",
|
|
288
288
|
"TOPIC_ISAR_MISSION",
|
|
289
289
|
"TOPIC_ISAR_TASK",
|
|
290
290
|
"TOPIC_ISAR_STEP",
|
|
291
|
-
"TOPIC_ISAR_ROBOT_STATUS",
|
|
292
291
|
"TOPIC_ISAR_ROBOT_INFO",
|
|
293
292
|
"TOPIC_ISAR_ROBOT_HEARTBEAT",
|
|
294
293
|
"TOPIC_ISAR_INSPECTION_RESULT",
|
|
@@ -312,13 +311,16 @@ settings = Settings()
|
|
|
312
311
|
class RobotSettings(BaseSettings):
|
|
313
312
|
def __init__(self) -> None:
|
|
314
313
|
try:
|
|
315
|
-
|
|
316
|
-
f"{settings.ROBOT_PACKAGE}
|
|
317
|
-
|
|
318
|
-
|
|
314
|
+
source = (
|
|
315
|
+
files(f"{settings.ROBOT_PACKAGE}")
|
|
316
|
+
.joinpath("config")
|
|
317
|
+
.joinpath("settings.env")
|
|
318
|
+
)
|
|
319
|
+
with as_file(source) as eml:
|
|
320
|
+
env_file = eml
|
|
319
321
|
except ModuleNotFoundError:
|
|
320
|
-
|
|
321
|
-
super().__init__(_env_file=
|
|
322
|
+
env_file = None
|
|
323
|
+
super().__init__(_env_file=env_file)
|
|
322
324
|
|
|
323
325
|
# ISAR steps the robot is capable of performing
|
|
324
326
|
# This should be set in the robot package settings.env file
|
{isar-1.18.0 → isar-1.19.1}/src/isar/services/service_connections/mqtt/robot_heartbeat_publisher.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import time
|
|
3
|
-
from datetime import datetime
|
|
3
|
+
from datetime import UTC, datetime
|
|
4
4
|
from queue import Queue
|
|
5
5
|
|
|
6
6
|
from isar.config.settings import settings
|
|
@@ -18,7 +18,7 @@ class RobotHeartbeatPublisher:
|
|
|
18
18
|
payload: RobotHeartbeatPayload = RobotHeartbeatPayload(
|
|
19
19
|
isar_id=settings.ISAR_ID,
|
|
20
20
|
robot_name=settings.ROBOT_NAME,
|
|
21
|
-
timestamp=datetime.
|
|
21
|
+
timestamp=datetime.now(UTC),
|
|
22
22
|
)
|
|
23
23
|
|
|
24
24
|
self.mqtt_publisher.publish(
|
{isar-1.18.0 → isar-1.19.1}/src/isar/services/service_connections/mqtt/robot_info_publisher.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import time
|
|
3
|
-
from datetime import datetime
|
|
3
|
+
from datetime import UTC, datetime
|
|
4
4
|
from queue import Queue
|
|
5
5
|
|
|
6
6
|
from isar.config.settings import robot_settings, settings
|
|
@@ -25,7 +25,7 @@ class RobotInfoPublisher:
|
|
|
25
25
|
host=settings.API_HOST_VIEWED_EXTERNALLY,
|
|
26
26
|
port=settings.API_PORT,
|
|
27
27
|
capabilities=robot_settings.CAPABILITIES,
|
|
28
|
-
timestamp=datetime.
|
|
28
|
+
timestamp=datetime.now(UTC),
|
|
29
29
|
)
|
|
30
30
|
|
|
31
31
|
self.mqtt_publisher.publish(
|
|
@@ -2,7 +2,7 @@ import json
|
|
|
2
2
|
import logging
|
|
3
3
|
import queue
|
|
4
4
|
from collections import deque
|
|
5
|
-
from datetime import datetime
|
|
5
|
+
from datetime import UTC, datetime
|
|
6
6
|
from typing import Deque, List, Optional
|
|
7
7
|
|
|
8
8
|
from alitra import Pose
|
|
@@ -24,6 +24,7 @@ from isar.state_machine.states import (
|
|
|
24
24
|
Initiate,
|
|
25
25
|
Monitor,
|
|
26
26
|
Off,
|
|
27
|
+
Offline,
|
|
27
28
|
Paused,
|
|
28
29
|
Stop,
|
|
29
30
|
)
|
|
@@ -31,7 +32,12 @@ from isar.state_machine.states_enum import States
|
|
|
31
32
|
from robot_interface.models.exceptions.robot_exceptions import ErrorMessage
|
|
32
33
|
from robot_interface.models.initialize.initialize_params import InitializeParams
|
|
33
34
|
from robot_interface.models.mission.mission import Mission
|
|
34
|
-
from robot_interface.models.mission.status import
|
|
35
|
+
from robot_interface.models.mission.status import (
|
|
36
|
+
MissionStatus,
|
|
37
|
+
RobotStatus,
|
|
38
|
+
StepStatus,
|
|
39
|
+
TaskStatus,
|
|
40
|
+
)
|
|
35
41
|
from robot_interface.models.mission.step import Step
|
|
36
42
|
from robot_interface.models.mission.task import Task
|
|
37
43
|
from robot_interface.robot_interface import RobotInterface
|
|
@@ -88,6 +94,7 @@ class StateMachine(object):
|
|
|
88
94
|
self.monitor_state: State = Monitor(self)
|
|
89
95
|
self.initiate_state: State = Initiate(self)
|
|
90
96
|
self.off_state: State = Off(self)
|
|
97
|
+
self.offline_state: State = Offline(self)
|
|
91
98
|
|
|
92
99
|
self.states: List[State] = [
|
|
93
100
|
self.off_state,
|
|
@@ -97,6 +104,7 @@ class StateMachine(object):
|
|
|
97
104
|
self.monitor_state,
|
|
98
105
|
self.stop_state,
|
|
99
106
|
self.paused_state,
|
|
107
|
+
self.offline_state,
|
|
100
108
|
]
|
|
101
109
|
|
|
102
110
|
self.machine = Machine(self, states=self.states, initial="off", queued=True)
|
|
@@ -194,6 +202,18 @@ class StateMachine(object):
|
|
|
194
202
|
"dest": self.idle_state,
|
|
195
203
|
"before": self._mission_stopped,
|
|
196
204
|
},
|
|
205
|
+
{
|
|
206
|
+
"trigger": "robot_turned_offline",
|
|
207
|
+
"source": [self.idle_state],
|
|
208
|
+
"dest": self.offline_state,
|
|
209
|
+
"before": self._offline,
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"trigger": "robot_turned_online",
|
|
213
|
+
"source": self.offline_state,
|
|
214
|
+
"dest": self.idle_state,
|
|
215
|
+
"before": self._online,
|
|
216
|
+
},
|
|
197
217
|
]
|
|
198
218
|
)
|
|
199
219
|
|
|
@@ -239,6 +259,12 @@ class StateMachine(object):
|
|
|
239
259
|
def _off(self) -> None:
|
|
240
260
|
return
|
|
241
261
|
|
|
262
|
+
def _offline(self) -> None:
|
|
263
|
+
return
|
|
264
|
+
|
|
265
|
+
def _online(self) -> None:
|
|
266
|
+
return
|
|
267
|
+
|
|
242
268
|
def _resume(self) -> None:
|
|
243
269
|
self.logger.info(f"Resuming mission: {self.current_mission.id}")
|
|
244
270
|
self.current_mission.status = MissionStatus.InProgress
|
|
@@ -417,7 +443,7 @@ class StateMachine(object):
|
|
|
417
443
|
self.send_state_status()
|
|
418
444
|
self._log_state_transition(self.current_state)
|
|
419
445
|
self.logger.info(f"State: {self.current_state}")
|
|
420
|
-
self.
|
|
446
|
+
self.publish_status()
|
|
421
447
|
|
|
422
448
|
def reset_state_machine(self) -> None:
|
|
423
449
|
self.logger.info("Resetting state machine")
|
|
@@ -482,7 +508,7 @@ class StateMachine(object):
|
|
|
482
508
|
"error_description": (
|
|
483
509
|
error_message.error_description if error_message else None
|
|
484
510
|
),
|
|
485
|
-
"timestamp": datetime.
|
|
511
|
+
"timestamp": datetime.now(UTC),
|
|
486
512
|
},
|
|
487
513
|
cls=EnhancedJSONEncoder,
|
|
488
514
|
)
|
|
@@ -490,7 +516,8 @@ class StateMachine(object):
|
|
|
490
516
|
self.mqtt_publisher.publish(
|
|
491
517
|
topic=settings.TOPIC_ISAR_MISSION,
|
|
492
518
|
payload=payload,
|
|
493
|
-
|
|
519
|
+
qos=1,
|
|
520
|
+
retain=True,
|
|
494
521
|
)
|
|
495
522
|
|
|
496
523
|
def publish_task_status(self, task: Task) -> None:
|
|
@@ -514,7 +541,7 @@ class StateMachine(object):
|
|
|
514
541
|
"error_description": (
|
|
515
542
|
error_message.error_description if error_message else None
|
|
516
543
|
),
|
|
517
|
-
"timestamp": datetime.
|
|
544
|
+
"timestamp": datetime.now(UTC),
|
|
518
545
|
},
|
|
519
546
|
cls=EnhancedJSONEncoder,
|
|
520
547
|
)
|
|
@@ -522,7 +549,8 @@ class StateMachine(object):
|
|
|
522
549
|
self.mqtt_publisher.publish(
|
|
523
550
|
topic=settings.TOPIC_ISAR_TASK,
|
|
524
551
|
payload=payload,
|
|
525
|
-
|
|
552
|
+
qos=1,
|
|
553
|
+
retain=True,
|
|
526
554
|
)
|
|
527
555
|
|
|
528
556
|
def publish_step_status(self, step: Step) -> None:
|
|
@@ -548,7 +576,7 @@ class StateMachine(object):
|
|
|
548
576
|
"error_description": (
|
|
549
577
|
error_message.error_description if error_message else None
|
|
550
578
|
),
|
|
551
|
-
"timestamp": datetime.
|
|
579
|
+
"timestamp": datetime.now(UTC),
|
|
552
580
|
},
|
|
553
581
|
cls=EnhancedJSONEncoder,
|
|
554
582
|
)
|
|
@@ -556,28 +584,38 @@ class StateMachine(object):
|
|
|
556
584
|
self.mqtt_publisher.publish(
|
|
557
585
|
topic=settings.TOPIC_ISAR_STEP,
|
|
558
586
|
payload=payload,
|
|
559
|
-
|
|
587
|
+
qos=1,
|
|
588
|
+
retain=True,
|
|
560
589
|
)
|
|
561
590
|
|
|
562
|
-
def
|
|
591
|
+
def publish_status(self) -> None:
|
|
563
592
|
if not self.mqtt_publisher:
|
|
564
593
|
return
|
|
565
594
|
payload: str = json.dumps(
|
|
566
595
|
{
|
|
567
596
|
"isar_id": settings.ISAR_ID,
|
|
568
597
|
"robot_name": settings.ROBOT_NAME,
|
|
569
|
-
"
|
|
570
|
-
"timestamp": datetime.
|
|
598
|
+
"status": self._current_status(),
|
|
599
|
+
"timestamp": datetime.now(UTC),
|
|
571
600
|
},
|
|
572
601
|
cls=EnhancedJSONEncoder,
|
|
573
602
|
)
|
|
574
603
|
|
|
575
604
|
self.mqtt_publisher.publish(
|
|
576
|
-
topic=settings.
|
|
605
|
+
topic=settings.TOPIC_ISAR_STATUS,
|
|
577
606
|
payload=payload,
|
|
578
|
-
|
|
607
|
+
qos=1,
|
|
608
|
+
retain=True,
|
|
579
609
|
)
|
|
580
610
|
|
|
611
|
+
def _current_status(self) -> RobotStatus:
|
|
612
|
+
if self.current_state == States.Idle:
|
|
613
|
+
return RobotStatus.Available
|
|
614
|
+
elif self.current_state == States.Offline:
|
|
615
|
+
return RobotStatus.Offline
|
|
616
|
+
else:
|
|
617
|
+
return RobotStatus.Busy
|
|
618
|
+
|
|
581
619
|
def _log_state_transition(self, next_state):
|
|
582
620
|
"""Logs all state transitions that are not self-transitions."""
|
|
583
621
|
self.transitions_list.append(next_state)
|
|
@@ -0,0 +1,85 @@
|
|
|
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.models.communication.message import StartMissionMessage
|
|
9
|
+
from isar.services.utilities.threaded_request import (
|
|
10
|
+
ThreadedRequest,
|
|
11
|
+
ThreadedRequestNotFinishedError,
|
|
12
|
+
)
|
|
13
|
+
from robot_interface.models.exceptions.robot_exceptions import RobotException
|
|
14
|
+
from robot_interface.models.mission.status import RobotStatus
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from isar.state_machine.state_machine import StateMachine
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Idle(State):
|
|
21
|
+
def __init__(self, state_machine: "StateMachine") -> None:
|
|
22
|
+
super().__init__(name="idle", on_enter=self.start, on_exit=self.stop)
|
|
23
|
+
self.state_machine: "StateMachine" = state_machine
|
|
24
|
+
self.logger = logging.getLogger("state_machine")
|
|
25
|
+
self.robot_status_thread: Optional[ThreadedRequest] = None
|
|
26
|
+
self.last_robot_status_poll_time: float = time.time()
|
|
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
|
+
start_mission: Optional[StartMissionMessage] = (
|
|
40
|
+
self.state_machine.should_start_mission()
|
|
41
|
+
)
|
|
42
|
+
if start_mission:
|
|
43
|
+
self.state_machine.start_mission(
|
|
44
|
+
mission=start_mission.mission,
|
|
45
|
+
initial_pose=start_mission.initial_pose,
|
|
46
|
+
)
|
|
47
|
+
transition = self.state_machine.mission_started # type: ignore
|
|
48
|
+
break
|
|
49
|
+
time.sleep(self.state_machine.sleep_time)
|
|
50
|
+
|
|
51
|
+
time_from_last_robot_status_poll = (
|
|
52
|
+
time.time() - self.last_robot_status_poll_time
|
|
53
|
+
)
|
|
54
|
+
if (
|
|
55
|
+
time_from_last_robot_status_poll
|
|
56
|
+
< settings.ROBOT_API_STATUS_POLL_INTERVAL
|
|
57
|
+
):
|
|
58
|
+
continue
|
|
59
|
+
|
|
60
|
+
if not self.robot_status_thread:
|
|
61
|
+
self.robot_status_thread = ThreadedRequest(
|
|
62
|
+
request_func=self.state_machine.robot.robot_status
|
|
63
|
+
)
|
|
64
|
+
self.robot_status_thread.start_thread(
|
|
65
|
+
name="State Machine Offline Get Robot Status"
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
try:
|
|
69
|
+
robot_status: RobotStatus = self.robot_status_thread.get_output()
|
|
70
|
+
except ThreadedRequestNotFinishedError:
|
|
71
|
+
time.sleep(self.state_machine.sleep_time)
|
|
72
|
+
continue
|
|
73
|
+
|
|
74
|
+
except (RobotException,) as e:
|
|
75
|
+
self.logger.error(
|
|
76
|
+
f"Failed to get robot status because: {e.error_description}"
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
self.last_robot_status_poll_time = time.time()
|
|
80
|
+
|
|
81
|
+
if robot_status == RobotStatus.Offline:
|
|
82
|
+
transition = self.state_machine.robot_turned_offline # type: ignore
|
|
83
|
+
break
|
|
84
|
+
|
|
85
|
+
transition()
|