isar 1.26.4__tar.gz → 1.27.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of isar might be problematic. Click here for more details.

Files changed (222) hide show
  1. {isar-1.26.4 → isar-1.27.1}/PKG-INFO +14 -7
  2. {isar-1.26.4 → isar-1.27.1}/README.md +13 -6
  3. isar-1.27.1/docs/full_state_machine_diagram.png +0 -0
  4. isar-1.27.1/docs/mission_state_machine_diagram.png +0 -0
  5. isar-1.27.1/docs/robot_status_state_machine_diagram.png +0 -0
  6. isar-1.27.1/docs/update_state_diagram.py +58 -0
  7. {isar-1.26.4 → isar-1.27.1}/src/isar/apis/api.py +25 -0
  8. {isar-1.26.4 → isar-1.27.1}/src/isar/apis/models/start_mission_definition.py +1 -7
  9. {isar-1.26.4 → isar-1.27.1}/src/isar/apis/schedule/scheduling_controller.py +17 -1
  10. {isar-1.26.4 → isar-1.27.1}/src/isar/config/settings.py +4 -1
  11. {isar-1.26.4 → isar-1.27.1}/src/isar/models/communication/queues/events.py +1 -0
  12. {isar-1.26.4 → isar-1.27.1}/src/isar/models/communication/queues/queue_utils.py +6 -0
  13. {isar-1.26.4 → isar-1.27.1}/src/isar/modules.py +13 -6
  14. {isar-1.26.4 → isar-1.27.1}/src/isar/robot/robot.py +10 -1
  15. {isar-1.26.4 → isar-1.27.1}/src/isar/robot/robot_status.py +11 -5
  16. {isar-1.26.4 → isar-1.27.1}/src/isar/robot/robot_task_status.py +3 -3
  17. {isar-1.26.4 → isar-1.27.1}/src/isar/services/utilities/scheduling_utilities.py +60 -7
  18. {isar-1.26.4 → isar-1.27.1}/src/isar/state_machine/state_machine.py +51 -121
  19. isar-1.27.1/src/isar/state_machine/states/await_next_mission.py +92 -0
  20. {isar-1.26.4 → isar-1.27.1}/src/isar/state_machine/states/blocked_protective_stop.py +2 -5
  21. isar-1.27.1/src/isar/state_machine/states/home.py +87 -0
  22. {isar-1.26.4 → isar-1.27.1}/src/isar/state_machine/states/monitor.py +8 -3
  23. {isar-1.26.4 → isar-1.27.1}/src/isar/state_machine/states/offline.py +3 -5
  24. isar-1.27.1/src/isar/state_machine/states/returning_home.py +186 -0
  25. isar-1.26.4/src/isar/state_machine/states/idle.py → isar-1.27.1/src/isar/state_machine/states/robot_standing_still.py +20 -8
  26. isar-1.26.4/src/isar/state_machine/states/stop.py → isar-1.27.1/src/isar/state_machine/states/stopping.py +16 -4
  27. isar-1.27.1/src/isar/state_machine/states/unknown_status.py +74 -0
  28. {isar-1.26.4 → isar-1.27.1}/src/isar/state_machine/states_enum.py +6 -3
  29. isar-1.27.1/src/isar/state_machine/transitions/functions/return_home.py +38 -0
  30. isar-1.27.1/src/isar/state_machine/transitions/functions/robot_status.py +27 -0
  31. {isar-1.26.4/src/isar/state_machine/transitions → isar-1.27.1/src/isar/state_machine/transitions/functions}/start_mission.py +1 -1
  32. isar-1.27.1/src/isar/state_machine/transitions/mission.py +119 -0
  33. isar-1.27.1/src/isar/state_machine/transitions/return_home.py +69 -0
  34. isar-1.27.1/src/isar/state_machine/transitions/robot_status.py +73 -0
  35. {isar-1.26.4 → isar-1.27.1}/src/isar.egg-info/PKG-INFO +14 -7
  36. {isar-1.26.4 → isar-1.27.1}/src/isar.egg-info/SOURCES.txt +22 -11
  37. {isar-1.26.4 → isar-1.27.1}/src/robot_interface/models/exceptions/robot_exceptions.py +14 -0
  38. {isar-1.26.4 → isar-1.27.1}/src/robot_interface/models/mission/mission.py +8 -1
  39. {isar-1.26.4 → isar-1.27.1}/src/robot_interface/models/mission/status.py +2 -0
  40. {isar-1.26.4 → isar-1.27.1}/src/robot_interface/models/mission/task.py +0 -1
  41. {isar-1.26.4 → isar-1.27.1}/tests/conftest.py +4 -4
  42. {isar-1.26.4 → isar-1.27.1}/tests/integration/turtlebot/test_successful_mission.py +1 -1
  43. {isar-1.26.4 → isar-1.27.1}/tests/isar/apis/scheduler/test_scheduler_router.py +56 -17
  44. {isar-1.26.4 → isar-1.27.1}/tests/isar/mission/test_mission.py +1 -7
  45. {isar-1.26.4 → isar-1.27.1}/tests/isar/services/readers/test_mission_reader.py +9 -20
  46. {isar-1.26.4 → isar-1.27.1}/tests/isar/services/utilities/test_scheduling_utilities.py +10 -1
  47. {isar-1.26.4 → isar-1.27.1}/tests/isar/state_machine/states/test_monitor.py +2 -2
  48. {isar-1.26.4 → isar-1.27.1}/tests/isar/state_machine/test_state_machine.py +152 -43
  49. {isar-1.26.4 → isar-1.27.1}/tests/mocks/mission_definition.py +1 -8
  50. {isar-1.26.4 → isar-1.27.1}/tests/mocks/robot_interface.py +46 -9
  51. {isar-1.26.4 → isar-1.27.1}/tests/mocks/status.py +1 -1
  52. {isar-1.26.4 → isar-1.27.1}/tests/mocks/task.py +1 -6
  53. {isar-1.26.4 → isar-1.27.1}/tests/test_data/test_mission_working.json +0 -38
  54. isar-1.26.4/docs/state_machine_diagram.png +0 -0
  55. isar-1.26.4/src/isar/state_machine/states/off.py +0 -18
  56. {isar-1.26.4 → isar-1.27.1}/.dockerignore +0 -0
  57. {isar-1.26.4 → isar-1.27.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  58. {isar-1.26.4 → isar-1.27.1}/.github/ISSUE_TEMPLATE/feature.md +0 -0
  59. {isar-1.26.4 → isar-1.27.1}/.github/ISSUE_TEMPLATE/improvement.md +0 -0
  60. {isar-1.26.4 → isar-1.27.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  61. {isar-1.26.4 → isar-1.27.1}/.github/release.yml +0 -0
  62. {isar-1.26.4 → isar-1.27.1}/.github/workflows/compile_requirements.yml +0 -0
  63. {isar-1.26.4 → isar-1.27.1}/.github/workflows/project_automations.yml +0 -0
  64. {isar-1.26.4 → isar-1.27.1}/.github/workflows/pythonpackage.yml +0 -0
  65. {isar-1.26.4 → isar-1.27.1}/.github/workflows/pythonpublish.yml +0 -0
  66. {isar-1.26.4 → isar-1.27.1}/.github/workflows/stale.yml +0 -0
  67. {isar-1.26.4 → isar-1.27.1}/.gitignore +0 -0
  68. {isar-1.26.4 → isar-1.27.1}/.pre-commit-config.yaml +0 -0
  69. {isar-1.26.4 → isar-1.27.1}/LICENSE +0 -0
  70. {isar-1.26.4 → isar-1.27.1}/SECURITY.md +0 -0
  71. {isar-1.26.4 → isar-1.27.1}/docs/Makefile +0 -0
  72. {isar-1.26.4 → isar-1.27.1}/docs/make.bat +0 -0
  73. {isar-1.26.4 → isar-1.27.1}/docs/rst_processing.py +0 -0
  74. {isar-1.26.4 → isar-1.27.1}/docs/source/conf.py +0 -0
  75. {isar-1.26.4 → isar-1.27.1}/docs/source/index.rst +0 -0
  76. {isar-1.26.4 → isar-1.27.1}/docs/source/readme_link.md +0 -0
  77. {isar-1.26.4 → isar-1.27.1}/main.py +0 -0
  78. {isar-1.26.4 → isar-1.27.1}/pyproject.toml +0 -0
  79. {isar-1.26.4 → isar-1.27.1}/radixconfig.yml +0 -0
  80. {isar-1.26.4 → isar-1.27.1}/requirements.txt +0 -0
  81. {isar-1.26.4 → isar-1.27.1}/setup.cfg +0 -0
  82. {isar-1.26.4 → isar-1.27.1}/src/isar/__init__.py +0 -0
  83. {isar-1.26.4 → isar-1.27.1}/src/isar/apis/__init__.py +0 -0
  84. {isar-1.26.4 → isar-1.27.1}/src/isar/apis/models/__init__.py +0 -0
  85. {isar-1.26.4 → isar-1.27.1}/src/isar/apis/models/models.py +0 -0
  86. {isar-1.26.4 → isar-1.27.1}/src/isar/apis/robot_control/robot_controller.py +0 -0
  87. {isar-1.26.4 → isar-1.27.1}/src/isar/apis/schedule/__init__.py +0 -0
  88. {isar-1.26.4 → isar-1.27.1}/src/isar/apis/security/__init__.py +0 -0
  89. {isar-1.26.4 → isar-1.27.1}/src/isar/apis/security/authentication.py +0 -0
  90. {isar-1.26.4 → isar-1.27.1}/src/isar/config/__init__.py +0 -0
  91. {isar-1.26.4 → isar-1.27.1}/src/isar/config/certs/ca-cert.pem +0 -0
  92. {isar-1.26.4 → isar-1.27.1}/src/isar/config/configuration_error.py +0 -0
  93. {isar-1.26.4 → isar-1.27.1}/src/isar/config/keyvault/__init__.py +0 -0
  94. {isar-1.26.4 → isar-1.27.1}/src/isar/config/keyvault/keyvault_error.py +0 -0
  95. {isar-1.26.4 → isar-1.27.1}/src/isar/config/keyvault/keyvault_service.py +0 -0
  96. {isar-1.26.4 → isar-1.27.1}/src/isar/config/log.py +0 -0
  97. {isar-1.26.4 → isar-1.27.1}/src/isar/config/logging.conf +0 -0
  98. {isar-1.26.4 → isar-1.27.1}/src/isar/config/maps/JSP1_intermediate_deck.json +0 -0
  99. {isar-1.26.4 → isar-1.27.1}/src/isar/config/maps/JSP1_weather_deck.json +0 -0
  100. {isar-1.26.4 → isar-1.27.1}/src/isar/config/maps/default_map.json +0 -0
  101. {isar-1.26.4 → isar-1.27.1}/src/isar/config/maps/klab_b.json +0 -0
  102. {isar-1.26.4 → isar-1.27.1}/src/isar/config/maps/klab_compressor.json +0 -0
  103. {isar-1.26.4 → isar-1.27.1}/src/isar/config/maps/klab_turtlebot.json +0 -0
  104. {isar-1.26.4 → isar-1.27.1}/src/isar/config/maps/turtleworld.json +0 -0
  105. {isar-1.26.4 → isar-1.27.1}/src/isar/config/predefined_mission_definition/__init__.py +0 -0
  106. {isar-1.26.4 → isar-1.27.1}/src/isar/config/predefined_mission_definition/default_exr.json +0 -0
  107. {isar-1.26.4 → isar-1.27.1}/src/isar/config/predefined_mission_definition/default_mission.json +0 -0
  108. {isar-1.26.4 → isar-1.27.1}/src/isar/config/predefined_mission_definition/default_turtlebot.json +0 -0
  109. {isar-1.26.4 → isar-1.27.1}/src/isar/config/predefined_missions/__init__.py +0 -0
  110. {isar-1.26.4 → isar-1.27.1}/src/isar/config/predefined_missions/default.json +0 -0
  111. {isar-1.26.4 → isar-1.27.1}/src/isar/config/predefined_missions/default_turtlebot.json +0 -0
  112. {isar-1.26.4 → isar-1.27.1}/src/isar/config/settings.env +0 -0
  113. {isar-1.26.4 → isar-1.27.1}/src/isar/mission_planner/__init__.py +0 -0
  114. {isar-1.26.4 → isar-1.27.1}/src/isar/mission_planner/local_planner.py +0 -0
  115. {isar-1.26.4 → isar-1.27.1}/src/isar/mission_planner/mission_planner_interface.py +0 -0
  116. {isar-1.26.4 → isar-1.27.1}/src/isar/mission_planner/sequential_task_selector.py +0 -0
  117. {isar-1.26.4 → isar-1.27.1}/src/isar/mission_planner/task_selector_interface.py +0 -0
  118. {isar-1.26.4 → isar-1.27.1}/src/isar/models/__init__.py +0 -0
  119. {isar-1.26.4 → isar-1.27.1}/src/isar/models/communication/__init__.py +0 -0
  120. {isar-1.26.4 → isar-1.27.1}/src/isar/models/communication/message.py +0 -0
  121. {isar-1.26.4 → isar-1.27.1}/src/isar/models/communication/queues/__init__.py +0 -0
  122. {isar-1.26.4 → isar-1.27.1}/src/isar/models/communication/queues/queue_io.py +0 -0
  123. {isar-1.26.4 → isar-1.27.1}/src/isar/models/communication/queues/queue_timeout_error.py +0 -0
  124. {isar-1.26.4 → isar-1.27.1}/src/isar/models/communication/queues/status_queue.py +0 -0
  125. {isar-1.26.4 → isar-1.27.1}/src/isar/models/mission_metadata/__init__.py +0 -0
  126. {isar-1.26.4 → isar-1.27.1}/src/isar/robot/robot_start_mission.py +0 -0
  127. {isar-1.26.4 → isar-1.27.1}/src/isar/robot/robot_stop_mission.py +0 -0
  128. {isar-1.26.4 → isar-1.27.1}/src/isar/script.py +0 -0
  129. {isar-1.26.4 → isar-1.27.1}/src/isar/services/__init__.py +0 -0
  130. {isar-1.26.4 → isar-1.27.1}/src/isar/services/auth/__init__.py +0 -0
  131. {isar-1.26.4 → isar-1.27.1}/src/isar/services/auth/azure_credentials.py +0 -0
  132. {isar-1.26.4 → isar-1.27.1}/src/isar/services/service_connections/__init__.py +0 -0
  133. {isar-1.26.4 → isar-1.27.1}/src/isar/services/service_connections/mqtt/__init__.py +0 -0
  134. {isar-1.26.4 → isar-1.27.1}/src/isar/services/service_connections/mqtt/mqtt_client.py +0 -0
  135. {isar-1.26.4 → isar-1.27.1}/src/isar/services/service_connections/mqtt/robot_heartbeat_publisher.py +0 -0
  136. {isar-1.26.4 → isar-1.27.1}/src/isar/services/service_connections/mqtt/robot_info_publisher.py +0 -0
  137. {isar-1.26.4 → isar-1.27.1}/src/isar/services/service_connections/request_handler.py +0 -0
  138. {isar-1.26.4 → isar-1.27.1}/src/isar/services/service_connections/stid/__init__.py +0 -0
  139. {isar-1.26.4 → isar-1.27.1}/src/isar/services/utilities/__init__.py +0 -0
  140. {isar-1.26.4 → isar-1.27.1}/src/isar/services/utilities/queue_utilities.py +0 -0
  141. {isar-1.26.4 → isar-1.27.1}/src/isar/services/utilities/robot_utilities.py +0 -0
  142. {isar-1.26.4 → isar-1.27.1}/src/isar/services/utilities/threaded_request.py +0 -0
  143. {isar-1.26.4 → isar-1.27.1}/src/isar/state_machine/__init__.py +0 -0
  144. {isar-1.26.4 → isar-1.27.1}/src/isar/state_machine/states/__init__.py +0 -0
  145. {isar-1.26.4 → isar-1.27.1}/src/isar/state_machine/states/paused.py +0 -0
  146. {isar-1.26.4/src/isar/state_machine/transitions → isar-1.27.1/src/isar/state_machine/transitions/functions}/fail_mission.py +0 -0
  147. {isar-1.26.4/src/isar/state_machine/transitions → isar-1.27.1/src/isar/state_machine/transitions/functions}/finish_mission.py +0 -0
  148. {isar-1.26.4/src/isar/state_machine/transitions → isar-1.27.1/src/isar/state_machine/transitions/functions}/pause.py +0 -0
  149. {isar-1.26.4/src/isar/state_machine/transitions → isar-1.27.1/src/isar/state_machine/transitions/functions}/resume.py +0 -0
  150. {isar-1.26.4/src/isar/state_machine/transitions → isar-1.27.1/src/isar/state_machine/transitions/functions}/stop.py +0 -0
  151. {isar-1.26.4/src/isar/state_machine/transitions → isar-1.27.1/src/isar/state_machine/transitions/functions}/utils.py +0 -0
  152. {isar-1.26.4 → isar-1.27.1}/src/isar/storage/__init__.py +0 -0
  153. {isar-1.26.4 → isar-1.27.1}/src/isar/storage/blob_storage.py +0 -0
  154. {isar-1.26.4 → isar-1.27.1}/src/isar/storage/local_storage.py +0 -0
  155. {isar-1.26.4 → isar-1.27.1}/src/isar/storage/slimm_storage.py +0 -0
  156. {isar-1.26.4 → isar-1.27.1}/src/isar/storage/storage_interface.py +0 -0
  157. {isar-1.26.4 → isar-1.27.1}/src/isar/storage/uploader.py +0 -0
  158. {isar-1.26.4 → isar-1.27.1}/src/isar/storage/utilities.py +0 -0
  159. {isar-1.26.4 → isar-1.27.1}/src/isar.egg-info/dependency_links.txt +0 -0
  160. {isar-1.26.4 → isar-1.27.1}/src/isar.egg-info/entry_points.txt +0 -0
  161. {isar-1.26.4 → isar-1.27.1}/src/isar.egg-info/requires.txt +0 -0
  162. {isar-1.26.4 → isar-1.27.1}/src/isar.egg-info/top_level.txt +0 -0
  163. {isar-1.26.4 → isar-1.27.1}/src/robot_interface/__init__.py +0 -0
  164. {isar-1.26.4 → isar-1.27.1}/src/robot_interface/models/__init__.py +0 -0
  165. {isar-1.26.4 → isar-1.27.1}/src/robot_interface/models/exceptions/__init__.py +0 -0
  166. {isar-1.26.4 → isar-1.27.1}/src/robot_interface/models/initialize/__init__.py +0 -0
  167. {isar-1.26.4 → isar-1.27.1}/src/robot_interface/models/inspection/__init__.py +0 -0
  168. {isar-1.26.4 → isar-1.27.1}/src/robot_interface/models/inspection/inspection.py +0 -0
  169. {isar-1.26.4 → isar-1.27.1}/src/robot_interface/models/mission/__init__.py +0 -0
  170. {isar-1.26.4 → isar-1.27.1}/src/robot_interface/models/robots/__init__.py +0 -0
  171. {isar-1.26.4 → isar-1.27.1}/src/robot_interface/models/robots/battery_state.py +0 -0
  172. {isar-1.26.4 → isar-1.27.1}/src/robot_interface/models/robots/media.py +0 -0
  173. {isar-1.26.4 → isar-1.27.1}/src/robot_interface/models/robots/robot_model.py +0 -0
  174. {isar-1.26.4 → isar-1.27.1}/src/robot_interface/robot_interface.py +0 -0
  175. {isar-1.26.4 → isar-1.27.1}/src/robot_interface/telemetry/__init__.py +0 -0
  176. {isar-1.26.4 → isar-1.27.1}/src/robot_interface/telemetry/mqtt_client.py +0 -0
  177. {isar-1.26.4 → isar-1.27.1}/src/robot_interface/telemetry/payloads.py +0 -0
  178. {isar-1.26.4 → isar-1.27.1}/src/robot_interface/test_robot_interface.py +0 -0
  179. {isar-1.26.4 → isar-1.27.1}/src/robot_interface/utilities/__init__.py +0 -0
  180. {isar-1.26.4 → isar-1.27.1}/src/robot_interface/utilities/json_service.py +0 -0
  181. {isar-1.26.4 → isar-1.27.1}/src/robot_interface/utilities/uuid_string_factory.py +0 -0
  182. {isar-1.26.4 → isar-1.27.1}/tests/__init__.py +0 -0
  183. {isar-1.26.4 → isar-1.27.1}/tests/integration/__init__.py +0 -0
  184. {isar-1.26.4 → isar-1.27.1}/tests/integration/turtlebot/__init__.py +0 -0
  185. {isar-1.26.4 → isar-1.27.1}/tests/integration/turtlebot/config/__init__.py +0 -0
  186. {isar-1.26.4 → isar-1.27.1}/tests/integration/turtlebot/config/maps/__init__.py +0 -0
  187. {isar-1.26.4 → isar-1.27.1}/tests/integration/turtlebot/config/maps/turtleworld.json +0 -0
  188. {isar-1.26.4 → isar-1.27.1}/tests/integration/turtlebot/config/missions/__init__.py +0 -0
  189. {isar-1.26.4 → isar-1.27.1}/tests/integration/turtlebot/config/missions/default.json +0 -0
  190. {isar-1.26.4 → isar-1.27.1}/tests/isar/__init__.py +0 -0
  191. {isar-1.26.4 → isar-1.27.1}/tests/isar/apis/__init__.py +0 -0
  192. {isar-1.26.4 → isar-1.27.1}/tests/isar/apis/models/__init__.py +0 -0
  193. {isar-1.26.4 → isar-1.27.1}/tests/isar/apis/models/example_mission_definition.json +0 -0
  194. {isar-1.26.4 → isar-1.27.1}/tests/isar/apis/models/test_start_mission_definition.py +0 -0
  195. {isar-1.26.4 → isar-1.27.1}/tests/isar/apis/scheduler/__init__.py +0 -0
  196. {isar-1.26.4 → isar-1.27.1}/tests/isar/apis/security/__init__.py +0 -0
  197. {isar-1.26.4 → isar-1.27.1}/tests/isar/apis/security/test_authentication.py +0 -0
  198. {isar-1.26.4 → isar-1.27.1}/tests/isar/mission/__init__.py +0 -0
  199. {isar-1.26.4 → isar-1.27.1}/tests/isar/models/__init__.py +0 -0
  200. {isar-1.26.4 → isar-1.27.1}/tests/isar/models/communication/__init__.py +0 -0
  201. {isar-1.26.4 → isar-1.27.1}/tests/isar/models/communication/test_queues.py +0 -0
  202. {isar-1.26.4 → isar-1.27.1}/tests/isar/services/__init__.py +0 -0
  203. {isar-1.26.4 → isar-1.27.1}/tests/isar/services/readers/__init__.py +0 -0
  204. {isar-1.26.4 → isar-1.27.1}/tests/isar/services/service_connections/__init__.py +0 -0
  205. {isar-1.26.4 → isar-1.27.1}/tests/isar/services/service_connections/echo/__init__.py +0 -0
  206. {isar-1.26.4 → isar-1.27.1}/tests/isar/services/service_connections/test_base_request_handler.py +0 -0
  207. {isar-1.26.4 → isar-1.27.1}/tests/isar/services/utilities/__init__.py +0 -0
  208. {isar-1.26.4 → isar-1.27.1}/tests/isar/services/utilities/test_queue_utilities.py +0 -0
  209. {isar-1.26.4 → isar-1.27.1}/tests/isar/state_machine/__init__.py +0 -0
  210. {isar-1.26.4 → isar-1.27.1}/tests/isar/state_machine/states/__init__.py +0 -0
  211. {isar-1.26.4 → isar-1.27.1}/tests/isar/storage/test_blob_storage.py +0 -0
  212. {isar-1.26.4 → isar-1.27.1}/tests/isar/storage/test_uploader.py +0 -0
  213. {isar-1.26.4 → isar-1.27.1}/tests/mocks/__init__.py +0 -0
  214. {isar-1.26.4 → isar-1.27.1}/tests/mocks/blob_storage.py +0 -0
  215. {isar-1.26.4 → isar-1.27.1}/tests/mocks/mqtt_client.py +0 -0
  216. {isar-1.26.4 → isar-1.27.1}/tests/mocks/pose.py +0 -0
  217. {isar-1.26.4 → isar-1.27.1}/tests/mocks/request.py +0 -0
  218. {isar-1.26.4 → isar-1.27.1}/tests/mocks/token.py +0 -0
  219. {isar-1.26.4 → isar-1.27.1}/tests/test_data/test_map_config/test_map_config.json +0 -0
  220. {isar-1.26.4 → isar-1.27.1}/tests/test_data/test_mission_not_working.json +0 -0
  221. {isar-1.26.4 → isar-1.27.1}/tests/test_data/test_mission_working_no_tasks.json +0 -0
  222. {isar-1.26.4 → isar-1.27.1}/tests/test_data/test_thermal_image_mission.json +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: isar
3
- Version: 1.26.4
3
+ Version: 1.27.1
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
@@ -331,22 +331,29 @@ The system consists of two main components.
331
331
  The state machine handles interaction with the robots API and monitors the execution of missions. It also enables
332
332
  interacting with the robot before, during and after missions.
333
333
 
334
- The state machine is based on the [transitions](https://github.com/pytransitions/transitions) package for Python. An visualization of the state machine can be seen below:
335
- ![State Machine](./docs/state_machine_diagram.png)
334
+ The state machine is based on the [transitions](https://github.com/pytransitions/transitions) package for Python. The following are some visualizations of the state machine:
335
+
336
+ Mission behavior without the robot status changed transition that enable the resting states to transition between each other if the robot status changes:
337
+ ![State Machine extended](./docs/extended_state_machine_diagram.png)
338
+
339
+ Robot status changed transition:
340
+ ![State Machine robot status changed](./docs/robot_status_state_machine_diagram.png)
341
+
342
+ Full state machine:
343
+ ![State Machine full](./docs/full_state_machine_diagram.png)
336
344
 
337
345
  In general the states
338
346
 
339
347
  ```
340
- States.Off,
341
- States.Stop,
348
+ States.Stopping,
342
349
  States.Monitor,
343
350
  States.Paused,
344
351
  ```
345
352
 
346
- indicates that the state machine is already running. For running a mission the state machine need to be in the state
353
+ indicates that the state machine is already running. For running a mission the state machine need to be in the states
347
354
 
348
355
  ```
349
- States.Idle
356
+ States.Home, States.RobotStandingStill, States.AwaitNextMission or States.ReturningHome
350
357
  ```
351
358
 
352
359
  ### FastAPI
@@ -189,22 +189,29 @@ The system consists of two main components.
189
189
  The state machine handles interaction with the robots API and monitors the execution of missions. It also enables
190
190
  interacting with the robot before, during and after missions.
191
191
 
192
- The state machine is based on the [transitions](https://github.com/pytransitions/transitions) package for Python. An visualization of the state machine can be seen below:
193
- ![State Machine](./docs/state_machine_diagram.png)
192
+ The state machine is based on the [transitions](https://github.com/pytransitions/transitions) package for Python. The following are some visualizations of the state machine:
193
+
194
+ Mission behavior without the robot status changed transition that enable the resting states to transition between each other if the robot status changes:
195
+ ![State Machine extended](./docs/extended_state_machine_diagram.png)
196
+
197
+ Robot status changed transition:
198
+ ![State Machine robot status changed](./docs/robot_status_state_machine_diagram.png)
199
+
200
+ Full state machine:
201
+ ![State Machine full](./docs/full_state_machine_diagram.png)
194
202
 
195
203
  In general the states
196
204
 
197
205
  ```
198
- States.Off,
199
- States.Stop,
206
+ States.Stopping,
200
207
  States.Monitor,
201
208
  States.Paused,
202
209
  ```
203
210
 
204
- indicates that the state machine is already running. For running a mission the state machine need to be in the state
211
+ indicates that the state machine is already running. For running a mission the state machine need to be in the states
205
212
 
206
213
  ```
207
- States.Idle
214
+ States.Home, States.RobotStandingStill, States.AwaitNextMission or States.ReturningHome
208
215
  ```
209
216
 
210
217
  ### FastAPI
@@ -0,0 +1,58 @@
1
+ import os
2
+ from pathlib import Path
3
+ from typing import List
4
+
5
+ from injector import Injector
6
+ from transitions import State
7
+ from transitions.extensions import GraphMachine
8
+
9
+ from isar.modules import get_injector
10
+ from isar.state_machine.state_machine import StateMachine
11
+ from isar.state_machine.transitions.mission import get_mission_transitions
12
+ from isar.state_machine.transitions.return_home import get_return_home_transitions
13
+ from isar.state_machine.transitions.robot_status import get_robot_status_transitions
14
+
15
+
16
+ def draw_diagram(states: List[State], transitions: List[dict], name: str):
17
+ machine = GraphMachine(states=states, initial="unknown_status", queued=True)
18
+ machine.add_transitions(transitions)
19
+ gp = machine.get_combined_graph()
20
+
21
+ state_machine_diagram_file = (
22
+ Path(__file__).parent.resolve().joinpath(Path(f"{name}.png"))
23
+ )
24
+
25
+ if os.path.isfile(state_machine_diagram_file):
26
+ os.remove(state_machine_diagram_file)
27
+
28
+ gp.draw(state_machine_diagram_file, prog="dot")
29
+
30
+
31
+ if __name__ == "__main__":
32
+ injector: Injector = get_injector()
33
+ state_machine: StateMachine = injector.get(StateMachine)
34
+
35
+ mission_extended_transitions: List[dict] = []
36
+ for transition in get_mission_transitions(state_machine):
37
+ mission_extended_transitions.append(transition)
38
+
39
+ for transition in get_return_home_transitions(state_machine):
40
+ mission_extended_transitions.append(transition)
41
+
42
+ draw_diagram(
43
+ states=state_machine.states,
44
+ transitions=mission_extended_transitions,
45
+ name="mission_state_machine_diagram",
46
+ )
47
+
48
+ draw_diagram(
49
+ states=state_machine.states,
50
+ transitions=get_robot_status_transitions(state_machine),
51
+ name="robot_status_state_machine_diagram",
52
+ )
53
+
54
+ draw_diagram(
55
+ states=state_machine.states,
56
+ transitions=state_machine.transitions,
57
+ name="full_state_machine_diagram",
58
+ )
@@ -150,6 +150,31 @@ class API:
150
150
  HTTPStatus.CONFLICT.value: {
151
151
  "description": "Conflict - Invalid command in the current state",
152
152
  },
153
+ HTTPStatus.BAD_REQUEST.value: {
154
+ "description": "Bad request - Robot does not have the capabilities to perform the mission",
155
+ },
156
+ HTTPStatus.INTERNAL_SERVER_ERROR.value: {
157
+ "description": "Internal Server Error - Current state of state machine unknown",
158
+ },
159
+ },
160
+ )
161
+ router.add_api_route(
162
+ path="/schedule/return-home",
163
+ endpoint=self.scheduling_controller.return_home,
164
+ methods=["POST"],
165
+ dependencies=[authentication_dependency],
166
+ summary="Start return home mission",
167
+ responses={
168
+ HTTPStatus.OK.value: {
169
+ "description": "Return home mission succesfully started",
170
+ "model": StartMissionResponse,
171
+ },
172
+ HTTPStatus.UNPROCESSABLE_ENTITY.value: {
173
+ "description": "Invalid body - The JSON is incorrect",
174
+ },
175
+ HTTPStatus.CONFLICT.value: {
176
+ "description": "Conflict - Invalid command in the current state",
177
+ },
153
178
  HTTPStatus.INTERNAL_SERVER_ERROR.value: {
154
179
  "description": "Internal Server Error - Current state of state machine unknown",
155
180
  },
@@ -92,7 +92,7 @@ def to_isar_task(task_definition: StartMissionTaskDefinition) -> TASKS:
92
92
  if task_definition.type == TaskType.Inspection:
93
93
  return to_inspection_task(task_definition)
94
94
  elif task_definition.type == TaskType.ReturnToHome:
95
- return create_return_to_home_task(task_definition)
95
+ return ReturnToHome()
96
96
  else:
97
97
  raise MissionPlannerError(
98
98
  f"Failed to create task: '{task_definition.type}' is not a valid"
@@ -162,11 +162,5 @@ def to_inspection_task(task_definition: StartMissionTaskDefinition) -> TASKS:
162
162
  )
163
163
 
164
164
 
165
- def create_return_to_home_task(
166
- task_definition: StartMissionTaskDefinition,
167
- ) -> ReturnToHome:
168
- return ReturnToHome(pose=task_definition.pose.to_alitra_pose())
169
-
170
-
171
165
  def _build_mission_name() -> str:
172
166
  return f"{settings.PLANT_SHORT_NAME}{settings.ROBOT_NAME}{int(time.time())}"
@@ -98,6 +98,16 @@ class SchedulingController:
98
98
  self.scheduling_utilities.start_mission(mission=mission)
99
99
  return self._api_response(mission)
100
100
 
101
+ def return_home(self) -> None:
102
+ self.logger.info("Received request to return home")
103
+
104
+ state: States = self.scheduling_utilities.get_state()
105
+ self.scheduling_utilities.verify_state_machine_ready_to_receive_return_home_mission(
106
+ state
107
+ )
108
+
109
+ self.scheduling_utilities.return_home()
110
+
101
111
  def pause_mission(self) -> ControlMissionResponse:
102
112
  self.logger.info("Received request to pause current mission")
103
113
 
@@ -142,7 +152,13 @@ class SchedulingController:
142
152
 
143
153
  state: States = self.scheduling_utilities.get_state()
144
154
 
145
- if state == States.Off:
155
+ if (
156
+ state == States.UnknownStatus
157
+ or state == States.Stopping
158
+ or state == States.BlockedProtectiveStop
159
+ or state == States.Offline
160
+ or state == States.Home
161
+ ):
146
162
  error_message = (
147
163
  f"Conflict - Stop command received in invalid state - State: {state}"
148
164
  )
@@ -82,6 +82,9 @@ class Settings(BaseSettings):
82
82
  # FastAPI port
83
83
  API_PORT: int = Field(default=3000)
84
84
 
85
+ # Determines how long delay time should be allowed before returning home
86
+ RETURN_HOME_DELAY: int = Field(default=10)
87
+
85
88
  # Determines which mission planner module is used by ISAR
86
89
  MISSION_PLANNER: str = Field(default="local")
87
90
 
@@ -311,7 +314,7 @@ class RobotSettings(BaseSettings):
311
314
 
312
315
  # ISAR steps the robot is capable of performing
313
316
  # This should be set in the robot package settings.env file
314
- CAPABILITIES: List[str] = Field(default=["return_to_home", "take_image"])
317
+ CAPABILITIES: List[str] = Field(default=["take_image"])
315
318
 
316
319
  # Model of the robot which ISAR is connected to
317
320
  # This should be set in the robot package settings.env file
@@ -29,6 +29,7 @@ class APIRequests:
29
29
  self.stop_mission: QueueIO = QueueIO(input_size=1, output_size=1)
30
30
  self.pause_mission: QueueIO = QueueIO(input_size=1, output_size=1)
31
31
  self.resume_mission: QueueIO = QueueIO(input_size=1, output_size=1)
32
+ self.return_home: QueueIO = QueueIO(input_size=1, output_size=1)
32
33
 
33
34
 
34
35
  class StateMachineEvents:
@@ -30,3 +30,9 @@ def check_for_event(queue: Queue[T]) -> Optional[T]:
30
30
  return queue.get(block=False)
31
31
  except Empty:
32
32
  return None
33
+
34
+
35
+ def check_for_event_without_consumption(queue: Queue[T]) -> bool:
36
+ return (
37
+ queue.qsize() != 0
38
+ ) # Queue size is not reliable, but should be sufficient for this case
@@ -70,12 +70,19 @@ class ApplicationContainer(containers.DeclarativeContainer):
70
70
  )
71
71
 
72
72
  # Storage
73
- local_storage = providers.Singleton(LocalStorage)
74
- blob_storage = providers.Singleton(BlobStorage, keyvault=keyvault)
75
- slimm_storage = providers.Singleton(
76
- SlimmStorage, request_handler=providers.Singleton(RequestHandler)
77
- )
78
- storage_handlers = providers.List(local_storage, blob_storage, slimm_storage)
73
+ storage_handlers_temp = []
74
+ if settings.STORAGE_LOCAL_ENABLED:
75
+ local_storage = providers.Singleton(LocalStorage)
76
+ storage_handlers_temp.append(local_storage)
77
+ if settings.STORAGE_BLOB_ENABLED:
78
+ blob_storage = providers.Singleton(BlobStorage, keyvault=keyvault)
79
+ storage_handlers_temp.append(blob_storage)
80
+ if settings.STORAGE_SLIMM_ENABLED:
81
+ slimm_storage = providers.Singleton(
82
+ SlimmStorage, request_handler=providers.Singleton(RequestHandler)
83
+ )
84
+ storage_handlers_temp.append(slimm_storage)
85
+ storage_handlers = providers.List(*storage_handlers_temp)
79
86
 
80
87
  # Mqtt client
81
88
  mqtt_client = (
@@ -11,11 +11,12 @@ from isar.models.communication.queues.events import (
11
11
  SharedState,
12
12
  StateMachineEvents,
13
13
  )
14
- from isar.models.communication.queues.queue_utils import check_for_event
14
+ from isar.models.communication.queues.queue_utils import check_for_event, trigger_event
15
15
  from isar.robot.robot_start_mission import RobotStartMissionThread
16
16
  from isar.robot.robot_status import RobotStatusThread
17
17
  from isar.robot.robot_stop_mission import RobotStopMissionThread
18
18
  from isar.robot.robot_task_status import RobotTaskStatusThread
19
+ from robot_interface.models.exceptions.robot_exceptions import ErrorMessage, ErrorReason
19
20
  from robot_interface.robot_interface import RobotInterface
20
21
 
21
22
 
@@ -94,6 +95,14 @@ class Robot(object):
94
95
  self.stop_mission_thread_thread is not None
95
96
  and self.start_mission_thread.is_alive()
96
97
  ):
98
+ error_description = "Received stop mission event while trying to start a mission. Aborting stop attempt."
99
+ error_message = ErrorMessage(
100
+ error_reason=ErrorReason.RobotStillStartingMissionException,
101
+ error_description=error_description,
102
+ )
103
+ trigger_event(
104
+ self.robot_service_events.mission_failed_to_stop, error_message
105
+ )
97
106
  return
98
107
  self.stop_mission_thread_thread = RobotStopMissionThread(
99
108
  self.robot_service_events, self.robot, self.signal_thread_quitting
@@ -5,6 +5,7 @@ from threading import Event, Thread
5
5
  from isar.config.settings import settings
6
6
  from isar.models.communication.queues.events import SharedState
7
7
  from isar.models.communication.queues.queue_utils import update_shared_state
8
+ from robot_interface.models.exceptions.robot_exceptions import RobotException
8
9
  from robot_interface.robot_interface import RobotInterface
9
10
 
10
11
 
@@ -19,7 +20,9 @@ class RobotStatusThread(Thread):
19
20
  self.shared_state: SharedState = shared_state
20
21
  self.robot: RobotInterface = robot
21
22
  self.signal_thread_quitting: Event = signal_thread_quitting
22
- self.last_robot_status_poll_time: float = time.time()
23
+ self.last_robot_status_poll_time: float = (
24
+ time.time() - settings.ROBOT_API_STATUS_POLL_INTERVAL
25
+ )
23
26
  Thread.__init__(self, name="Robot status thread")
24
27
 
25
28
  def stop(self) -> None:
@@ -40,9 +43,12 @@ class RobotStatusThread(Thread):
40
43
  while not self.signal_thread_quitting.wait(0.001):
41
44
  if not self._is_ready_to_poll_for_status():
42
45
  continue
46
+ try:
47
+ robot_status = self.robot.robot_status()
43
48
 
44
- robot_status = self.robot.robot_status()
45
-
46
- update_shared_state(self.shared_state.robot_status, robot_status)
47
- self.last_robot_status_poll_time = time.time()
49
+ update_shared_state(self.shared_state.robot_status, robot_status)
50
+ self.last_robot_status_poll_time = time.time()
51
+ except RobotException as e:
52
+ self.logger.error(f"Failed to retrieve robot status: {e}")
53
+ continue
48
54
  self.logger.info("Exiting robot status thread")
@@ -50,15 +50,15 @@ class RobotTaskStatusThread(Thread):
50
50
 
51
51
  try:
52
52
  task_status = self.robot.task_status(self.task_id)
53
- self.request_status_failure_counter = 0
53
+ request_status_failure_counter = 0
54
54
  except (
55
55
  RobotCommunicationTimeoutException,
56
56
  RobotCommunicationException,
57
57
  ) as e:
58
- self.request_status_failure_counter += 1
58
+ request_status_failure_counter += 1
59
59
  self.logger.error(
60
60
  f"Failed to get task status "
61
- f"{self.request_status_failure_counter} times because: "
61
+ f"{request_status_failure_counter} times because: "
62
62
  f"{e.error_description}"
63
63
  )
64
64
 
@@ -119,19 +119,47 @@ class SchedulingUtilities:
119
119
  return True
120
120
 
121
121
  def verify_state_machine_ready_to_receive_mission(self, state: States) -> bool:
122
- """Verify that the state machine is idle and ready to receive a mission
122
+ """Verify that the state machine is ready to receive a mission
123
123
 
124
124
  Raises
125
125
  ------
126
126
  HTTPException 409 Conflict
127
- If state machine is not idle and therefore can not start a new mission
127
+ If state machine is not home, robot standing still, awaiting next mission
128
+ or returning home and therefore cannot start a new mission
128
129
  """
129
- if state != States.Idle:
130
- error_message = f"Conflict - Robot is not idle - State: {state}"
131
- self.logger.warning(error_message)
132
- raise HTTPException(status_code=HTTPStatus.CONFLICT, detail=error_message)
130
+ if (
131
+ state == States.RobotStandingStill
132
+ or state == States.Home
133
+ or state == States.AwaitNextMission
134
+ or state == States.ReturningHome
135
+ ):
136
+ return True
133
137
 
134
- return True
138
+ error_message = f"Conflict - Robot is not home, robot standing still, awaiting next mission or returning home - State: {state}"
139
+ self.logger.warning(error_message)
140
+ raise HTTPException(status_code=HTTPStatus.CONFLICT, detail=error_message)
141
+
142
+ def verify_state_machine_ready_to_receive_return_home_mission(
143
+ self, state: States
144
+ ) -> bool:
145
+ """Verify that the state machine is ready to receive a return home mission
146
+
147
+ Raises
148
+ ------
149
+ HTTPException 409 Conflict
150
+ If state machine is not home, robot standing still or awaiting next mission
151
+ and therefore cannot start a new return home mission
152
+ """
153
+ if (
154
+ state == States.RobotStandingStill
155
+ or state == States.Home
156
+ or state == States.AwaitNextMission
157
+ ):
158
+ return True
159
+
160
+ error_message = f"Conflict - Robot is not home, robot standing still or awaiting next mission - State: {state}"
161
+ self.logger.warning(error_message)
162
+ raise HTTPException(status_code=HTTPStatus.CONFLICT, detail=error_message)
135
163
 
136
164
  def start_mission(
137
165
  self,
@@ -157,6 +185,31 @@ class SchedulingUtilities:
157
185
  )
158
186
  self.logger.info("OK - Mission started in ISAR")
159
187
 
188
+ def return_home(
189
+ self,
190
+ ) -> None:
191
+ """Start return home mission
192
+
193
+ Raises
194
+ ------
195
+ HTTTPException 408 Request timeout
196
+ If there is a timeout while communicating with the state machine
197
+ """
198
+ try:
199
+ self._send_command(
200
+ True,
201
+ self.api_events.return_home,
202
+ )
203
+ except QueueTimeoutError:
204
+ error_message = (
205
+ "Internal Server Error - Failed to start return home mission in ISAR"
206
+ )
207
+ self.logger.error(error_message)
208
+ raise HTTPException(
209
+ status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=error_message
210
+ )
211
+ self.logger.info("OK - Return home mission started in ISAR")
212
+
160
213
  def pause_mission(self) -> ControlMissionResponse:
161
214
  """Pause mission
162
215