isar 1.33.8__tar.gz → 1.34.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of isar might be problematic. Click here for more details.
- {isar-1.33.8 → isar-1.34.0}/.github/workflows/compile_requirements.yml +1 -1
- {isar-1.33.8 → isar-1.34.0}/.github/workflows/project_automations.yml +11 -5
- {isar-1.33.8 → isar-1.34.0}/.github/workflows/pythonpackage.yml +3 -0
- {isar-1.33.8 → isar-1.34.0}/.github/workflows/pythonpublish.yml +3 -0
- {isar-1.33.8 → isar-1.34.0}/PKG-INFO +2 -63
- {isar-1.33.8 → isar-1.34.0}/README.md +1 -62
- {isar-1.33.8 → isar-1.34.0}/src/isar/apis/models/models.py +2 -5
- {isar-1.33.8 → isar-1.34.0}/src/isar/config/settings.py +1 -8
- {isar-1.33.8 → isar-1.34.0}/src/isar/models/events.py +9 -10
- {isar-1.33.8 → isar-1.34.0}/src/isar/modules.py +5 -11
- {isar-1.33.8 → isar-1.34.0}/src/isar/robot/robot.py +109 -24
- isar-1.34.0/src/isar/robot/robot_monitor_mission.py +399 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/robot/robot_status.py +0 -10
- {isar-1.33.8 → isar-1.34.0}/src/isar/robot/robot_stop_mission.py +7 -7
- isar-1.34.0/src/isar/robot/robot_upload_inspection.py +80 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/services/utilities/scheduling_utilities.py +30 -10
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/state_machine.py +7 -223
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/states/await_next_mission.py +7 -6
- isar-1.34.0/src/isar/state_machine/states/going_to_lockdown.py +70 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/states/home.py +11 -15
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/states/intervention_needed.py +7 -6
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/states/lockdown.py +8 -7
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/states/monitor.py +39 -53
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/states/paused.py +19 -17
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/states/pausing.py +12 -27
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/states/pausing_return_home.py +12 -27
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/states/recharging.py +17 -11
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/states/return_home_paused.py +27 -23
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/states/returning_home.py +62 -55
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/states/stopping.py +13 -31
- isar-1.34.0/src/isar/state_machine/states/stopping_go_to_lockdown.py +59 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/states/stopping_return_home.py +26 -26
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/states/unknown_status.py +7 -4
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/transitions/functions/fail_mission.py +1 -9
- isar-1.34.0/src/isar/state_machine/transitions/functions/finish_mission.py +9 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/transitions/functions/pause.py +8 -7
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/transitions/functions/resume.py +3 -12
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/transitions/functions/return_home.py +1 -16
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/transitions/functions/robot_status.py +2 -12
- isar-1.34.0/src/isar/state_machine/transitions/functions/start_mission.py +40 -0
- isar-1.34.0/src/isar/state_machine/transitions/functions/stop.py +33 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/transitions/mission.py +2 -17
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/transitions/return_home.py +3 -24
- isar-1.34.0/src/isar/state_machine/utils/common_event_handlers.py +98 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar.egg-info/PKG-INFO +2 -63
- {isar-1.33.8 → isar-1.34.0}/src/isar.egg-info/SOURCES.txt +2 -5
- {isar-1.33.8 → isar-1.34.0}/src/robot_interface/models/mission/task.py +0 -10
- {isar-1.33.8 → isar-1.34.0}/src/robot_interface/robot_interface.py +25 -1
- {isar-1.33.8 → isar-1.34.0}/tests/conftest.py +1 -2
- {isar-1.33.8 → isar-1.34.0}/tests/integration/turtlebot/test_successful_mission.py +1 -1
- {isar-1.33.8 → isar-1.34.0}/tests/isar/apis/scheduler/test_scheduler_router.py +5 -19
- {isar-1.33.8 → isar-1.34.0}/tests/isar/state_machine/test_state_machine.py +128 -130
- {isar-1.33.8 → isar-1.34.0}/tests/test_double/robot_interface.py +3 -0
- isar-1.33.8/src/isar/mission_planner/sequential_task_selector.py +0 -23
- isar-1.33.8/src/isar/mission_planner/task_selector_interface.py +0 -31
- isar-1.33.8/src/isar/robot/robot_task_status.py +0 -87
- isar-1.33.8/src/isar/state_machine/states/going_to_lockdown.py +0 -80
- isar-1.33.8/src/isar/state_machine/states/stopping_go_to_lockdown.py +0 -79
- isar-1.33.8/src/isar/state_machine/transitions/functions/finish_mission.py +0 -39
- isar-1.33.8/src/isar/state_machine/transitions/functions/start_mission.py +0 -82
- isar-1.33.8/src/isar/state_machine/transitions/functions/stop.py +0 -62
- isar-1.33.8/src/isar/state_machine/utils/common_event_handlers.py +0 -181
- isar-1.33.8/tests/isar/state_machine/states/test_monitor.py +0 -54
- isar-1.33.8/tests/test_double/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/.dockerignore +0 -0
- {isar-1.33.8 → isar-1.34.0}/.env.test +0 -0
- {isar-1.33.8 → isar-1.34.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {isar-1.33.8 → isar-1.34.0}/.github/ISSUE_TEMPLATE/feature.md +0 -0
- {isar-1.33.8 → isar-1.34.0}/.github/ISSUE_TEMPLATE/improvement.md +0 -0
- {isar-1.33.8 → isar-1.34.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {isar-1.33.8 → isar-1.34.0}/.github/release.yml +0 -0
- {isar-1.33.8 → isar-1.34.0}/.github/workflows/stale.yml +0 -0
- {isar-1.33.8 → isar-1.34.0}/.gitignore +0 -0
- {isar-1.33.8 → isar-1.34.0}/.pre-commit-config.yaml +0 -0
- {isar-1.33.8 → isar-1.34.0}/LICENSE +0 -0
- {isar-1.33.8 → isar-1.34.0}/SECURITY.md +0 -0
- {isar-1.33.8 → isar-1.34.0}/docs/Makefile +0 -0
- {isar-1.33.8 → isar-1.34.0}/docs/full_state_machine_diagram.png +0 -0
- {isar-1.33.8 → isar-1.34.0}/docs/make.bat +0 -0
- {isar-1.33.8 → isar-1.34.0}/docs/mission_state_machine_diagram.png +0 -0
- {isar-1.33.8 → isar-1.34.0}/docs/robot_status_state_machine_diagram.png +0 -0
- {isar-1.33.8 → isar-1.34.0}/docs/rst_processing.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/docs/source/conf.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/docs/source/index.rst +0 -0
- {isar-1.33.8 → isar-1.34.0}/docs/source/readme_link.md +0 -0
- {isar-1.33.8 → isar-1.34.0}/docs/update_state_diagram.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/main.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/pyproject.toml +0 -0
- {isar-1.33.8 → isar-1.34.0}/radixconfig.yml +0 -0
- {isar-1.33.8 → isar-1.34.0}/requirements.txt +0 -0
- {isar-1.33.8 → isar-1.34.0}/setup.cfg +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/apis/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/apis/api.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/apis/models/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/apis/models/start_mission_definition.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/apis/robot_control/robot_controller.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/apis/schedule/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/apis/schedule/scheduling_controller.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/apis/security/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/apis/security/authentication.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/config/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/config/certs/ca-cert.pem +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/config/configuration_error.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/config/keyvault/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/config/keyvault/keyvault_error.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/config/keyvault/keyvault_service.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/config/log.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/config/logging.conf +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/config/maps/JSP1_intermediate_deck.json +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/config/maps/JSP1_weather_deck.json +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/config/maps/default_map.json +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/config/maps/klab_b.json +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/config/maps/klab_compressor.json +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/config/maps/klab_turtlebot.json +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/config/maps/turtleworld.json +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/config/open_telemetry.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/config/predefined_mission_definition/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/config/predefined_mission_definition/default_exr.json +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/config/predefined_mission_definition/default_mission.json +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/config/predefined_mission_definition/default_turtlebot.json +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/config/predefined_missions/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/config/predefined_missions/default.json +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/config/predefined_missions/default_turtlebot.json +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/eventhandlers/eventhandler.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/mission_planner/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/mission_planner/local_planner.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/mission_planner/mission_planner_interface.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/models/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/models/status.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/robot/robot_battery.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/robot/robot_pause_mission.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/robot/robot_start_mission.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/script.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/services/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/services/auth/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/services/auth/azure_credentials.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/services/service_connections/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/services/service_connections/mqtt/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/services/service_connections/mqtt/mqtt_client.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/services/service_connections/mqtt/robot_heartbeat_publisher.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/services/service_connections/mqtt/robot_info_publisher.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/services/service_connections/request_handler.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/services/utilities/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/services/utilities/robot_utilities.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/services/utilities/threaded_request.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/states/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/states/blocked_protective_stop.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/states/offline.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/states_enum.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/transitions/functions/utils.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/state_machine/transitions/robot_status.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/storage/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/storage/blob_storage.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/storage/local_storage.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/storage/storage_interface.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/storage/uploader.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar/storage/utilities.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar.egg-info/dependency_links.txt +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar.egg-info/entry_points.txt +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar.egg-info/requires.txt +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/isar.egg-info/top_level.txt +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/robot_interface/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/robot_interface/models/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/robot_interface/models/exceptions/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/robot_interface/models/exceptions/robot_exceptions.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/robot_interface/models/initialize/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/robot_interface/models/inspection/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/robot_interface/models/inspection/inspection.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/robot_interface/models/mission/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/robot_interface/models/mission/mission.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/robot_interface/models/mission/status.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/robot_interface/models/robots/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/robot_interface/models/robots/battery_state.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/robot_interface/models/robots/media.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/robot_interface/models/robots/robot_model.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/robot_interface/telemetry/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/robot_interface/telemetry/mqtt_client.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/robot_interface/telemetry/payloads.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/robot_interface/test_robot_interface.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/robot_interface/utilities/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/robot_interface/utilities/json_service.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/src/robot_interface/utilities/uuid_string_factory.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/integration/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/integration/turtlebot/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/integration/turtlebot/config/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/integration/turtlebot/config/maps/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/integration/turtlebot/config/maps/turtleworld.json +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/integration/turtlebot/config/missions/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/integration/turtlebot/config/missions/default.json +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/isar/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/isar/apis/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/isar/apis/models/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/isar/apis/models/example_mission_definition.json +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/isar/apis/models/test_start_mission_definition.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/isar/apis/scheduler/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/isar/apis/security/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/isar/apis/security/test_authentication.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/isar/mission/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/isar/mission/test_mission.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/isar/models/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/isar/models/communication/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/isar/models/communication/test_events.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/isar/services/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/isar/services/readers/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/isar/services/readers/test_mission_reader.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/isar/services/service_connections/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/isar/services/service_connections/echo/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/isar/services/service_connections/test_base_request_handler.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/isar/services/utilities/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/isar/services/utilities/test_queue_utilities.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/isar/services/utilities/test_scheduling_utilities.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/isar/state_machine/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/isar/storage/test_blob_storage.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/isar/storage/test_uploader.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/test_data/test_map_config/test_map_config.json +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/test_data/test_mission_not_working.json +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/test_data/test_mission_working.json +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/test_data/test_mission_working_no_tasks.json +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/test_data/test_thermal_image_mission.json +0 -0
- {isar-1.33.8/tests/isar/state_machine/states → isar-1.34.0/tests/test_double}/__init__.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/test_double/blob_storage.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/test_double/mission_definition.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/test_double/mqtt_client.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/test_double/pose.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/test_double/request.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/test_double/status.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/test_double/task.py +0 -0
- {isar-1.33.8 → isar-1.34.0}/tests/test_double/token.py +0 -0
|
@@ -38,7 +38,7 @@ jobs:
|
|
|
38
38
|
pip-compile --output-file=requirements.txt pyproject.toml --upgrade
|
|
39
39
|
|
|
40
40
|
- name: Create Pull Request
|
|
41
|
-
uses: peter-evans/create-pull-request@
|
|
41
|
+
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e #v7
|
|
42
42
|
with:
|
|
43
43
|
commit-message: "GHA: Update dependencies"
|
|
44
44
|
title: Update dependencies
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
name: Project automations
|
|
2
|
+
|
|
3
|
+
permissions:
|
|
4
|
+
contents: read
|
|
5
|
+
issues: write
|
|
6
|
+
pull-requests: write
|
|
7
|
+
|
|
2
8
|
on:
|
|
3
9
|
issues:
|
|
4
10
|
types:
|
|
@@ -19,7 +25,7 @@ jobs:
|
|
|
19
25
|
if: github.event_name == 'issues' && github.event.action == 'opened' || github.event.action == 'reopened'
|
|
20
26
|
steps:
|
|
21
27
|
- name: 'Move issue to "Todo"'
|
|
22
|
-
uses: leonsteinhaeuser/project-beta-automations@
|
|
28
|
+
uses: leonsteinhaeuser/project-beta-automations@939000fb1900c9fc4f7b5058a09d9f833ebc6859 #Version 2.2.1
|
|
23
29
|
with:
|
|
24
30
|
gh_token: ${{ secrets.MY_GITHUB_TOKEN }}
|
|
25
31
|
organization: equinor
|
|
@@ -32,7 +38,7 @@ jobs:
|
|
|
32
38
|
if: github.event_name == 'issues' && github.event.action == 'closed'
|
|
33
39
|
steps:
|
|
34
40
|
- name: 'Moved issue to "Done"'
|
|
35
|
-
uses: leonsteinhaeuser/project-beta-automations@
|
|
41
|
+
uses: leonsteinhaeuser/project-beta-automations@939000fb1900c9fc4f7b5058a09d9f833ebc6859 #Version 2.2.1
|
|
36
42
|
with:
|
|
37
43
|
gh_token: ${{ secrets.MY_GITHUB_TOKEN }}
|
|
38
44
|
organization: equinor
|
|
@@ -45,7 +51,7 @@ jobs:
|
|
|
45
51
|
if: github.event_name == 'pull_request' && github.event.action == 'opened' || github.event.action == 'reopened' || github.event.action == 'review_requested'
|
|
46
52
|
steps:
|
|
47
53
|
- name: 'Move PR to "In Progress"'
|
|
48
|
-
uses: leonsteinhaeuser/project-beta-automations@
|
|
54
|
+
uses: leonsteinhaeuser/project-beta-automations@939000fb1900c9fc4f7b5058a09d9f833ebc6859 #Version 2.2.1
|
|
49
55
|
with:
|
|
50
56
|
gh_token: ${{ secrets.MY_GITHUB_TOKEN }}
|
|
51
57
|
organization: equinor
|
|
@@ -58,7 +64,7 @@ jobs:
|
|
|
58
64
|
if: github.event_name == 'pull_request' && github.event.action == 'ready_for_review'
|
|
59
65
|
steps:
|
|
60
66
|
- name: 'Move PR to "Review"'
|
|
61
|
-
uses: leonsteinhaeuser/project-beta-automations@
|
|
67
|
+
uses: leonsteinhaeuser/project-beta-automations@939000fb1900c9fc4f7b5058a09d9f833ebc6859 #Version 2.2.1
|
|
62
68
|
with:
|
|
63
69
|
gh_token: ${{ secrets.MY_GITHUB_TOKEN }}
|
|
64
70
|
organization: equinor
|
|
@@ -71,7 +77,7 @@ jobs:
|
|
|
71
77
|
if: github.event_name == 'pull_request' && github.event.action == 'closed'
|
|
72
78
|
steps:
|
|
73
79
|
- name: 'Move PR to "Done"'
|
|
74
|
-
uses: leonsteinhaeuser/project-beta-automations@
|
|
80
|
+
uses: leonsteinhaeuser/project-beta-automations@939000fb1900c9fc4f7b5058a09d9f833ebc6859 #Version 2.2.1
|
|
75
81
|
with:
|
|
76
82
|
gh_token: ${{ secrets.MY_GITHUB_TOKEN }}
|
|
77
83
|
organization: equinor
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: isar
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.34.0
|
|
4
4
|
Summary: Integration and Supervisory control of Autonomous Robots
|
|
5
5
|
Author-email: Equinor ASA <fg_robots_dev@equinor.com>
|
|
6
6
|
License: Eclipse Public License version 2.0
|
|
@@ -402,68 +402,6 @@ You can create your own storage module by implementing the [storage interface](.
|
|
|
402
402
|
and adding your storage module to the selection [here](./src/isar/modules.py). Note that you must add your module as an
|
|
403
403
|
option in the dictionary.
|
|
404
404
|
|
|
405
|
-
## Task selection
|
|
406
|
-
|
|
407
|
-
The tasks of a mission are selected based on a task selector module, defined by the `TASK_SELECTOR` configuration variable. The default task selector is `sequential`. When using the default module, tasks are executed in sequential order defined by the current input mission.
|
|
408
|
-
|
|
409
|
-
### Implement you own task selector module
|
|
410
|
-
|
|
411
|
-
Custom task selector modules may be added by implementing additional versions of the [task selector interface](./src/isar/mission_planner/task_selector_interface.py).
|
|
412
|
-
|
|
413
|
-
For every custom module, the interface function `next_task()` must be implemented. All interface implementations by default have access to the list of tasks in the current mission through the member `self.tasks`, however additional variables may be supplied by adding arguments to `next_task()`. To comply with the interface definition, the function should return the next task upon every call, and raise the `TaskSelectorStop` exception when all tasks in the current mission have been completed:
|
|
414
|
-
|
|
415
|
-
```python
|
|
416
|
-
class CustomTaskSelector(TaskSelectorInterface):
|
|
417
|
-
...
|
|
418
|
-
def next_task(...) -> Task:
|
|
419
|
-
|
|
420
|
-
# Add code here
|
|
421
|
-
...
|
|
422
|
-
|
|
423
|
-
# Raise `TaskSelectorStop` when all tasks have been completed
|
|
424
|
-
...
|
|
425
|
-
```
|
|
426
|
-
|
|
427
|
-
Optionally, the `initialize()` function may be extended by supplementing the parameter list or function body:
|
|
428
|
-
|
|
429
|
-
```python
|
|
430
|
-
class CustomTaskSelector(TaskSelectorInterface):
|
|
431
|
-
...
|
|
432
|
-
def initialize(self, tasks: List[Task], ...) -> None:
|
|
433
|
-
super.initialize(tasks=tasks)
|
|
434
|
-
|
|
435
|
-
# Add supplementary code here
|
|
436
|
-
...
|
|
437
|
-
```
|
|
438
|
-
|
|
439
|
-
A custom task selector may be made available during [module selection](./src/isar/modules.py) by adding it to the series of options in the dictionary of injector modules. It can then be activated by overriding the task selector configuration variable:
|
|
440
|
-
|
|
441
|
-
```python
|
|
442
|
-
# Add custom task selector module to `modules.py`
|
|
443
|
-
|
|
444
|
-
class CustomTaskSelectorModule(Module):
|
|
445
|
-
@provider
|
|
446
|
-
@singleton
|
|
447
|
-
def provide_task_selector(self) -> TaskSelectorInterface:
|
|
448
|
-
return CustomTaskSelector()
|
|
449
|
-
|
|
450
|
-
...
|
|
451
|
-
|
|
452
|
-
# Make it available to select during injector instantiation
|
|
453
|
-
|
|
454
|
-
modules: dict[str, tuple[Module, Union[str, bool]]] = {
|
|
455
|
-
...
|
|
456
|
-
"task_selector": (
|
|
457
|
-
{
|
|
458
|
-
"sequential": SequentialTaskSelectorModule,
|
|
459
|
-
"custom": CustomTaskSelectorModule
|
|
460
|
-
}
|
|
461
|
-
...
|
|
462
|
-
)
|
|
463
|
-
...
|
|
464
|
-
}
|
|
465
|
-
```
|
|
466
|
-
|
|
467
405
|
## API authentication
|
|
468
406
|
|
|
469
407
|
The API has an option to include user authentication. This can be enabled by setting the environment variable
|
|
@@ -480,6 +418,7 @@ Enabling API authentication also requires the same environment variables. The re
|
|
|
480
418
|
AZURE_CLIENT_ID
|
|
481
419
|
AZURE_TENANT_ID
|
|
482
420
|
AZURE_CLIENT_SECRET
|
|
421
|
+
ISAR_BLOB_STORAGE_ACCOUNT
|
|
483
422
|
```
|
|
484
423
|
|
|
485
424
|
## MQTT communication
|
|
@@ -258,68 +258,6 @@ You can create your own storage module by implementing the [storage interface](.
|
|
|
258
258
|
and adding your storage module to the selection [here](./src/isar/modules.py). Note that you must add your module as an
|
|
259
259
|
option in the dictionary.
|
|
260
260
|
|
|
261
|
-
## Task selection
|
|
262
|
-
|
|
263
|
-
The tasks of a mission are selected based on a task selector module, defined by the `TASK_SELECTOR` configuration variable. The default task selector is `sequential`. When using the default module, tasks are executed in sequential order defined by the current input mission.
|
|
264
|
-
|
|
265
|
-
### Implement you own task selector module
|
|
266
|
-
|
|
267
|
-
Custom task selector modules may be added by implementing additional versions of the [task selector interface](./src/isar/mission_planner/task_selector_interface.py).
|
|
268
|
-
|
|
269
|
-
For every custom module, the interface function `next_task()` must be implemented. All interface implementations by default have access to the list of tasks in the current mission through the member `self.tasks`, however additional variables may be supplied by adding arguments to `next_task()`. To comply with the interface definition, the function should return the next task upon every call, and raise the `TaskSelectorStop` exception when all tasks in the current mission have been completed:
|
|
270
|
-
|
|
271
|
-
```python
|
|
272
|
-
class CustomTaskSelector(TaskSelectorInterface):
|
|
273
|
-
...
|
|
274
|
-
def next_task(...) -> Task:
|
|
275
|
-
|
|
276
|
-
# Add code here
|
|
277
|
-
...
|
|
278
|
-
|
|
279
|
-
# Raise `TaskSelectorStop` when all tasks have been completed
|
|
280
|
-
...
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
Optionally, the `initialize()` function may be extended by supplementing the parameter list or function body:
|
|
284
|
-
|
|
285
|
-
```python
|
|
286
|
-
class CustomTaskSelector(TaskSelectorInterface):
|
|
287
|
-
...
|
|
288
|
-
def initialize(self, tasks: List[Task], ...) -> None:
|
|
289
|
-
super.initialize(tasks=tasks)
|
|
290
|
-
|
|
291
|
-
# Add supplementary code here
|
|
292
|
-
...
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
A custom task selector may be made available during [module selection](./src/isar/modules.py) by adding it to the series of options in the dictionary of injector modules. It can then be activated by overriding the task selector configuration variable:
|
|
296
|
-
|
|
297
|
-
```python
|
|
298
|
-
# Add custom task selector module to `modules.py`
|
|
299
|
-
|
|
300
|
-
class CustomTaskSelectorModule(Module):
|
|
301
|
-
@provider
|
|
302
|
-
@singleton
|
|
303
|
-
def provide_task_selector(self) -> TaskSelectorInterface:
|
|
304
|
-
return CustomTaskSelector()
|
|
305
|
-
|
|
306
|
-
...
|
|
307
|
-
|
|
308
|
-
# Make it available to select during injector instantiation
|
|
309
|
-
|
|
310
|
-
modules: dict[str, tuple[Module, Union[str, bool]]] = {
|
|
311
|
-
...
|
|
312
|
-
"task_selector": (
|
|
313
|
-
{
|
|
314
|
-
"sequential": SequentialTaskSelectorModule,
|
|
315
|
-
"custom": CustomTaskSelectorModule
|
|
316
|
-
}
|
|
317
|
-
...
|
|
318
|
-
)
|
|
319
|
-
...
|
|
320
|
-
}
|
|
321
|
-
```
|
|
322
|
-
|
|
323
261
|
## API authentication
|
|
324
262
|
|
|
325
263
|
The API has an option to include user authentication. This can be enabled by setting the environment variable
|
|
@@ -336,6 +274,7 @@ Enabling API authentication also requires the same environment variables. The re
|
|
|
336
274
|
AZURE_CLIENT_ID
|
|
337
275
|
AZURE_TENANT_ID
|
|
338
276
|
AZURE_CLIENT_SECRET
|
|
277
|
+
ISAR_BLOB_STORAGE_ACCOUNT
|
|
339
278
|
```
|
|
340
279
|
|
|
341
280
|
## MQTT communication
|
|
@@ -19,11 +19,8 @@ class StartMissionResponse(BaseModel):
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class ControlMissionResponse(BaseModel):
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
mission_not_found: Optional[bool] = False
|
|
25
|
-
task_id: Optional[str]
|
|
26
|
-
task_status: Optional[str]
|
|
22
|
+
success: bool
|
|
23
|
+
failure_reason: Optional[str] = None
|
|
27
24
|
|
|
28
25
|
|
|
29
26
|
class MissionStartResponse(BaseModel):
|
|
@@ -59,9 +59,6 @@ class Settings(BaseSettings):
|
|
|
59
59
|
# issues
|
|
60
60
|
REQUEST_STATUS_COMMUNICATION_RECONNECT_DELAY: float = Field(default=10)
|
|
61
61
|
|
|
62
|
-
# Time allowed to clear the robot status before giving up
|
|
63
|
-
CLEAR_ROBOT_STATUS_TIMEOUT: int = Field(default=3)
|
|
64
|
-
|
|
65
62
|
# Number of attempts for state transitions resume and pause if failed
|
|
66
63
|
STATE_TRANSITION_NUM_RETIRES: int = Field(default=10)
|
|
67
64
|
|
|
@@ -109,10 +106,6 @@ class Settings(BaseSettings):
|
|
|
109
106
|
# Determines which mission planner module is used by ISAR
|
|
110
107
|
MISSION_PLANNER: str = Field(default="local")
|
|
111
108
|
|
|
112
|
-
# Determines which task selector module is used by ISAR
|
|
113
|
-
# Options: [sequential]
|
|
114
|
-
TASK_SELECTOR: str = Field(default="sequential")
|
|
115
|
-
|
|
116
109
|
# Determines which storage modules are used by ISAR
|
|
117
110
|
# Multiple storage modules can be chosen
|
|
118
111
|
# Each module will be called when storing results from inspections
|
|
@@ -168,7 +161,7 @@ class Settings(BaseSettings):
|
|
|
168
161
|
UPLOAD_INSPECTIONS_ASYNC: bool = Field(default=False)
|
|
169
162
|
|
|
170
163
|
# URL to storage account for Azure Blob Storage
|
|
171
|
-
BLOB_STORAGE_ACCOUNT: str = Field(default="
|
|
164
|
+
BLOB_STORAGE_ACCOUNT: str = Field(default="")
|
|
172
165
|
|
|
173
166
|
# Name of blob container in Azure Blob Storage [slimm test]
|
|
174
167
|
BLOB_CONTAINER: str = Field(default="test")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from collections import deque
|
|
2
2
|
from queue import Empty, Queue
|
|
3
|
-
from typing import Generic, Optional, TypeVar
|
|
3
|
+
from typing import Generic, Optional, Tuple, TypeVar
|
|
4
4
|
|
|
5
5
|
from transitions import State
|
|
6
6
|
|
|
@@ -12,7 +12,7 @@ from isar.apis.models.models import (
|
|
|
12
12
|
from isar.config.settings import settings
|
|
13
13
|
from robot_interface.models.exceptions.robot_exceptions import ErrorMessage
|
|
14
14
|
from robot_interface.models.mission.mission import Mission
|
|
15
|
-
from robot_interface.models.mission.status import
|
|
15
|
+
from robot_interface.models.mission.status import MissionStatus, RobotStatus
|
|
16
16
|
from robot_interface.models.mission.task import TASKS
|
|
17
17
|
|
|
18
18
|
T = TypeVar("T")
|
|
@@ -126,18 +126,16 @@ class StateMachineEvents:
|
|
|
126
126
|
self.start_mission: Event[Mission] = Event("start_mission")
|
|
127
127
|
self.stop_mission: Event[bool] = Event("stop_mission")
|
|
128
128
|
self.pause_mission: Event[bool] = Event("pause_mission")
|
|
129
|
-
self.task_status_request: Event[str] = Event("task_status_request")
|
|
130
|
-
self.clear_robot_status: Event[bool] = Event("clear_robot_status")
|
|
131
129
|
|
|
132
130
|
|
|
133
131
|
class RobotServiceEvents:
|
|
134
132
|
def __init__(self) -> None:
|
|
135
|
-
self.
|
|
136
|
-
|
|
133
|
+
self.mission_status_updated: Event[MissionStatus] = Event(
|
|
134
|
+
"mission_status_updated"
|
|
135
|
+
)
|
|
137
136
|
self.mission_started: Event[bool] = Event("mission_started")
|
|
138
137
|
self.mission_failed: Event[ErrorMessage] = Event("mission_failed")
|
|
139
138
|
self.robot_status_changed: Event[bool] = Event("robot_status_changed")
|
|
140
|
-
self.robot_status_cleared: Event[bool] = Event("robot_status_cleared")
|
|
141
139
|
self.mission_failed_to_stop: Event[ErrorMessage] = Event(
|
|
142
140
|
"mission_failed_to_stop"
|
|
143
141
|
)
|
|
@@ -150,16 +148,17 @@ class RobotServiceEvents:
|
|
|
150
148
|
self.mission_successfully_paused: Event[bool] = Event(
|
|
151
149
|
"mission_successfully_paused"
|
|
152
150
|
)
|
|
151
|
+
self.request_inspection_upload: Event[Tuple[TASKS, Mission]] = Event(
|
|
152
|
+
"request_inspection_upload"
|
|
153
|
+
)
|
|
153
154
|
|
|
154
155
|
|
|
155
156
|
class SharedState:
|
|
156
157
|
def __init__(self) -> None:
|
|
157
158
|
self.state: Event[State] = Event("state")
|
|
158
159
|
self.robot_status: Event[RobotStatus] = Event("robot_status")
|
|
159
|
-
self.state_machine_current_task: Event[TASKS] = Event(
|
|
160
|
-
"state_machine_current_task"
|
|
161
|
-
)
|
|
162
160
|
self.robot_battery_level: Event[float] = Event("robot_battery_level")
|
|
161
|
+
self.mission_id: Event[Optional[str]] = Event("mission_id")
|
|
163
162
|
|
|
164
163
|
|
|
165
164
|
class EventTimeoutError(Exception):
|
|
@@ -10,8 +10,6 @@ from isar.apis.security.authentication import Authenticator
|
|
|
10
10
|
from isar.config.keyvault.keyvault_service import Keyvault
|
|
11
11
|
from isar.config.settings import settings
|
|
12
12
|
from isar.mission_planner.local_planner import LocalPlanner
|
|
13
|
-
from isar.mission_planner.sequential_task_selector import SequentialTaskSelector
|
|
14
|
-
from isar.mission_planner.task_selector_interface import TaskSelectorInterface
|
|
15
13
|
from isar.models.events import Events, SharedState
|
|
16
14
|
from isar.robot.robot import Robot
|
|
17
15
|
from isar.services.utilities.robot_utilities import RobotUtilities
|
|
@@ -89,24 +87,21 @@ class ApplicationContainer(containers.DeclarativeContainer):
|
|
|
89
87
|
storage_handlers = providers.List(*storage_handlers_temp)
|
|
90
88
|
|
|
91
89
|
# State machine
|
|
92
|
-
task_selector = providers.Singleton(
|
|
93
|
-
SequentialTaskSelector
|
|
94
|
-
if settings.TASK_SELECTOR == "sequential"
|
|
95
|
-
else TaskSelectorInterface
|
|
96
|
-
)
|
|
97
|
-
|
|
98
90
|
state_machine = providers.Singleton(
|
|
99
91
|
StateMachine,
|
|
100
92
|
events=events,
|
|
101
93
|
shared_state=shared_state,
|
|
102
94
|
robot=robot_interface,
|
|
103
95
|
mqtt_publisher=mqtt_client,
|
|
104
|
-
task_selector=task_selector,
|
|
105
96
|
)
|
|
106
97
|
|
|
107
98
|
# Robot
|
|
108
99
|
robot = providers.Singleton(
|
|
109
|
-
Robot,
|
|
100
|
+
Robot,
|
|
101
|
+
events=events,
|
|
102
|
+
robot=robot_interface,
|
|
103
|
+
shared_state=shared_state,
|
|
104
|
+
mqtt_publisher=mqtt_client,
|
|
110
105
|
)
|
|
111
106
|
|
|
112
107
|
# Uploader
|
|
@@ -126,7 +121,6 @@ def get_injector() -> ApplicationContainer:
|
|
|
126
121
|
{
|
|
127
122
|
"KEYVAULT_NAME": settings.KEYVAULT_NAME,
|
|
128
123
|
"MQTT_ENABLED": settings.MQTT_ENABLED,
|
|
129
|
-
"TASK_SELECTOR": settings.TASK_SELECTOR,
|
|
130
124
|
}
|
|
131
125
|
)
|
|
132
126
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
from queue import Queue
|
|
2
3
|
from threading import Event as ThreadEvent
|
|
3
|
-
from typing import Optional
|
|
4
|
+
from typing import List, Optional, Tuple
|
|
4
5
|
|
|
5
6
|
from isar.models.events import (
|
|
6
7
|
Event,
|
|
@@ -10,32 +11,43 @@ from isar.models.events import (
|
|
|
10
11
|
StateMachineEvents,
|
|
11
12
|
)
|
|
12
13
|
from isar.robot.robot_battery import RobotBatteryThread
|
|
14
|
+
from isar.robot.robot_monitor_mission import RobotMonitorMissionThread
|
|
13
15
|
from isar.robot.robot_pause_mission import RobotPauseMissionThread
|
|
14
16
|
from isar.robot.robot_start_mission import RobotStartMissionThread
|
|
15
17
|
from isar.robot.robot_status import RobotStatusThread
|
|
16
18
|
from isar.robot.robot_stop_mission import RobotStopMissionThread
|
|
17
|
-
from isar.robot.
|
|
19
|
+
from isar.robot.robot_upload_inspection import RobotUploadInspectionThread
|
|
18
20
|
from robot_interface.models.exceptions.robot_exceptions import ErrorMessage, ErrorReason
|
|
19
21
|
from robot_interface.models.mission.mission import Mission
|
|
22
|
+
from robot_interface.models.mission.task import TASKS
|
|
20
23
|
from robot_interface.robot_interface import RobotInterface
|
|
24
|
+
from robot_interface.telemetry.mqtt_client import MqttClientInterface
|
|
21
25
|
|
|
22
26
|
|
|
23
27
|
class Robot(object):
|
|
24
28
|
def __init__(
|
|
25
|
-
self,
|
|
29
|
+
self,
|
|
30
|
+
events: Events,
|
|
31
|
+
robot: RobotInterface,
|
|
32
|
+
shared_state: SharedState,
|
|
33
|
+
mqtt_publisher: MqttClientInterface,
|
|
26
34
|
) -> None:
|
|
27
35
|
self.logger = logging.getLogger("robot")
|
|
28
36
|
self.state_machine_events: StateMachineEvents = events.state_machine_events
|
|
29
37
|
self.robot_service_events: RobotServiceEvents = events.robot_service_events
|
|
38
|
+
self.mqtt_publisher: MqttClientInterface = mqtt_publisher
|
|
39
|
+
self.upload_queue: Queue = events.upload_queue
|
|
30
40
|
self.shared_state: SharedState = shared_state
|
|
31
41
|
self.robot: RobotInterface = robot
|
|
32
42
|
self.start_mission_thread: Optional[RobotStartMissionThread] = None
|
|
33
43
|
self.robot_battery_thread: Optional[RobotBatteryThread] = None
|
|
34
44
|
self.robot_status_thread: Optional[RobotStatusThread] = None
|
|
35
|
-
self.
|
|
45
|
+
self.monitor_mission_thread: Optional[RobotMonitorMissionThread] = None
|
|
36
46
|
self.stop_mission_thread: Optional[RobotStopMissionThread] = None
|
|
37
47
|
self.pause_mission_thread: Optional[RobotPauseMissionThread] = None
|
|
48
|
+
self.upload_inspection_threads: List[RobotUploadInspectionThread] = []
|
|
38
49
|
self.signal_thread_quitting: ThreadEvent = ThreadEvent()
|
|
50
|
+
self.signal_mission_stopped: ThreadEvent = ThreadEvent()
|
|
39
51
|
|
|
40
52
|
def stop(self) -> None:
|
|
41
53
|
self.signal_thread_quitting.set()
|
|
@@ -47,10 +59,10 @@ class Robot(object):
|
|
|
47
59
|
):
|
|
48
60
|
self.robot_battery_thread.join()
|
|
49
61
|
if (
|
|
50
|
-
self.
|
|
51
|
-
and self.
|
|
62
|
+
self.monitor_mission_thread is not None
|
|
63
|
+
and self.monitor_mission_thread.is_alive()
|
|
52
64
|
):
|
|
53
|
-
self.
|
|
65
|
+
self.monitor_mission_thread.join()
|
|
54
66
|
if (
|
|
55
67
|
self.start_mission_thread is not None
|
|
56
68
|
and self.start_mission_thread.is_alive()
|
|
@@ -60,8 +72,64 @@ class Robot(object):
|
|
|
60
72
|
self.stop_mission_thread.join()
|
|
61
73
|
self.robot_status_thread = None
|
|
62
74
|
self.robot_battery_thread = None
|
|
63
|
-
self.robot_task_status_thread = None
|
|
64
75
|
self.start_mission_thread = None
|
|
76
|
+
self.monitor_mission_thread = None
|
|
77
|
+
|
|
78
|
+
def _start_mission_done_handler(self) -> None:
|
|
79
|
+
if (
|
|
80
|
+
self.start_mission_thread is not None
|
|
81
|
+
and not self.start_mission_thread.is_alive()
|
|
82
|
+
):
|
|
83
|
+
self.start_mission_thread.join()
|
|
84
|
+
mission = self.start_mission_thread.mission
|
|
85
|
+
self.start_mission_thread = None
|
|
86
|
+
|
|
87
|
+
if (
|
|
88
|
+
self.monitor_mission_thread is not None
|
|
89
|
+
and self.monitor_mission_thread.is_alive()
|
|
90
|
+
):
|
|
91
|
+
self.logger.warning(
|
|
92
|
+
"Attempted to start mission while monitoring an old mission."
|
|
93
|
+
)
|
|
94
|
+
self.monitor_mission_thread.join()
|
|
95
|
+
|
|
96
|
+
self.signal_mission_stopped.clear()
|
|
97
|
+
self.monitor_mission_thread = RobotMonitorMissionThread(
|
|
98
|
+
self.robot_service_events,
|
|
99
|
+
self.shared_state,
|
|
100
|
+
self.robot,
|
|
101
|
+
self.mqtt_publisher,
|
|
102
|
+
self.signal_thread_quitting,
|
|
103
|
+
self.signal_mission_stopped,
|
|
104
|
+
mission,
|
|
105
|
+
)
|
|
106
|
+
self.monitor_mission_thread.start()
|
|
107
|
+
|
|
108
|
+
def _stop_mission_done_handler(self) -> None:
|
|
109
|
+
if (
|
|
110
|
+
self.stop_mission_thread is not None
|
|
111
|
+
and not self.stop_mission_thread.is_alive()
|
|
112
|
+
and (
|
|
113
|
+
not self.monitor_mission_thread
|
|
114
|
+
or not self.monitor_mission_thread.is_alive()
|
|
115
|
+
)
|
|
116
|
+
):
|
|
117
|
+
self.stop_mission_thread.join()
|
|
118
|
+
error_message = self.stop_mission_thread.error_message
|
|
119
|
+
self.stop_mission_thread = None
|
|
120
|
+
|
|
121
|
+
if self.monitor_mission_thread is not None:
|
|
122
|
+
self.monitor_mission_thread.join()
|
|
123
|
+
self.monitor_mission_thread = None
|
|
124
|
+
|
|
125
|
+
if error_message:
|
|
126
|
+
self.robot_service_events.mission_failed_to_stop.trigger_event(
|
|
127
|
+
error_message
|
|
128
|
+
)
|
|
129
|
+
else:
|
|
130
|
+
self.robot_service_events.mission_successfully_stopped.trigger_event(
|
|
131
|
+
True
|
|
132
|
+
)
|
|
65
133
|
|
|
66
134
|
def _start_mission_event_handler(self, event: Event[Mission]) -> None:
|
|
67
135
|
start_mission = event.consume_event()
|
|
@@ -74,6 +142,7 @@ class Robot(object):
|
|
|
74
142
|
"Attempted to start mission while another mission was starting."
|
|
75
143
|
)
|
|
76
144
|
self.start_mission_thread.join()
|
|
145
|
+
|
|
77
146
|
self.start_mission_thread = RobotStartMissionThread(
|
|
78
147
|
self.robot_service_events,
|
|
79
148
|
self.robot,
|
|
@@ -82,17 +151,6 @@ class Robot(object):
|
|
|
82
151
|
)
|
|
83
152
|
self.start_mission_thread.start()
|
|
84
153
|
|
|
85
|
-
def _task_status_request_handler(self, event: Event[str]) -> None:
|
|
86
|
-
task_id: str = event.consume_event()
|
|
87
|
-
if task_id:
|
|
88
|
-
self.robot_task_status_thread = RobotTaskStatusThread(
|
|
89
|
-
self.robot_service_events,
|
|
90
|
-
self.robot,
|
|
91
|
-
self.signal_thread_quitting,
|
|
92
|
-
task_id,
|
|
93
|
-
)
|
|
94
|
-
self.robot_task_status_thread.start()
|
|
95
|
-
|
|
96
154
|
def _stop_mission_request_handler(self, event: Event[bool]) -> None:
|
|
97
155
|
if event.consume_event():
|
|
98
156
|
if (
|
|
@@ -117,9 +175,10 @@ class Robot(object):
|
|
|
117
175
|
)
|
|
118
176
|
return
|
|
119
177
|
self.stop_mission_thread = RobotStopMissionThread(
|
|
120
|
-
self.
|
|
178
|
+
self.robot, self.signal_thread_quitting
|
|
121
179
|
)
|
|
122
180
|
self.stop_mission_thread.start()
|
|
181
|
+
self.signal_mission_stopped.set()
|
|
123
182
|
|
|
124
183
|
def _pause_mission_request_handler(self, event: Event[bool]) -> None:
|
|
125
184
|
if event.consume_event():
|
|
@@ -149,6 +208,28 @@ class Robot(object):
|
|
|
149
208
|
)
|
|
150
209
|
self.pause_mission_thread.start()
|
|
151
210
|
|
|
211
|
+
def _upload_inspection_event_handler(
|
|
212
|
+
self, event: Event[Tuple[TASKS, Mission]]
|
|
213
|
+
) -> None:
|
|
214
|
+
upload_request = event.consume_event()
|
|
215
|
+
if upload_request:
|
|
216
|
+
|
|
217
|
+
upload_inspection_thread = RobotUploadInspectionThread(
|
|
218
|
+
self.upload_queue, self.robot, upload_request[0], upload_request[1]
|
|
219
|
+
)
|
|
220
|
+
self.upload_inspection_threads.append(upload_inspection_thread)
|
|
221
|
+
upload_inspection_thread.start()
|
|
222
|
+
|
|
223
|
+
def _join_threads(thread: RobotUploadInspectionThread) -> bool:
|
|
224
|
+
if thread.is_done():
|
|
225
|
+
thread.join()
|
|
226
|
+
return True
|
|
227
|
+
return False
|
|
228
|
+
|
|
229
|
+
self.upload_inspection_threads[:] = [
|
|
230
|
+
thread for thread in self.upload_inspection_threads if _join_threads(thread)
|
|
231
|
+
]
|
|
232
|
+
|
|
152
233
|
def run(self) -> None:
|
|
153
234
|
self.robot_status_thread = RobotStatusThread(
|
|
154
235
|
robot=self.robot,
|
|
@@ -167,12 +248,16 @@ class Robot(object):
|
|
|
167
248
|
while not self.signal_thread_quitting.wait(0):
|
|
168
249
|
self._start_mission_event_handler(self.state_machine_events.start_mission)
|
|
169
250
|
|
|
170
|
-
self._task_status_request_handler(
|
|
171
|
-
self.state_machine_events.task_status_request
|
|
172
|
-
)
|
|
173
|
-
|
|
174
251
|
self._pause_mission_request_handler(self.state_machine_events.pause_mission)
|
|
175
252
|
|
|
176
253
|
self._stop_mission_request_handler(self.state_machine_events.stop_mission)
|
|
177
254
|
|
|
255
|
+
self._upload_inspection_event_handler(
|
|
256
|
+
self.robot_service_events.request_inspection_upload
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
self._start_mission_done_handler()
|
|
260
|
+
|
|
261
|
+
self._stop_mission_done_handler()
|
|
262
|
+
|
|
178
263
|
self.logger.info("Exiting robot service main thread")
|