isar 1.33.1__tar.gz → 1.33.3__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.1 → isar-1.33.3}/PKG-INFO +2 -2
- {isar-1.33.1 → isar-1.33.3}/README.md +1 -1
- {isar-1.33.1 → isar-1.33.3}/src/isar/apis/schedule/scheduling_controller.py +3 -1
- {isar-1.33.1 → isar-1.33.3}/src/isar/config/settings.py +5 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/services/service_connections/mqtt/mqtt_client.py +46 -10
- {isar-1.33.1 → isar-1.33.3}/src/isar/services/service_connections/mqtt/robot_heartbeat_publisher.py +3 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/services/utilities/scheduling_utilities.py +5 -9
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/state_machine.py +16 -9
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/states/home.py +14 -5
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/states/paused.py +24 -1
- isar-1.33.3/src/isar/state_machine/states/return_home_paused.py +66 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/states/returning_home.py +10 -5
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/states/stopping.py +5 -22
- isar-1.33.3/src/isar/state_machine/states/stopping_return_home.py +73 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/states_enum.py +2 -1
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/transitions/functions/pause.py +38 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/transitions/functions/robot_status.py +2 -7
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/transitions/mission.py +46 -19
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/transitions/return_home.py +1 -7
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/transitions/robot_status.py +2 -17
- isar-1.33.3/src/isar/storage/blob_storage.py +101 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/storage/local_storage.py +21 -11
- {isar-1.33.1 → isar-1.33.3}/src/isar/storage/storage_interface.py +27 -6
- {isar-1.33.1 → isar-1.33.3}/src/isar/storage/uploader.py +30 -13
- {isar-1.33.1 → isar-1.33.3}/src/isar.egg-info/PKG-INFO +2 -2
- {isar-1.33.1 → isar-1.33.3}/src/isar.egg-info/SOURCES.txt +2 -1
- {isar-1.33.1 → isar-1.33.3}/src/robot_interface/models/mission/status.py +2 -1
- {isar-1.33.1 → isar-1.33.3}/src/robot_interface/telemetry/mqtt_client.py +62 -6
- {isar-1.33.1 → isar-1.33.3}/src/robot_interface/telemetry/payloads.py +4 -2
- {isar-1.33.1 → isar-1.33.3}/src/robot_interface/utilities/json_service.py +6 -0
- {isar-1.33.1 → isar-1.33.3}/tests/conftest.py +12 -4
- {isar-1.33.1 → isar-1.33.3}/tests/integration/turtlebot/test_successful_mission.py +1 -1
- {isar-1.33.1 → isar-1.33.3}/tests/isar/apis/scheduler/test_scheduler_router.py +13 -51
- {isar-1.33.1 → isar-1.33.3}/tests/isar/services/utilities/test_scheduling_utilities.py +0 -3
- {isar-1.33.1 → isar-1.33.3}/tests/isar/state_machine/test_state_machine.py +119 -205
- {isar-1.33.1 → isar-1.33.3}/tests/test_double/robot_interface.py +2 -19
- {isar-1.33.1 → isar-1.33.3}/tests/test_double/status.py +1 -1
- isar-1.33.1/src/isar/state_machine/states/robot_standing_still.py +0 -52
- isar-1.33.1/src/isar/storage/blob_storage.py +0 -79
- {isar-1.33.1 → isar-1.33.3}/.dockerignore +0 -0
- {isar-1.33.1 → isar-1.33.3}/.env.test +0 -0
- {isar-1.33.1 → isar-1.33.3}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {isar-1.33.1 → isar-1.33.3}/.github/ISSUE_TEMPLATE/feature.md +0 -0
- {isar-1.33.1 → isar-1.33.3}/.github/ISSUE_TEMPLATE/improvement.md +0 -0
- {isar-1.33.1 → isar-1.33.3}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {isar-1.33.1 → isar-1.33.3}/.github/release.yml +0 -0
- {isar-1.33.1 → isar-1.33.3}/.github/workflows/compile_requirements.yml +0 -0
- {isar-1.33.1 → isar-1.33.3}/.github/workflows/project_automations.yml +0 -0
- {isar-1.33.1 → isar-1.33.3}/.github/workflows/pythonpackage.yml +0 -0
- {isar-1.33.1 → isar-1.33.3}/.github/workflows/pythonpublish.yml +0 -0
- {isar-1.33.1 → isar-1.33.3}/.github/workflows/stale.yml +0 -0
- {isar-1.33.1 → isar-1.33.3}/.gitignore +0 -0
- {isar-1.33.1 → isar-1.33.3}/.pre-commit-config.yaml +0 -0
- {isar-1.33.1 → isar-1.33.3}/LICENSE +0 -0
- {isar-1.33.1 → isar-1.33.3}/SECURITY.md +0 -0
- {isar-1.33.1 → isar-1.33.3}/docs/Makefile +0 -0
- {isar-1.33.1 → isar-1.33.3}/docs/full_state_machine_diagram.png +0 -0
- {isar-1.33.1 → isar-1.33.3}/docs/make.bat +0 -0
- {isar-1.33.1 → isar-1.33.3}/docs/mission_state_machine_diagram.png +0 -0
- {isar-1.33.1 → isar-1.33.3}/docs/robot_status_state_machine_diagram.png +0 -0
- {isar-1.33.1 → isar-1.33.3}/docs/rst_processing.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/docs/source/conf.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/docs/source/index.rst +0 -0
- {isar-1.33.1 → isar-1.33.3}/docs/source/readme_link.md +0 -0
- {isar-1.33.1 → isar-1.33.3}/docs/update_state_diagram.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/main.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/pyproject.toml +0 -0
- {isar-1.33.1 → isar-1.33.3}/radixconfig.yml +0 -0
- {isar-1.33.1 → isar-1.33.3}/requirements.txt +0 -0
- {isar-1.33.1 → isar-1.33.3}/setup.cfg +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/apis/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/apis/api.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/apis/models/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/apis/models/models.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/apis/models/start_mission_definition.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/apis/robot_control/robot_controller.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/apis/schedule/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/apis/security/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/apis/security/authentication.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/config/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/config/certs/ca-cert.pem +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/config/configuration_error.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/config/keyvault/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/config/keyvault/keyvault_error.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/config/keyvault/keyvault_service.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/config/log.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/config/logging.conf +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/config/maps/JSP1_intermediate_deck.json +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/config/maps/JSP1_weather_deck.json +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/config/maps/default_map.json +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/config/maps/klab_b.json +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/config/maps/klab_compressor.json +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/config/maps/klab_turtlebot.json +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/config/maps/turtleworld.json +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/config/open_telemetry.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/config/predefined_mission_definition/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/config/predefined_mission_definition/default_exr.json +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/config/predefined_mission_definition/default_mission.json +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/config/predefined_mission_definition/default_turtlebot.json +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/config/predefined_missions/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/config/predefined_missions/default.json +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/config/predefined_missions/default_turtlebot.json +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/eventhandlers/eventhandler.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/mission_planner/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/mission_planner/local_planner.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/mission_planner/mission_planner_interface.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/mission_planner/sequential_task_selector.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/mission_planner/task_selector_interface.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/models/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/models/events.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/modules.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/robot/robot.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/robot/robot_start_mission.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/robot/robot_status.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/robot/robot_stop_mission.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/robot/robot_task_status.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/script.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/services/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/services/auth/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/services/auth/azure_credentials.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/services/service_connections/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/services/service_connections/mqtt/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/services/service_connections/mqtt/robot_info_publisher.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/services/service_connections/request_handler.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/services/utilities/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/services/utilities/robot_utilities.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/services/utilities/threaded_request.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/states/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/states/await_next_mission.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/states/blocked_protective_stop.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/states/intervention_needed.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/states/monitor.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/states/offline.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/states/recharging.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/states/unknown_status.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/transitions/functions/fail_mission.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/transitions/functions/finish_mission.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/transitions/functions/resume.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/transitions/functions/return_home.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/transitions/functions/start_mission.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/transitions/functions/stop.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/transitions/functions/utils.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/state_machine/utils/common_event_handlers.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/storage/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar/storage/utilities.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar.egg-info/dependency_links.txt +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar.egg-info/entry_points.txt +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar.egg-info/requires.txt +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/isar.egg-info/top_level.txt +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/robot_interface/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/robot_interface/models/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/robot_interface/models/exceptions/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/robot_interface/models/exceptions/robot_exceptions.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/robot_interface/models/initialize/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/robot_interface/models/inspection/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/robot_interface/models/inspection/inspection.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/robot_interface/models/mission/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/robot_interface/models/mission/mission.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/robot_interface/models/mission/task.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/robot_interface/models/robots/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/robot_interface/models/robots/battery_state.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/robot_interface/models/robots/media.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/robot_interface/models/robots/robot_model.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/robot_interface/robot_interface.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/robot_interface/telemetry/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/robot_interface/test_robot_interface.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/robot_interface/utilities/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/src/robot_interface/utilities/uuid_string_factory.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/integration/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/integration/turtlebot/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/integration/turtlebot/config/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/integration/turtlebot/config/maps/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/integration/turtlebot/config/maps/turtleworld.json +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/integration/turtlebot/config/missions/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/integration/turtlebot/config/missions/default.json +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/isar/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/isar/apis/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/isar/apis/models/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/isar/apis/models/example_mission_definition.json +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/isar/apis/models/test_start_mission_definition.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/isar/apis/scheduler/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/isar/apis/security/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/isar/apis/security/test_authentication.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/isar/mission/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/isar/mission/test_mission.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/isar/models/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/isar/models/communication/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/isar/models/communication/test_events.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/isar/services/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/isar/services/readers/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/isar/services/readers/test_mission_reader.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/isar/services/service_connections/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/isar/services/service_connections/echo/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/isar/services/service_connections/test_base_request_handler.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/isar/services/utilities/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/isar/services/utilities/test_queue_utilities.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/isar/state_machine/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/isar/state_machine/states/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/isar/state_machine/states/test_monitor.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/isar/storage/test_blob_storage.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/isar/storage/test_uploader.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/test_data/test_map_config/test_map_config.json +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/test_data/test_mission_not_working.json +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/test_data/test_mission_working.json +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/test_data/test_mission_working_no_tasks.json +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/test_data/test_thermal_image_mission.json +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/test_double/__init__.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/test_double/blob_storage.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/test_double/mission_definition.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/test_double/pose.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/test_double/request.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/test_double/task.py +0 -0
- {isar-1.33.1 → isar-1.33.3}/tests/test_double/token.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: isar
|
|
3
|
-
Version: 1.33.
|
|
3
|
+
Version: 1.33.3
|
|
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
|
|
@@ -369,7 +369,7 @@ States.Paused,
|
|
|
369
369
|
indicates that the state machine is already running. For running a mission the state machine need to be in the states
|
|
370
370
|
|
|
371
371
|
```
|
|
372
|
-
States.Home, States.
|
|
372
|
+
States.Home, States.AwaitNextMission or States.ReturningHome
|
|
373
373
|
```
|
|
374
374
|
|
|
375
375
|
### FastAPI
|
|
@@ -225,7 +225,7 @@ States.Paused,
|
|
|
225
225
|
indicates that the state machine is already running. For running a mission the state machine need to be in the states
|
|
226
226
|
|
|
227
227
|
```
|
|
228
|
-
States.Home, States.
|
|
228
|
+
States.Home, States.AwaitNextMission or States.ReturningHome
|
|
229
229
|
```
|
|
230
230
|
|
|
231
231
|
### FastAPI
|
|
@@ -115,6 +115,7 @@ class SchedulingController:
|
|
|
115
115
|
|
|
116
116
|
if state not in [
|
|
117
117
|
States.Monitor,
|
|
118
|
+
States.ReturningHome,
|
|
118
119
|
]:
|
|
119
120
|
error_message = (
|
|
120
121
|
f"Conflict - Pause command received in invalid state - State: {state}"
|
|
@@ -135,7 +136,7 @@ class SchedulingController:
|
|
|
135
136
|
|
|
136
137
|
state: States = self.scheduling_utilities.get_state()
|
|
137
138
|
|
|
138
|
-
if state
|
|
139
|
+
if state not in [States.Paused, States.ReturnHomePaused]:
|
|
139
140
|
error_message = (
|
|
140
141
|
f"Conflict - Resume command received in invalid state - State: {state}"
|
|
141
142
|
)
|
|
@@ -167,6 +168,7 @@ class SchedulingController:
|
|
|
167
168
|
or state == States.BlockedProtectiveStop
|
|
168
169
|
or state == States.Offline
|
|
169
170
|
or state == States.Home
|
|
171
|
+
or state == States.ReturningHome
|
|
170
172
|
):
|
|
171
173
|
error_message = (
|
|
172
174
|
f"Conflict - Stop command received in invalid state - State: {state}"
|
|
@@ -244,6 +244,11 @@ class Settings(BaseSettings):
|
|
|
244
244
|
default="intervention_needed", validate_default=True
|
|
245
245
|
)
|
|
246
246
|
|
|
247
|
+
# List of MQTT Topics Expiry
|
|
248
|
+
MQTT_ROBOT_HEARTBEAT_EXPIRY: int = Field(default=5)
|
|
249
|
+
MQTT_TELEMETRY_EXPIRY: int = Field(default=10)
|
|
250
|
+
MQTT_MISSION_AND_TASK_EXPIRY: int = Field(default=86400)
|
|
251
|
+
|
|
247
252
|
# Logging
|
|
248
253
|
|
|
249
254
|
# Log handlers
|
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import os
|
|
3
|
+
import time
|
|
3
4
|
from queue import Empty, Queue
|
|
4
5
|
|
|
5
6
|
import backoff
|
|
6
7
|
from paho.mqtt import client as mqtt
|
|
7
8
|
from paho.mqtt.client import Client
|
|
9
|
+
from paho.mqtt.packettypes import PacketTypes
|
|
10
|
+
from paho.mqtt.properties import Properties
|
|
8
11
|
|
|
9
12
|
from isar.config.settings import settings
|
|
10
13
|
from robot_interface.telemetry.mqtt_client import MqttClientInterface
|
|
11
14
|
|
|
12
15
|
|
|
16
|
+
def props_expiry(seconds: int) -> Properties:
|
|
17
|
+
p = Properties(PacketTypes.PUBLISH)
|
|
18
|
+
p.MessageExpiryInterval = seconds
|
|
19
|
+
return p
|
|
20
|
+
|
|
21
|
+
|
|
13
22
|
def _on_success(data: dict) -> None:
|
|
14
23
|
logging.getLogger("mqtt_client").info("Connected to MQTT Broker")
|
|
15
24
|
logging.getLogger("mqtt_client").debug(
|
|
@@ -53,7 +62,9 @@ class MqttClient(MqttClientInterface):
|
|
|
53
62
|
|
|
54
63
|
self.port: int = settings.MQTT_PORT
|
|
55
64
|
|
|
56
|
-
self.client: Client = Client(
|
|
65
|
+
self.client: Client = Client(
|
|
66
|
+
protocol=mqtt.MQTTv5, callback_api_version=mqtt.CallbackAPIVersion.VERSION2
|
|
67
|
+
)
|
|
57
68
|
|
|
58
69
|
self.client.enable_logger(logger=self.logger)
|
|
59
70
|
|
|
@@ -74,20 +85,36 @@ class MqttClient(MqttClientInterface):
|
|
|
74
85
|
|
|
75
86
|
while True:
|
|
76
87
|
if not self.client.is_connected():
|
|
88
|
+
time.sleep(0) # avoid CPU spin
|
|
77
89
|
continue
|
|
78
90
|
try:
|
|
79
|
-
|
|
91
|
+
item = self.mqtt_queue.get(timeout=1)
|
|
92
|
+
if len(item) == 4:
|
|
93
|
+
topic, payload, qos, retain = item
|
|
94
|
+
properties = None
|
|
95
|
+
else:
|
|
96
|
+
topic, payload, qos, retain, properties = item
|
|
80
97
|
except Empty:
|
|
81
98
|
continue
|
|
82
99
|
|
|
83
|
-
self.publish(
|
|
100
|
+
self.publish(
|
|
101
|
+
topic=topic,
|
|
102
|
+
payload=payload,
|
|
103
|
+
qos=qos,
|
|
104
|
+
retain=retain,
|
|
105
|
+
properties=properties,
|
|
106
|
+
)
|
|
84
107
|
|
|
85
|
-
def on_connect(self, client, userdata, flags,
|
|
86
|
-
self.logger.info(
|
|
108
|
+
def on_connect(self, client, userdata, flags, reason_code, properties):
|
|
109
|
+
self.logger.info(
|
|
110
|
+
"Connection returned result: " + mqtt.connack_string(reason_code)
|
|
111
|
+
)
|
|
87
112
|
|
|
88
|
-
def on_disconnect(self, client, userdata,
|
|
89
|
-
if
|
|
90
|
-
self.logger.warning(
|
|
113
|
+
def on_disconnect(self, client, userdata, reason_code, properties):
|
|
114
|
+
if reason_code != 0:
|
|
115
|
+
self.logger.warning(
|
|
116
|
+
f"Unexpected disconnection from MQTT Broker, {reason_code}"
|
|
117
|
+
)
|
|
91
118
|
|
|
92
119
|
@backoff.on_exception(
|
|
93
120
|
backoff.expo,
|
|
@@ -102,6 +129,15 @@ class MqttClient(MqttClientInterface):
|
|
|
102
129
|
self.logger.info("Host: %s, Port: %s", host, port)
|
|
103
130
|
self.client.connect(host=host, port=port)
|
|
104
131
|
|
|
105
|
-
def publish(
|
|
132
|
+
def publish(
|
|
133
|
+
self,
|
|
134
|
+
topic: str,
|
|
135
|
+
payload: str,
|
|
136
|
+
qos: int = 0,
|
|
137
|
+
retain: bool = False,
|
|
138
|
+
properties=None,
|
|
139
|
+
):
|
|
106
140
|
self.logger.debug("Publishing message to topic: %s", topic)
|
|
107
|
-
self.client.publish(
|
|
141
|
+
self.client.publish(
|
|
142
|
+
topic=topic, payload=payload, qos=qos, retain=retain, properties=properties
|
|
143
|
+
)
|
{isar-1.33.1 → isar-1.33.3}/src/isar/services/service_connections/mqtt/robot_heartbeat_publisher.py
RENAMED
|
@@ -4,6 +4,7 @@ from datetime import datetime, timezone
|
|
|
4
4
|
from queue import Queue
|
|
5
5
|
|
|
6
6
|
from isar.config.settings import settings
|
|
7
|
+
from isar.services.service_connections.mqtt.mqtt_client import props_expiry
|
|
7
8
|
from robot_interface.telemetry.mqtt_client import MqttPublisher
|
|
8
9
|
from robot_interface.telemetry.payloads import RobotHeartbeatPayload
|
|
9
10
|
from robot_interface.utilities.json_service import EnhancedJSONEncoder
|
|
@@ -24,6 +25,8 @@ class RobotHeartbeatPublisher:
|
|
|
24
25
|
self.mqtt_publisher.publish(
|
|
25
26
|
topic=settings.TOPIC_ISAR_ROBOT_HEARTBEAT,
|
|
26
27
|
payload=json.dumps(payload, cls=EnhancedJSONEncoder),
|
|
28
|
+
retain=True,
|
|
29
|
+
properties=props_expiry(settings.MQTT_ROBOT_HEARTBEAT_EXPIRY),
|
|
27
30
|
)
|
|
28
31
|
|
|
29
32
|
time.sleep(settings.ROBOT_HEARTBEAT_PUBLISH_INTERVAL)
|
|
@@ -129,13 +129,13 @@ class SchedulingUtilities:
|
|
|
129
129
|
------
|
|
130
130
|
HTTPException 409 Conflict
|
|
131
131
|
If state machine is not home, robot standing still, awaiting next mission
|
|
132
|
-
or returning home and therefore cannot start a new mission
|
|
132
|
+
return home paused or returning home and therefore cannot start a new mission
|
|
133
133
|
"""
|
|
134
134
|
if (
|
|
135
|
-
state == States.
|
|
136
|
-
or state == States.Home
|
|
135
|
+
state == States.Home
|
|
137
136
|
or state == States.AwaitNextMission
|
|
138
137
|
or state == States.ReturningHome
|
|
138
|
+
or state == States.ReturnHomePaused
|
|
139
139
|
):
|
|
140
140
|
return True
|
|
141
141
|
|
|
@@ -154,11 +154,7 @@ class SchedulingUtilities:
|
|
|
154
154
|
If state machine is not home, robot standing still or awaiting next mission
|
|
155
155
|
and therefore cannot start a new return home mission
|
|
156
156
|
"""
|
|
157
|
-
if
|
|
158
|
-
state == States.RobotStandingStill
|
|
159
|
-
or state == States.Home
|
|
160
|
-
or state == States.AwaitNextMission
|
|
161
|
-
):
|
|
157
|
+
if state == States.Home or state == States.AwaitNextMission:
|
|
162
158
|
return True
|
|
163
159
|
|
|
164
160
|
error_message = f"Conflict - Robot is not home, robot standing still or awaiting next mission - State: {state}"
|
|
@@ -336,7 +332,7 @@ class SchedulingUtilities:
|
|
|
336
332
|
)
|
|
337
333
|
|
|
338
334
|
def _send_command(self, input: T1, api_event: APIEvent[T1, T2]) -> T2:
|
|
339
|
-
if api_event.request.has_event()
|
|
335
|
+
if api_event.request.has_event():
|
|
340
336
|
raise EventConflictError("API event has already been sent")
|
|
341
337
|
|
|
342
338
|
try:
|
|
@@ -15,6 +15,7 @@ from isar.mission_planner.task_selector_interface import (
|
|
|
15
15
|
TaskSelectorStop,
|
|
16
16
|
)
|
|
17
17
|
from isar.models.events import Events, SharedState
|
|
18
|
+
from isar.services.service_connections.mqtt.mqtt_client import props_expiry
|
|
18
19
|
from isar.state_machine.states.await_next_mission import AwaitNextMission
|
|
19
20
|
from isar.state_machine.states.blocked_protective_stop import BlockedProtectiveStop
|
|
20
21
|
from isar.state_machine.states.home import Home
|
|
@@ -23,9 +24,10 @@ from isar.state_machine.states.monitor import Monitor
|
|
|
23
24
|
from isar.state_machine.states.offline import Offline
|
|
24
25
|
from isar.state_machine.states.paused import Paused
|
|
25
26
|
from isar.state_machine.states.recharging import Recharging
|
|
27
|
+
from isar.state_machine.states.return_home_paused import ReturnHomePaused
|
|
26
28
|
from isar.state_machine.states.returning_home import ReturningHome
|
|
27
|
-
from isar.state_machine.states.robot_standing_still import RobotStandingStill
|
|
28
29
|
from isar.state_machine.states.stopping import Stopping
|
|
30
|
+
from isar.state_machine.states.stopping_return_home import StoppingReturnHome
|
|
29
31
|
from isar.state_machine.states.unknown_status import UnknownStatus
|
|
30
32
|
from isar.state_machine.states_enum import States
|
|
31
33
|
from isar.state_machine.transitions.mission import get_mission_transitions
|
|
@@ -100,11 +102,12 @@ class StateMachine(object):
|
|
|
100
102
|
self.returning_home_state: State = ReturningHome(self)
|
|
101
103
|
self.stopping_state: State = Stopping(self)
|
|
102
104
|
self.paused_state: State = Paused(self)
|
|
105
|
+
self.return_home_paused_state: State = ReturnHomePaused(self)
|
|
106
|
+
self.stopping_return_home_state: State = StoppingReturnHome(self)
|
|
103
107
|
|
|
104
108
|
# States Waiting for mission
|
|
105
109
|
self.await_next_mission_state: State = AwaitNextMission(self)
|
|
106
110
|
self.home_state: State = Home(self)
|
|
107
|
-
self.robot_standing_still_state: State = RobotStandingStill(self)
|
|
108
111
|
self.intervention_needed_state: State = InterventionNeeded(self)
|
|
109
112
|
|
|
110
113
|
# Status states
|
|
@@ -119,10 +122,11 @@ class StateMachine(object):
|
|
|
119
122
|
self.monitor_state,
|
|
120
123
|
self.returning_home_state,
|
|
121
124
|
self.stopping_state,
|
|
125
|
+
self.stopping_return_home_state,
|
|
122
126
|
self.paused_state,
|
|
127
|
+
self.return_home_paused_state,
|
|
123
128
|
self.await_next_mission_state,
|
|
124
129
|
self.home_state,
|
|
125
|
-
self.robot_standing_still_state,
|
|
126
130
|
self.offline_state,
|
|
127
131
|
self.blocked_protective_stopping_state,
|
|
128
132
|
self.unknown_status_state,
|
|
@@ -285,10 +289,11 @@ class StateMachine(object):
|
|
|
285
289
|
)
|
|
286
290
|
|
|
287
291
|
self.mqtt_publisher.publish(
|
|
288
|
-
topic=settings.TOPIC_ISAR_MISSION,
|
|
292
|
+
topic=settings.TOPIC_ISAR_MISSION + f"/{self.current_mission.id}",
|
|
289
293
|
payload=json.dumps(payload, cls=EnhancedJSONEncoder),
|
|
290
294
|
qos=1,
|
|
291
295
|
retain=True,
|
|
296
|
+
properties=props_expiry(settings.MQTT_MISSION_AND_TASK_EXPIRY),
|
|
292
297
|
)
|
|
293
298
|
|
|
294
299
|
def publish_task_status(self, task: TASKS) -> None:
|
|
@@ -316,10 +321,11 @@ class StateMachine(object):
|
|
|
316
321
|
)
|
|
317
322
|
|
|
318
323
|
self.mqtt_publisher.publish(
|
|
319
|
-
topic=settings.TOPIC_ISAR_TASK,
|
|
324
|
+
topic=settings.TOPIC_ISAR_TASK + f"/{task.id}",
|
|
320
325
|
payload=json.dumps(payload, cls=EnhancedJSONEncoder),
|
|
321
326
|
qos=1,
|
|
322
327
|
retain=True,
|
|
328
|
+
properties=props_expiry(settings.MQTT_MISSION_AND_TASK_EXPIRY),
|
|
323
329
|
)
|
|
324
330
|
|
|
325
331
|
def publish_intervention_needed(self, error_message: str) -> None:
|
|
@@ -360,11 +366,12 @@ class StateMachine(object):
|
|
|
360
366
|
)
|
|
361
367
|
|
|
362
368
|
def _current_status(self) -> RobotStatus:
|
|
363
|
-
if
|
|
364
|
-
self.current_state == States.RobotStandingStill
|
|
365
|
-
or self.current_state == States.AwaitNextMission
|
|
366
|
-
):
|
|
369
|
+
if self.current_state == States.AwaitNextMission:
|
|
367
370
|
return RobotStatus.Available
|
|
371
|
+
elif self.current_state == States.ReturnHomePaused:
|
|
372
|
+
return RobotStatus.ReturnHomePaused
|
|
373
|
+
elif self.current_state == States.Paused:
|
|
374
|
+
return RobotStatus.Paused
|
|
368
375
|
elif self.current_state == States.Home:
|
|
369
376
|
return RobotStatus.Home
|
|
370
377
|
elif self.current_state == States.ReturningHome:
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
from typing import TYPE_CHECKING, List
|
|
1
|
+
from typing import TYPE_CHECKING, Callable, List, Optional
|
|
2
2
|
|
|
3
3
|
from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
|
|
4
|
+
from isar.models.events import Event
|
|
4
5
|
from isar.state_machine.utils.common_event_handlers import (
|
|
5
6
|
return_home_event_handler,
|
|
6
|
-
robot_status_event_handler,
|
|
7
7
|
start_mission_event_handler,
|
|
8
8
|
stop_mission_event_handler,
|
|
9
9
|
)
|
|
@@ -19,6 +19,17 @@ class Home(EventHandlerBase):
|
|
|
19
19
|
events = state_machine.events
|
|
20
20
|
shared_state = state_machine.shared_state
|
|
21
21
|
|
|
22
|
+
def _robot_status_event_handler(
|
|
23
|
+
event: Event[RobotStatus],
|
|
24
|
+
) -> Optional[Callable]:
|
|
25
|
+
robot_status: RobotStatus = event.check()
|
|
26
|
+
if not (
|
|
27
|
+
robot_status == RobotStatus.Available
|
|
28
|
+
or robot_status == RobotStatus.Home
|
|
29
|
+
):
|
|
30
|
+
return state_machine.robot_status_changed # type: ignore
|
|
31
|
+
return None
|
|
32
|
+
|
|
22
33
|
event_handlers: List[EventHandlerMapping] = [
|
|
23
34
|
EventHandlerMapping(
|
|
24
35
|
name="start_mission_event",
|
|
@@ -40,9 +51,7 @@ class Home(EventHandlerBase):
|
|
|
40
51
|
EventHandlerMapping(
|
|
41
52
|
name="robot_status_event",
|
|
42
53
|
event=shared_state.robot_status,
|
|
43
|
-
handler=
|
|
44
|
-
state_machine, RobotStatus.Home, event
|
|
45
|
-
),
|
|
54
|
+
handler=_robot_status_event_handler,
|
|
46
55
|
),
|
|
47
56
|
]
|
|
48
57
|
super().__init__(
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
from typing import TYPE_CHECKING, List
|
|
1
|
+
from typing import TYPE_CHECKING, Callable, List, Optional
|
|
2
2
|
|
|
3
|
+
from isar.config.settings import settings
|
|
3
4
|
from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
|
|
5
|
+
from isar.models.events import Event
|
|
4
6
|
|
|
5
7
|
if TYPE_CHECKING:
|
|
6
8
|
from isar.state_machine.state_machine import StateMachine
|
|
@@ -10,6 +12,22 @@ class Paused(EventHandlerBase):
|
|
|
10
12
|
|
|
11
13
|
def __init__(self, state_machine: "StateMachine"):
|
|
12
14
|
events = state_machine.events
|
|
15
|
+
shared_state = state_machine.shared_state
|
|
16
|
+
|
|
17
|
+
def _robot_battery_level_updated_handler(
|
|
18
|
+
event: Event[float],
|
|
19
|
+
) -> Optional[Callable]:
|
|
20
|
+
battery_level: float = event.check()
|
|
21
|
+
if battery_level < settings.ROBOT_MISSION_BATTERY_START_THRESHOLD:
|
|
22
|
+
state_machine.publish_mission_aborted(
|
|
23
|
+
"Robot battery too low to continue mission", True
|
|
24
|
+
)
|
|
25
|
+
state_machine._finalize()
|
|
26
|
+
state_machine.logger.warning(
|
|
27
|
+
"Cancelling current mission due to low battery"
|
|
28
|
+
)
|
|
29
|
+
return state_machine.stop # type: ignore
|
|
30
|
+
return None
|
|
13
31
|
|
|
14
32
|
event_handlers: List[EventHandlerMapping] = [
|
|
15
33
|
EventHandlerMapping(
|
|
@@ -22,6 +40,11 @@ class Paused(EventHandlerBase):
|
|
|
22
40
|
event=events.api_requests.resume_mission.request,
|
|
23
41
|
handler=lambda event: state_machine.resume if event.consume_event() else None, # type: ignore
|
|
24
42
|
),
|
|
43
|
+
EventHandlerMapping(
|
|
44
|
+
name="robot_battery_update_event",
|
|
45
|
+
event=shared_state.robot_battery_level,
|
|
46
|
+
handler=_robot_battery_level_updated_handler,
|
|
47
|
+
),
|
|
25
48
|
]
|
|
26
49
|
super().__init__(
|
|
27
50
|
state_name="paused",
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Callable, List, Optional
|
|
2
|
+
|
|
3
|
+
from isar.apis.models.models import MissionStartResponse
|
|
4
|
+
from isar.config.settings import settings
|
|
5
|
+
from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
|
|
6
|
+
from isar.models.events import Event
|
|
7
|
+
from robot_interface.models.mission.mission import Mission
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from isar.state_machine.state_machine import StateMachine
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ReturnHomePaused(EventHandlerBase):
|
|
14
|
+
|
|
15
|
+
def __init__(self, state_machine: "StateMachine"):
|
|
16
|
+
events = state_machine.events
|
|
17
|
+
shared_state = state_machine.shared_state
|
|
18
|
+
|
|
19
|
+
def _robot_battery_level_updated_handler(
|
|
20
|
+
event: Event[float],
|
|
21
|
+
) -> Optional[Callable]:
|
|
22
|
+
battery_level: float = event.check()
|
|
23
|
+
if battery_level < settings.ROBOT_MISSION_BATTERY_START_THRESHOLD:
|
|
24
|
+
return state_machine.resume # type: ignore
|
|
25
|
+
return None
|
|
26
|
+
|
|
27
|
+
def _start_mission_event_handler(
|
|
28
|
+
event: Event[Mission],
|
|
29
|
+
) -> Optional[Callable]:
|
|
30
|
+
if event.has_event():
|
|
31
|
+
if not state_machine.battery_level_is_above_mission_start_threshold():
|
|
32
|
+
state_machine.events.api_requests.start_mission.request.consume_event()
|
|
33
|
+
response = MissionStartResponse(
|
|
34
|
+
mission_id=None,
|
|
35
|
+
mission_started=False,
|
|
36
|
+
mission_not_started_reason="Robot battery too low",
|
|
37
|
+
)
|
|
38
|
+
state_machine.events.api_requests.start_mission.response.trigger_event(
|
|
39
|
+
response
|
|
40
|
+
)
|
|
41
|
+
return None
|
|
42
|
+
return state_machine.stop_return_home # type: ignore
|
|
43
|
+
return None
|
|
44
|
+
|
|
45
|
+
event_handlers: List[EventHandlerMapping] = [
|
|
46
|
+
EventHandlerMapping(
|
|
47
|
+
name="resume_return_home_event",
|
|
48
|
+
event=events.api_requests.resume_mission.request,
|
|
49
|
+
handler=lambda event: state_machine.resume if event.consume_event() else None, # type: ignore
|
|
50
|
+
),
|
|
51
|
+
EventHandlerMapping(
|
|
52
|
+
name="robot_battery_update_event",
|
|
53
|
+
event=shared_state.robot_battery_level,
|
|
54
|
+
handler=_robot_battery_level_updated_handler,
|
|
55
|
+
),
|
|
56
|
+
EventHandlerMapping(
|
|
57
|
+
name="start_mission_event",
|
|
58
|
+
event=events.api_requests.start_mission.request,
|
|
59
|
+
handler=_start_mission_event_handler,
|
|
60
|
+
),
|
|
61
|
+
]
|
|
62
|
+
super().__init__(
|
|
63
|
+
state_name="return_home_paused",
|
|
64
|
+
state_machine=state_machine,
|
|
65
|
+
event_handler_mappings=event_handlers,
|
|
66
|
+
)
|
|
@@ -6,7 +6,6 @@ from isar.models.events import Event
|
|
|
6
6
|
from isar.state_machine.utils.common_event_handlers import (
|
|
7
7
|
mission_failed_event_handler,
|
|
8
8
|
mission_started_event_handler,
|
|
9
|
-
stop_mission_event_handler,
|
|
10
9
|
task_status_event_handler,
|
|
11
10
|
task_status_failed_event_handler,
|
|
12
11
|
)
|
|
@@ -24,6 +23,11 @@ class ReturningHome(EventHandlerBase):
|
|
|
24
23
|
self.failed_return_home_attemps: int = 0
|
|
25
24
|
events = state_machine.events
|
|
26
25
|
|
|
26
|
+
def _pause_mission_event_handler(event: Event[bool]) -> Optional[Callable]:
|
|
27
|
+
if event.consume_event():
|
|
28
|
+
return state_machine.pause # type: ignore
|
|
29
|
+
return None
|
|
30
|
+
|
|
27
31
|
def _handle_task_completed(status: TaskStatus):
|
|
28
32
|
if status != TaskStatus.Successful:
|
|
29
33
|
state_machine.current_mission.error_message = ErrorMessage(
|
|
@@ -43,6 +47,7 @@ class ReturningHome(EventHandlerBase):
|
|
|
43
47
|
) -> Optional[Callable]:
|
|
44
48
|
if event.has_event():
|
|
45
49
|
if not state_machine.battery_level_is_above_mission_start_threshold():
|
|
50
|
+
state_machine.events.api_requests.start_mission.request.consume_event()
|
|
46
51
|
response = MissionStartResponse(
|
|
47
52
|
mission_id=None,
|
|
48
53
|
mission_started=False,
|
|
@@ -52,14 +57,14 @@ class ReturningHome(EventHandlerBase):
|
|
|
52
57
|
response
|
|
53
58
|
)
|
|
54
59
|
return None
|
|
55
|
-
return state_machine.
|
|
60
|
+
return state_machine.stop_return_home # type: ignore
|
|
56
61
|
return None
|
|
57
62
|
|
|
58
63
|
event_handlers: List[EventHandlerMapping] = [
|
|
59
64
|
EventHandlerMapping(
|
|
60
|
-
name="
|
|
61
|
-
event=events.api_requests.
|
|
62
|
-
handler=
|
|
65
|
+
name="pause_mission_event",
|
|
66
|
+
event=events.api_requests.pause_mission.request,
|
|
67
|
+
handler=_pause_mission_event_handler,
|
|
63
68
|
),
|
|
64
69
|
EventHandlerMapping(
|
|
65
70
|
name="mission_started_event",
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import logging
|
|
2
1
|
from typing import TYPE_CHECKING, Callable, List, Optional
|
|
3
2
|
|
|
4
3
|
from isar.apis.models.models import ControlMissionResponse
|
|
@@ -14,7 +13,6 @@ if TYPE_CHECKING:
|
|
|
14
13
|
class Stopping(EventHandlerBase):
|
|
15
14
|
|
|
16
15
|
def __init__(self, state_machine: "StateMachine"):
|
|
17
|
-
logger = logging.getLogger("state_machine")
|
|
18
16
|
events = state_machine.events
|
|
19
17
|
|
|
20
18
|
def _stop_mission_cleanup() -> None:
|
|
@@ -48,30 +46,15 @@ class Stopping(EventHandlerBase):
|
|
|
48
46
|
) -> Optional[Callable]:
|
|
49
47
|
error_message: Optional[ErrorMessage] = event.consume_event()
|
|
50
48
|
if error_message is not None:
|
|
51
|
-
|
|
52
|
-
if (
|
|
53
|
-
state_machine.current_mission is not None
|
|
54
|
-
and state_machine.current_mission._is_return_to_home_mission()
|
|
55
|
-
):
|
|
56
|
-
return state_machine.return_home_mission_stopping_failed # type: ignore
|
|
57
|
-
else:
|
|
58
|
-
return state_machine.mission_stopping_failed # type: ignore
|
|
49
|
+
return state_machine.mission_stopping_failed # type: ignore
|
|
59
50
|
return None
|
|
60
51
|
|
|
61
52
|
def _successful_stop_event_handler(event: Event[bool]) -> Optional[Callable]:
|
|
62
53
|
if event.consume_event():
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return state_machine.return_home_mission_stopped # type: ignore
|
|
68
|
-
else:
|
|
69
|
-
_stop_mission_cleanup()
|
|
70
|
-
if (
|
|
71
|
-
not state_machine.battery_level_is_above_mission_start_threshold()
|
|
72
|
-
):
|
|
73
|
-
return state_machine.request_return_home # type: ignore
|
|
74
|
-
return state_machine.mission_stopped # type: ignore
|
|
54
|
+
_stop_mission_cleanup()
|
|
55
|
+
if not state_machine.battery_level_is_above_mission_start_threshold():
|
|
56
|
+
return state_machine.request_return_home # type: ignore
|
|
57
|
+
return state_machine.mission_stopped # type: ignore
|
|
75
58
|
return None
|
|
76
59
|
|
|
77
60
|
event_handlers: List[EventHandlerMapping] = [
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import TYPE_CHECKING, Callable, List, Optional
|
|
3
|
+
|
|
4
|
+
from isar.apis.models.models import MissionStartResponse
|
|
5
|
+
from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
|
|
6
|
+
from isar.models.events import Event
|
|
7
|
+
from robot_interface.models.exceptions.robot_exceptions import ErrorMessage
|
|
8
|
+
from robot_interface.models.mission.mission import Mission
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from isar.state_machine.state_machine import StateMachine
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class StoppingReturnHome(EventHandlerBase):
|
|
15
|
+
|
|
16
|
+
def __init__(self, state_machine: "StateMachine"):
|
|
17
|
+
logger = logging.getLogger("state_machine")
|
|
18
|
+
events = state_machine.events
|
|
19
|
+
|
|
20
|
+
def _failed_stop_event_handler(
|
|
21
|
+
event: Event[ErrorMessage],
|
|
22
|
+
) -> Optional[Callable]:
|
|
23
|
+
error_message: Optional[ErrorMessage] = event.consume_event()
|
|
24
|
+
if error_message is not None:
|
|
25
|
+
logger.warning(error_message.error_description)
|
|
26
|
+
mission: Mission = (
|
|
27
|
+
state_machine.events.api_requests.start_mission.request.consume_event()
|
|
28
|
+
)
|
|
29
|
+
state_machine.events.api_requests.start_mission.response.trigger_event(
|
|
30
|
+
MissionStartResponse(
|
|
31
|
+
mission_id=mission.id,
|
|
32
|
+
mission_started=False,
|
|
33
|
+
mission_not_started_reason="Failed to cancel return home mission",
|
|
34
|
+
)
|
|
35
|
+
)
|
|
36
|
+
return state_machine.return_home_mission_stopping_failed # type: ignore
|
|
37
|
+
return None
|
|
38
|
+
|
|
39
|
+
def _successful_stop_event_handler(event: Event[bool]) -> Optional[Callable]:
|
|
40
|
+
if event.consume_event():
|
|
41
|
+
mission: Mission = (
|
|
42
|
+
state_machine.events.api_requests.start_mission.request.consume_event()
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
state_machine.reset_state_machine()
|
|
46
|
+
|
|
47
|
+
if mission:
|
|
48
|
+
state_machine.start_mission(mission=mission)
|
|
49
|
+
return state_machine.request_mission_start # type: ignore
|
|
50
|
+
|
|
51
|
+
state_machine.logger.error(
|
|
52
|
+
"Stopped return home without a new mission to start"
|
|
53
|
+
)
|
|
54
|
+
return state_machine.request_return_home # type: ignore
|
|
55
|
+
return None
|
|
56
|
+
|
|
57
|
+
event_handlers: List[EventHandlerMapping] = [
|
|
58
|
+
EventHandlerMapping(
|
|
59
|
+
name="failed_stop_event",
|
|
60
|
+
event=events.robot_service_events.mission_failed_to_stop,
|
|
61
|
+
handler=_failed_stop_event_handler,
|
|
62
|
+
),
|
|
63
|
+
EventHandlerMapping(
|
|
64
|
+
name="successful_stop_event",
|
|
65
|
+
event=events.robot_service_events.mission_successfully_stopped,
|
|
66
|
+
handler=_successful_stop_event_handler,
|
|
67
|
+
),
|
|
68
|
+
]
|
|
69
|
+
super().__init__(
|
|
70
|
+
state_name="stopping_return_home",
|
|
71
|
+
state_machine=state_machine,
|
|
72
|
+
event_handler_mappings=event_handlers,
|
|
73
|
+
)
|
|
@@ -5,10 +5,11 @@ class States(str, Enum):
|
|
|
5
5
|
Monitor = "monitor"
|
|
6
6
|
ReturningHome = "returning_home"
|
|
7
7
|
Stopping = "stopping"
|
|
8
|
+
StoppingReturnHome = "stopping_return_home"
|
|
8
9
|
Paused = "paused"
|
|
10
|
+
ReturnHomePaused = "return_home_paused"
|
|
9
11
|
AwaitNextMission = "await_next_mission"
|
|
10
12
|
Home = "home"
|
|
11
|
-
RobotStandingStill = "robot_standing_still"
|
|
12
13
|
Offline = "offline"
|
|
13
14
|
BlockedProtectiveStop = "blocked_protective_stop"
|
|
14
15
|
UnknownStatus = "unknown_status"
|