isar 1.16.16__tar.gz → 1.16.18__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.16.16 → isar-1.16.18}/PKG-INFO +1 -1
- {isar-1.16.16 → isar-1.16.18}/src/isar/config/settings.env +1 -1
- {isar-1.16.16 → isar-1.16.18}/src/isar/config/settings.py +4 -4
- {isar-1.16.16 → isar-1.16.18}/src/isar/services/service_connections/mqtt/robot_info_publisher.py +1 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/state_machine/state_machine.py +33 -60
- {isar-1.16.16 → isar-1.16.18}/src/isar/state_machine/states/monitor.py +40 -37
- {isar-1.16.16 → isar-1.16.18}/src/isar.egg-info/PKG-INFO +1 -1
- {isar-1.16.16 → isar-1.16.18}/src/robot_interface/telemetry/mqtt_client.py +18 -8
- {isar-1.16.16 → isar-1.16.18}/src/robot_interface/telemetry/payloads.py +8 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/state_machine/states/test_monitor.py +9 -6
- {isar-1.16.16 → isar-1.16.18}/tests/isar/state_machine/test_state_machine.py +36 -13
- {isar-1.16.16 → isar-1.16.18}/.dockerignore +0 -0
- {isar-1.16.16 → isar-1.16.18}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {isar-1.16.16 → isar-1.16.18}/.github/ISSUE_TEMPLATE/feature.md +0 -0
- {isar-1.16.16 → isar-1.16.18}/.github/ISSUE_TEMPLATE/improvement.md +0 -0
- {isar-1.16.16 → isar-1.16.18}/.github/release.yml +0 -0
- {isar-1.16.16 → isar-1.16.18}/.github/workflows/project_automations.yml +0 -0
- {isar-1.16.16 → isar-1.16.18}/.github/workflows/publish_isar_base_image.yml +0 -0
- {isar-1.16.16 → isar-1.16.18}/.github/workflows/pythonpackage.yml +0 -0
- {isar-1.16.16 → isar-1.16.18}/.github/workflows/pythonpublish.yml +0 -0
- {isar-1.16.16 → isar-1.16.18}/.github/workflows/repository_dispatch_on_merge.yml +0 -0
- {isar-1.16.16 → isar-1.16.18}/.github/workflows/stale.yml +0 -0
- {isar-1.16.16 → isar-1.16.18}/.gitignore +0 -0
- {isar-1.16.16 → isar-1.16.18}/.pre-commit-config.yaml +0 -0
- {isar-1.16.16 → isar-1.16.18}/Dockerfile +0 -0
- {isar-1.16.16 → isar-1.16.18}/LICENSE +0 -0
- {isar-1.16.16 → isar-1.16.18}/README.md +0 -0
- {isar-1.16.16 → isar-1.16.18}/SECURITY.md +0 -0
- {isar-1.16.16 → isar-1.16.18}/docker-compose-turtlebot.yml +0 -0
- {isar-1.16.16 → isar-1.16.18}/docker-compose.yml +0 -0
- {isar-1.16.16 → isar-1.16.18}/docs/Makefile +0 -0
- {isar-1.16.16 → isar-1.16.18}/docs/make.bat +0 -0
- {isar-1.16.16 → isar-1.16.18}/docs/rst_processing.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/docs/source/conf.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/docs/source/index.rst +0 -0
- {isar-1.16.16 → isar-1.16.18}/docs/source/readme_link.md +0 -0
- {isar-1.16.16 → isar-1.16.18}/docs/state_machine_diagram.png +0 -0
- {isar-1.16.16 → isar-1.16.18}/main.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/pyproject.toml +0 -0
- {isar-1.16.16 → isar-1.16.18}/radixconfig.yml +0 -0
- {isar-1.16.16 → isar-1.16.18}/setup.cfg +0 -0
- {isar-1.16.16 → isar-1.16.18}/setup.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/apis/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/apis/api.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/apis/models/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/apis/models/models.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/apis/models/start_mission_definition.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/apis/schedule/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/apis/schedule/scheduling_controller.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/apis/security/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/apis/security/authentication.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/config/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/config/certs/ca-cert.pem +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/config/configuration_error.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/config/keyvault/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/config/keyvault/keyvault_error.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/config/keyvault/keyvault_service.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/config/log.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/config/logging.conf +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/config/maps/JSP1_intermediate_deck.json +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/config/maps/JSP1_weather_deck.json +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/config/maps/default_map.json +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/config/maps/klab_b.json +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/config/maps/klab_compressor.json +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/config/maps/klab_turtlebot.json +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/config/maps/turtleworld.json +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/config/predefined_mission_definition/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/config/predefined_mission_definition/default_exr.json +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/config/predefined_mission_definition/default_mission.json +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/config/predefined_mission_definition/default_turtlebot.json +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/config/predefined_missions/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/config/predefined_missions/default.json +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/config/predefined_missions/default_turtlebot.json +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/config/predefined_poses/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/config/predefined_poses/predefined_poses.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/mission_planner/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/mission_planner/local_planner.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/mission_planner/mission_planner_interface.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/mission_planner/sequential_task_selector.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/mission_planner/task_selector_interface.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/models/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/models/communication/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/models/communication/message.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/models/communication/queues/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/models/communication/queues/queue_io.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/models/communication/queues/queue_timeout_error.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/models/communication/queues/queues.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/models/communication/queues/status_queue.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/models/mission_metadata/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/modules.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/services/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/services/auth/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/services/auth/azure_credentials.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/services/readers/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/services/readers/base_reader.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/services/service_connections/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/services/service_connections/mqtt/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/services/service_connections/mqtt/mqtt_client.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/services/service_connections/mqtt/robot_heartbeat_publisher.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/services/service_connections/mqtt/robot_status_publisher.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/services/service_connections/request_handler.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/services/service_connections/stid/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/services/utilities/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/services/utilities/queue_utilities.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/services/utilities/scheduling_utilities.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/services/utilities/threaded_request.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/state_machine/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/state_machine/states/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/state_machine/states/idle.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/state_machine/states/initialize.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/state_machine/states/initiate.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/state_machine/states/off.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/state_machine/states/paused.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/state_machine/states/stop.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/state_machine/states_enum.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/storage/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/storage/blob_storage.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/storage/local_storage.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/storage/slimm_storage.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/storage/storage_interface.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/storage/uploader.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar/storage/utilities.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar.egg-info/SOURCES.txt +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar.egg-info/dependency_links.txt +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar.egg-info/requires.txt +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/isar.egg-info/top_level.txt +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/robot_interface/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/robot_interface/models/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/robot_interface/models/exceptions/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/robot_interface/models/exceptions/robot_exceptions.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/robot_interface/models/initialize/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/robot_interface/models/initialize/initialize_params.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/robot_interface/models/inspection/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/robot_interface/models/inspection/inspection.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/robot_interface/models/mission/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/robot_interface/models/mission/mission.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/robot_interface/models/mission/status.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/robot_interface/models/mission/step.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/robot_interface/models/mission/task.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/robot_interface/models/robots/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/robot_interface/models/robots/robot_model.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/robot_interface/robot_interface.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/robot_interface/telemetry/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/robot_interface/test_robot_interface.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/robot_interface/utilities/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/robot_interface/utilities/json_service.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/src/robot_interface/utilities/uuid_string_factory.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/conftest.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/integration/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/integration/turtlebot/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/integration/turtlebot/config/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/integration/turtlebot/config/maps/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/integration/turtlebot/config/maps/turtleworld.json +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/integration/turtlebot/config/missions/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/integration/turtlebot/config/missions/default.json +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/integration/turtlebot/test_successful_mission.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/apis/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/apis/scheduler/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/apis/scheduler/test_scheduler_router.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/apis/security/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/apis/security/test_authentication.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/mission/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/mission/test_mission.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/models/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/models/communication/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/models/communication/test_queues.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/models/example_mission_definition.json +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/models/test_start_mission_definition.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/services/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/services/readers/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/services/readers/test_base_reader.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/services/readers/test_mission_reader.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/services/service_connections/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/services/service_connections/echo/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/services/service_connections/test_base_request_handler.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/services/utilities/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/services/utilities/test_queue_utilities.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/services/utilities/test_scheduling_utilities.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/state_machine/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/state_machine/states/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/storage/test_blob_storage.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/isar/storage/test_uploader.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/mocks/__init__.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/mocks/blob_storage.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/mocks/mission_definition.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/mocks/mqtt_client.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/mocks/pose.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/mocks/request.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/mocks/robot_interface.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/mocks/status.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/mocks/step.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/mocks/task.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/mocks/token.py +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/test_data/test_json_file.json +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/test_data/test_map_config/test_map_config.json +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/test_data/test_mission_not_working.json +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/test_data/test_mission_working.json +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/test_data/test_mission_working_no_tasks.json +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/test_data/test_thermal_image_mission.json +0 -0
- {isar-1.16.16 → isar-1.16.18}/tests/test_modules.py +0 -0
|
@@ -66,10 +66,10 @@ class Settings(BaseSettings):
|
|
|
66
66
|
UPLOAD_FAILURE_MAX_WAIT: int = Field(default=60)
|
|
67
67
|
|
|
68
68
|
# ISAR telemetry intervals
|
|
69
|
-
ROBOT_STATUS_PUBLISH_INTERVAL:
|
|
70
|
-
ROBOT_HEARTBEAT_PUBLISH_INTERVAL:
|
|
71
|
-
ROBOT_INFO_PUBLISH_INTERVAL:
|
|
72
|
-
ROBOT_API_STATUS_POLL_INTERVAL:
|
|
69
|
+
ROBOT_STATUS_PUBLISH_INTERVAL: float = Field(default=1)
|
|
70
|
+
ROBOT_HEARTBEAT_PUBLISH_INTERVAL: float = Field(default=1)
|
|
71
|
+
ROBOT_INFO_PUBLISH_INTERVAL: float = Field(default=5)
|
|
72
|
+
ROBOT_API_STATUS_POLL_INTERVAL: float = Field(default=5)
|
|
73
73
|
|
|
74
74
|
# FastAPI host
|
|
75
75
|
API_HOST_VIEWED_EXTERNALLY: str = Field(default="0.0.0.0")
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import logging
|
|
3
3
|
import queue
|
|
4
|
-
import time
|
|
5
4
|
from collections import deque
|
|
6
5
|
from datetime import datetime
|
|
7
6
|
from typing import Deque, List, Optional
|
|
@@ -226,18 +225,13 @@ class StateMachine(object):
|
|
|
226
225
|
def _initiated(self) -> None:
|
|
227
226
|
if self.stepwise_mission:
|
|
228
227
|
self.current_step.status = StepStatus.InProgress
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
)
|
|
235
|
-
|
|
236
|
-
self.current_mission.status = MissionStatus.InProgress
|
|
237
|
-
self.logger.info(
|
|
238
|
-
f"Successfully initiated full mission with ID: "
|
|
239
|
-
f"{str(self.current_mission.id)[:8]}"
|
|
240
|
-
)
|
|
228
|
+
self.current_mission.status = MissionStatus.InProgress
|
|
229
|
+
self.publish_step_status(step=self.current_step)
|
|
230
|
+
self.logger.info(
|
|
231
|
+
f"Successfully initiated "
|
|
232
|
+
f"{type(self.current_step).__name__} "
|
|
233
|
+
f"step: {str(self.current_step.id)[:8]}"
|
|
234
|
+
)
|
|
241
235
|
|
|
242
236
|
def _pause(self) -> None:
|
|
243
237
|
return
|
|
@@ -269,7 +263,9 @@ class StateMachine(object):
|
|
|
269
263
|
]
|
|
270
264
|
partially_fail_statuses = fail_statuses + [TaskStatus.PartiallySuccessful]
|
|
271
265
|
|
|
272
|
-
if
|
|
266
|
+
if len(self.current_mission.tasks) == 0:
|
|
267
|
+
self.current_mission.status = MissionStatus.Successful
|
|
268
|
+
elif all(task.status in fail_statuses for task in self.current_mission.tasks):
|
|
273
269
|
self.current_mission.error_message = ErrorMessage(
|
|
274
270
|
error_reason=None,
|
|
275
271
|
error_description="The mission failed because all tasks in the mission "
|
|
@@ -296,9 +292,12 @@ class StateMachine(object):
|
|
|
296
292
|
self.current_mission.status = MissionStatus.InProgress
|
|
297
293
|
self.publish_mission_status()
|
|
298
294
|
self.current_task = self.task_selector.next_task()
|
|
299
|
-
self.current_task
|
|
300
|
-
|
|
301
|
-
|
|
295
|
+
if self.current_task == None:
|
|
296
|
+
self._mission_finished()
|
|
297
|
+
else:
|
|
298
|
+
self.current_task.status = TaskStatus.InProgress
|
|
299
|
+
self.publish_task_status(task=self.current_task)
|
|
300
|
+
self.update_current_step()
|
|
302
301
|
|
|
303
302
|
def _step_finished(self) -> None:
|
|
304
303
|
self.publish_step_status(step=self.current_step)
|
|
@@ -307,28 +306,6 @@ class StateMachine(object):
|
|
|
307
306
|
|
|
308
307
|
def _full_mission_finished(self) -> None:
|
|
309
308
|
self.current_task = None
|
|
310
|
-
step_status: StepStatus = StepStatus.Failed
|
|
311
|
-
task_status: TaskStatus = TaskStatus.Failed
|
|
312
|
-
|
|
313
|
-
if self.current_mission.status == MissionStatus.Failed:
|
|
314
|
-
step_status = StepStatus.Failed
|
|
315
|
-
task_status = TaskStatus.Failed
|
|
316
|
-
elif self.current_mission.status == MissionStatus.Cancelled:
|
|
317
|
-
step_status = StepStatus.Cancelled
|
|
318
|
-
task_status = TaskStatus.Cancelled
|
|
319
|
-
elif (
|
|
320
|
-
self.current_mission.status == MissionStatus.Successful
|
|
321
|
-
or self.current_mission.status == MissionStatus.PartiallySuccessful
|
|
322
|
-
):
|
|
323
|
-
step_status = StepStatus.Successful
|
|
324
|
-
task_status = TaskStatus.Successful
|
|
325
|
-
|
|
326
|
-
for task in self.current_mission.tasks:
|
|
327
|
-
task.status = task_status
|
|
328
|
-
for step in task.steps:
|
|
329
|
-
step.status = step_status
|
|
330
|
-
self.publish_step_status(step=step)
|
|
331
|
-
self.publish_task_status(task=task)
|
|
332
309
|
|
|
333
310
|
def _mission_paused(self) -> None:
|
|
334
311
|
self.logger.info(f"Pausing mission: {self.current_mission.id}")
|
|
@@ -349,26 +326,12 @@ class StateMachine(object):
|
|
|
349
326
|
self.stopped = True
|
|
350
327
|
|
|
351
328
|
def _initiate_failed(self) -> None:
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
self._finalize()
|
|
359
|
-
|
|
360
|
-
else:
|
|
361
|
-
self.current_task = None
|
|
362
|
-
step_status: StepStatus = StepStatus.Cancelled
|
|
363
|
-
task_status: TaskStatus = TaskStatus.Cancelled
|
|
364
|
-
|
|
365
|
-
for task in self.current_mission.tasks:
|
|
366
|
-
task.status = task_status
|
|
367
|
-
for step in task.steps:
|
|
368
|
-
step.status = step_status
|
|
369
|
-
self.publish_step_status(step=step)
|
|
370
|
-
self.publish_task_status(task=task)
|
|
371
|
-
self._finalize()
|
|
329
|
+
self.current_step.status = StepStatus.Failed
|
|
330
|
+
self.current_task.update_task_status()
|
|
331
|
+
self.current_mission.status = MissionStatus.Failed
|
|
332
|
+
self.publish_step_status(step=self.current_step)
|
|
333
|
+
self.publish_task_status(task=self.current_task)
|
|
334
|
+
self._finalize()
|
|
372
335
|
|
|
373
336
|
def _initiate_infeasible(self) -> None:
|
|
374
337
|
if self.stepwise_mission:
|
|
@@ -435,9 +398,19 @@ class StateMachine(object):
|
|
|
435
398
|
self.current_task = None
|
|
436
399
|
|
|
437
400
|
def update_current_step(self):
|
|
438
|
-
if self.current_task:
|
|
401
|
+
if self.current_task != None:
|
|
439
402
|
self.current_step = self.current_task.next_step()
|
|
440
403
|
|
|
404
|
+
def update_remaining_steps(self):
|
|
405
|
+
if self.current_task:
|
|
406
|
+
for step in self.current_task.steps:
|
|
407
|
+
if (
|
|
408
|
+
step.status == StepStatus.InProgress
|
|
409
|
+
or step.status == StepStatus.NotStarted
|
|
410
|
+
):
|
|
411
|
+
step.status = self.current_task.status
|
|
412
|
+
self.publish_step_status(step=step)
|
|
413
|
+
|
|
441
414
|
def update_state(self):
|
|
442
415
|
"""Updates the current state of the state machine."""
|
|
443
416
|
self.current_state = States(self.state)
|
|
@@ -6,6 +6,7 @@ from typing import Callable, Optional, Sequence, TYPE_CHECKING, Tuple, Union
|
|
|
6
6
|
from injector import inject
|
|
7
7
|
from transitions import State
|
|
8
8
|
|
|
9
|
+
from isar.mission_planner.task_selector_interface import TaskSelectorStop
|
|
9
10
|
from isar.services.utilities.threaded_request import (
|
|
10
11
|
ThreadedRequest,
|
|
11
12
|
ThreadedRequestNotFinishedError,
|
|
@@ -19,7 +20,7 @@ from robot_interface.models.exceptions.robot_exceptions import (
|
|
|
19
20
|
)
|
|
20
21
|
from robot_interface.models.inspection.inspection import Inspection
|
|
21
22
|
from robot_interface.models.mission.mission import Mission
|
|
22
|
-
from robot_interface.models.mission.status import MissionStatus
|
|
23
|
+
from robot_interface.models.mission.status import MissionStatus, TaskStatus
|
|
23
24
|
from robot_interface.models.mission.step import InspectionStep, Step, StepStatus
|
|
24
25
|
|
|
25
26
|
if TYPE_CHECKING:
|
|
@@ -56,16 +57,10 @@ class Monitor(State):
|
|
|
56
57
|
break
|
|
57
58
|
|
|
58
59
|
if not self.step_status_thread:
|
|
59
|
-
|
|
60
|
-
self.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
)
|
|
64
|
-
else:
|
|
65
|
-
self._run_get_status_thread(
|
|
66
|
-
status_function=self.state_machine.robot.mission_status,
|
|
67
|
-
thread_name="State Machine Monitor Get Mission Status",
|
|
68
|
-
)
|
|
60
|
+
self._run_get_status_thread(
|
|
61
|
+
status_function=self.state_machine.robot.step_status,
|
|
62
|
+
thread_name="State Machine Monitor Get Step Status",
|
|
63
|
+
)
|
|
69
64
|
|
|
70
65
|
try:
|
|
71
66
|
status: Union[StepStatus, MissionStatus] = (
|
|
@@ -97,19 +92,19 @@ class Monitor(State):
|
|
|
97
92
|
|
|
98
93
|
except RobotException as e:
|
|
99
94
|
self._set_error_message(e)
|
|
100
|
-
|
|
101
|
-
status = StepStatus.Failed
|
|
102
|
-
else:
|
|
103
|
-
status = MissionStatus.Failed
|
|
95
|
+
status = StepStatus.Failed
|
|
104
96
|
|
|
105
97
|
self.logger.error(
|
|
106
98
|
f"Retrieving the status failed because: {e.error_description}"
|
|
107
99
|
)
|
|
108
100
|
|
|
109
|
-
if
|
|
101
|
+
if isinstance(status, StepStatus):
|
|
110
102
|
self.state_machine.current_step.status = status
|
|
111
103
|
elif isinstance(status, MissionStatus):
|
|
112
104
|
self.state_machine.current_mission.status = status
|
|
105
|
+
self.logger.error(
|
|
106
|
+
f"Received an invalid status update when monitoring mission. Only StepStatus is expected."
|
|
107
|
+
)
|
|
113
108
|
|
|
114
109
|
if self._should_upload_inspections():
|
|
115
110
|
get_inspections_thread = ThreadedRequest(
|
|
@@ -126,7 +121,28 @@ class Monitor(State):
|
|
|
126
121
|
transition = self.state_machine.step_finished # type: ignore
|
|
127
122
|
break
|
|
128
123
|
else:
|
|
129
|
-
if
|
|
124
|
+
if isinstance(status, StepStatus):
|
|
125
|
+
if self._step_finished(self.state_machine.current_step):
|
|
126
|
+
self.state_machine.current_task.update_task_status()
|
|
127
|
+
else: # If not all steps are done
|
|
128
|
+
self.state_machine.current_task.status = TaskStatus.InProgress
|
|
129
|
+
|
|
130
|
+
self.state_machine.publish_task_status(
|
|
131
|
+
self.state_machine.current_task
|
|
132
|
+
)
|
|
133
|
+
if self.state_machine.current_task.status == TaskStatus.Successful:
|
|
134
|
+
self.state_machine.update_remaining_steps()
|
|
135
|
+
try:
|
|
136
|
+
self.state_machine.current_task = (
|
|
137
|
+
self.state_machine.task_selector.next_task()
|
|
138
|
+
)
|
|
139
|
+
except TaskSelectorStop:
|
|
140
|
+
# Indicates that all tasks are finished
|
|
141
|
+
self.state_machine.current_task = None
|
|
142
|
+
transition = self.state_machine.full_mission_finished # type: ignore
|
|
143
|
+
break
|
|
144
|
+
self.state_machine.update_current_step()
|
|
145
|
+
elif self._mission_finished(self.state_machine.current_mission):
|
|
130
146
|
transition = self.state_machine.full_mission_finished # type: ignore
|
|
131
147
|
break
|
|
132
148
|
|
|
@@ -196,28 +212,15 @@ class Monitor(State):
|
|
|
196
212
|
return False
|
|
197
213
|
|
|
198
214
|
def _should_upload_inspections(self) -> bool:
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
)
|
|
206
|
-
else:
|
|
207
|
-
mission_status: MissionStatus = self.state_machine.current_mission.status
|
|
208
|
-
if (
|
|
209
|
-
mission_status == MissionStatus.Successful
|
|
210
|
-
or mission_status == MissionStatus.PartiallySuccessful
|
|
211
|
-
):
|
|
212
|
-
return True
|
|
213
|
-
return False
|
|
215
|
+
step: Step = self.state_machine.current_step
|
|
216
|
+
return (
|
|
217
|
+
self._step_finished(step)
|
|
218
|
+
and step.status == StepStatus.Successful
|
|
219
|
+
and isinstance(step, InspectionStep)
|
|
220
|
+
)
|
|
214
221
|
|
|
215
222
|
def _set_error_message(self, e: RobotException) -> None:
|
|
216
223
|
error_message: ErrorMessage = ErrorMessage(
|
|
217
224
|
error_reason=e.error_reason, error_description=e.error_description
|
|
218
225
|
)
|
|
219
|
-
|
|
220
|
-
self.state_machine.current_step.error_message = error_message
|
|
221
|
-
else:
|
|
222
|
-
if self.state_machine.current_mission:
|
|
223
|
-
self.state_machine.current_mission.error_message = error_message
|
|
226
|
+
self.state_machine.current_step.error_message = error_message
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import time
|
|
2
2
|
from abc import ABCMeta, abstractmethod
|
|
3
3
|
from queue import Queue
|
|
4
|
-
from typing import Callable, Tuple
|
|
4
|
+
from typing import Callable, Tuple, Type
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
import json
|
|
5
7
|
|
|
6
8
|
from robot_interface.models.exceptions.robot_exceptions import (
|
|
7
9
|
RobotTelemetryException,
|
|
8
10
|
)
|
|
11
|
+
from robot_interface.telemetry.payloads import CloudHealthPayload
|
|
12
|
+
from robot_interface.utilities.json_service import EnhancedJSONEncoder
|
|
9
13
|
|
|
10
14
|
|
|
11
15
|
class MqttClientInterface(metaclass=ABCMeta):
|
|
@@ -61,17 +65,23 @@ class MqttTelemetryPublisher(MqttClientInterface):
|
|
|
61
65
|
self.retain: bool = retain
|
|
62
66
|
|
|
63
67
|
def run(self, isar_id: str, robot_name: str) -> None:
|
|
68
|
+
self.cloud_healt_topic: str = f"isar/{isar_id}/cloud_health"
|
|
69
|
+
topic: str
|
|
70
|
+
payload: str
|
|
71
|
+
|
|
64
72
|
while True:
|
|
65
73
|
try:
|
|
66
|
-
payload
|
|
67
|
-
|
|
68
|
-
)
|
|
74
|
+
payload = self.telemetry_method(isar_id=isar_id, robot_name=robot_name)
|
|
75
|
+
topic = self.topic
|
|
69
76
|
except RobotTelemetryException:
|
|
70
|
-
|
|
77
|
+
payload = json.dumps(
|
|
78
|
+
CloudHealthPayload(isar_id, robot_name, datetime.utcnow()),
|
|
79
|
+
cls=EnhancedJSONEncoder,
|
|
80
|
+
)
|
|
81
|
+
topic = self.cloud_healt_topic
|
|
82
|
+
|
|
83
|
+
self.publish(topic=topic, payload=payload, qos=self.qos, retain=self.retain)
|
|
71
84
|
|
|
72
|
-
self.publish(
|
|
73
|
-
topic=self.topic, payload=payload, qos=self.qos, retain=self.retain
|
|
74
|
-
)
|
|
75
85
|
time.sleep(self.interval)
|
|
76
86
|
|
|
77
87
|
def publish(
|
|
@@ -15,6 +15,13 @@ class TelemetryPayload:
|
|
|
15
15
|
timestamp: datetime
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
@dataclass
|
|
19
|
+
class CloudHealthPayload:
|
|
20
|
+
isar_id: str
|
|
21
|
+
robot_name: str
|
|
22
|
+
timestamp: datetime
|
|
23
|
+
|
|
24
|
+
|
|
18
25
|
@dataclass
|
|
19
26
|
class TelemetryPosePayload(TelemetryPayload):
|
|
20
27
|
pose: Pose
|
|
@@ -65,6 +72,7 @@ class RobotInfoPayload:
|
|
|
65
72
|
video_streams: List[VideoStream]
|
|
66
73
|
host: str
|
|
67
74
|
port: int
|
|
75
|
+
capabilities: List[str]
|
|
68
76
|
timestamp: datetime
|
|
69
77
|
|
|
70
78
|
|
|
@@ -2,7 +2,7 @@ import pytest
|
|
|
2
2
|
|
|
3
3
|
from isar.state_machine.states.monitor import Monitor
|
|
4
4
|
from robot_interface.models.mission.mission import Mission
|
|
5
|
-
from robot_interface.models.mission.status import StepStatus
|
|
5
|
+
from robot_interface.models.mission.status import MissionStatus, StepStatus
|
|
6
6
|
from robot_interface.models.mission.step import Step, TakeImage
|
|
7
7
|
from robot_interface.models.mission.task import Task
|
|
8
8
|
from tests.mocks.step import MockStep
|
|
@@ -27,19 +27,22 @@ def test_step_finished(monitor: Monitor, mock_status, expected_output):
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
@pytest.mark.parametrize(
|
|
30
|
-
"
|
|
30
|
+
"is_status_successful, should_queue_upload",
|
|
31
31
|
[
|
|
32
|
-
(
|
|
33
|
-
(
|
|
32
|
+
(True, True),
|
|
33
|
+
(False, False),
|
|
34
34
|
],
|
|
35
35
|
)
|
|
36
36
|
def test_should_only_upload_if_status_is_completed(
|
|
37
|
-
monitor: Monitor,
|
|
37
|
+
monitor: Monitor, is_status_successful, should_queue_upload
|
|
38
38
|
):
|
|
39
39
|
step: TakeImage = MockStep.take_image_in_coordinate_direction()
|
|
40
|
-
step.status =
|
|
40
|
+
step.status = StepStatus.Successful if is_status_successful else StepStatus.Failed
|
|
41
41
|
task: Task = Task(steps=[step])
|
|
42
42
|
mission: Mission = Mission(tasks=[task])
|
|
43
|
+
mission.status = (
|
|
44
|
+
MissionStatus.Successful if is_status_successful else MissionStatus.Failed
|
|
45
|
+
)
|
|
43
46
|
|
|
44
47
|
monitor.state_machine.current_mission = mission
|
|
45
48
|
monitor.state_machine.current_task = task
|
|
@@ -90,27 +90,50 @@ def test_reset_state_machine(state_machine) -> None:
|
|
|
90
90
|
empty_mission: Mission = Mission([], None)
|
|
91
91
|
|
|
92
92
|
|
|
93
|
-
|
|
93
|
+
@pytest.mark.parametrize(
|
|
94
|
+
"should_run_stepwise",
|
|
95
|
+
[
|
|
96
|
+
(True),
|
|
97
|
+
(False),
|
|
98
|
+
],
|
|
99
|
+
)
|
|
100
|
+
def test_state_machine_transitions(
|
|
101
|
+
injector, state_machine_thread, should_run_stepwise
|
|
102
|
+
) -> None:
|
|
94
103
|
step_1: Step = DriveToPose(pose=MockPose.default_pose())
|
|
95
104
|
step_2: Step = TakeImage(target=MockPose.default_pose().position)
|
|
96
105
|
mission: Mission = Mission(tasks=[Task(steps=[step_1, step_2])]) # type: ignore
|
|
97
106
|
|
|
107
|
+
state_machine_thread.state_machine.stepwise_mission = should_run_stepwise
|
|
108
|
+
|
|
98
109
|
scheduling_utilities: SchedulingUtilities = injector.get(SchedulingUtilities)
|
|
99
110
|
scheduling_utilities.start_mission(mission=mission, initial_pose=None)
|
|
100
111
|
|
|
101
112
|
time.sleep(3)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
113
|
+
if should_run_stepwise:
|
|
114
|
+
expected_transitions_list = deque(
|
|
115
|
+
[
|
|
116
|
+
States.Idle,
|
|
117
|
+
States.Initialize,
|
|
118
|
+
States.Initiate,
|
|
119
|
+
States.Monitor,
|
|
120
|
+
States.Initiate,
|
|
121
|
+
States.Monitor,
|
|
122
|
+
States.Initiate,
|
|
123
|
+
States.Idle,
|
|
124
|
+
]
|
|
125
|
+
)
|
|
126
|
+
else:
|
|
127
|
+
expected_transitions_list = deque(
|
|
128
|
+
[
|
|
129
|
+
States.Idle,
|
|
130
|
+
States.Initialize,
|
|
131
|
+
States.Initiate,
|
|
132
|
+
States.Monitor,
|
|
133
|
+
States.Initiate,
|
|
134
|
+
States.Idle,
|
|
135
|
+
]
|
|
136
|
+
)
|
|
114
137
|
assert (
|
|
115
138
|
state_machine_thread.state_machine.transitions_list == expected_transitions_list
|
|
116
139
|
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{isar-1.16.16 → isar-1.16.18}/src/isar/config/predefined_mission_definition/default_exr.json
RENAMED
|
File without changes
|
{isar-1.16.16 → isar-1.16.18}/src/isar/config/predefined_mission_definition/default_mission.json
RENAMED
|
File without changes
|