isar 1.33.6__tar.gz → 1.33.7__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 (225) hide show
  1. {isar-1.33.6 → isar-1.33.7}/PKG-INFO +1 -1
  2. isar-1.33.7/docs/full_state_machine_diagram.png +0 -0
  3. isar-1.33.7/docs/mission_state_machine_diagram.png +0 -0
  4. isar-1.33.7/docs/robot_status_state_machine_diagram.png +0 -0
  5. {isar-1.33.6 → isar-1.33.7}/src/isar/config/settings.py +4 -0
  6. {isar-1.33.6 → isar-1.33.7}/src/isar/models/events.py +2 -0
  7. {isar-1.33.6 → isar-1.33.7}/src/isar/robot/robot.py +18 -1
  8. isar-1.33.6/src/isar/robot/robot_status.py → isar-1.33.7/src/isar/robot/robot_battery.py +17 -15
  9. isar-1.33.7/src/isar/robot/robot_status.py +71 -0
  10. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/states/blocked_protective_stop.py +9 -9
  11. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/states/home.py +21 -13
  12. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/states/offline.py +9 -10
  13. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/transitions/functions/robot_status.py +15 -0
  14. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/transitions/return_home.py +9 -0
  15. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/utils/common_event_handlers.py +5 -2
  16. {isar-1.33.6 → isar-1.33.7}/src/isar.egg-info/PKG-INFO +1 -1
  17. {isar-1.33.6 → isar-1.33.7}/src/isar.egg-info/SOURCES.txt +1 -0
  18. {isar-1.33.6 → isar-1.33.7}/tests/isar/state_machine/test_state_machine.py +22 -4
  19. {isar-1.33.6 → isar-1.33.7}/tests/test_double/robot_interface.py +38 -1
  20. isar-1.33.6/docs/full_state_machine_diagram.png +0 -0
  21. isar-1.33.6/docs/mission_state_machine_diagram.png +0 -0
  22. isar-1.33.6/docs/robot_status_state_machine_diagram.png +0 -0
  23. {isar-1.33.6 → isar-1.33.7}/.dockerignore +0 -0
  24. {isar-1.33.6 → isar-1.33.7}/.env.test +0 -0
  25. {isar-1.33.6 → isar-1.33.7}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  26. {isar-1.33.6 → isar-1.33.7}/.github/ISSUE_TEMPLATE/feature.md +0 -0
  27. {isar-1.33.6 → isar-1.33.7}/.github/ISSUE_TEMPLATE/improvement.md +0 -0
  28. {isar-1.33.6 → isar-1.33.7}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  29. {isar-1.33.6 → isar-1.33.7}/.github/release.yml +0 -0
  30. {isar-1.33.6 → isar-1.33.7}/.github/workflows/compile_requirements.yml +0 -0
  31. {isar-1.33.6 → isar-1.33.7}/.github/workflows/project_automations.yml +0 -0
  32. {isar-1.33.6 → isar-1.33.7}/.github/workflows/pythonpackage.yml +0 -0
  33. {isar-1.33.6 → isar-1.33.7}/.github/workflows/pythonpublish.yml +0 -0
  34. {isar-1.33.6 → isar-1.33.7}/.github/workflows/stale.yml +0 -0
  35. {isar-1.33.6 → isar-1.33.7}/.gitignore +0 -0
  36. {isar-1.33.6 → isar-1.33.7}/.pre-commit-config.yaml +0 -0
  37. {isar-1.33.6 → isar-1.33.7}/LICENSE +0 -0
  38. {isar-1.33.6 → isar-1.33.7}/README.md +0 -0
  39. {isar-1.33.6 → isar-1.33.7}/SECURITY.md +0 -0
  40. {isar-1.33.6 → isar-1.33.7}/docs/Makefile +0 -0
  41. {isar-1.33.6 → isar-1.33.7}/docs/make.bat +0 -0
  42. {isar-1.33.6 → isar-1.33.7}/docs/rst_processing.py +0 -0
  43. {isar-1.33.6 → isar-1.33.7}/docs/source/conf.py +0 -0
  44. {isar-1.33.6 → isar-1.33.7}/docs/source/index.rst +0 -0
  45. {isar-1.33.6 → isar-1.33.7}/docs/source/readme_link.md +0 -0
  46. {isar-1.33.6 → isar-1.33.7}/docs/update_state_diagram.py +0 -0
  47. {isar-1.33.6 → isar-1.33.7}/main.py +0 -0
  48. {isar-1.33.6 → isar-1.33.7}/pyproject.toml +0 -0
  49. {isar-1.33.6 → isar-1.33.7}/radixconfig.yml +0 -0
  50. {isar-1.33.6 → isar-1.33.7}/requirements.txt +0 -0
  51. {isar-1.33.6 → isar-1.33.7}/setup.cfg +0 -0
  52. {isar-1.33.6 → isar-1.33.7}/src/isar/__init__.py +0 -0
  53. {isar-1.33.6 → isar-1.33.7}/src/isar/apis/__init__.py +0 -0
  54. {isar-1.33.6 → isar-1.33.7}/src/isar/apis/api.py +0 -0
  55. {isar-1.33.6 → isar-1.33.7}/src/isar/apis/models/__init__.py +0 -0
  56. {isar-1.33.6 → isar-1.33.7}/src/isar/apis/models/models.py +0 -0
  57. {isar-1.33.6 → isar-1.33.7}/src/isar/apis/models/start_mission_definition.py +0 -0
  58. {isar-1.33.6 → isar-1.33.7}/src/isar/apis/robot_control/robot_controller.py +0 -0
  59. {isar-1.33.6 → isar-1.33.7}/src/isar/apis/schedule/__init__.py +0 -0
  60. {isar-1.33.6 → isar-1.33.7}/src/isar/apis/schedule/scheduling_controller.py +0 -0
  61. {isar-1.33.6 → isar-1.33.7}/src/isar/apis/security/__init__.py +0 -0
  62. {isar-1.33.6 → isar-1.33.7}/src/isar/apis/security/authentication.py +0 -0
  63. {isar-1.33.6 → isar-1.33.7}/src/isar/config/__init__.py +0 -0
  64. {isar-1.33.6 → isar-1.33.7}/src/isar/config/certs/ca-cert.pem +0 -0
  65. {isar-1.33.6 → isar-1.33.7}/src/isar/config/configuration_error.py +0 -0
  66. {isar-1.33.6 → isar-1.33.7}/src/isar/config/keyvault/__init__.py +0 -0
  67. {isar-1.33.6 → isar-1.33.7}/src/isar/config/keyvault/keyvault_error.py +0 -0
  68. {isar-1.33.6 → isar-1.33.7}/src/isar/config/keyvault/keyvault_service.py +0 -0
  69. {isar-1.33.6 → isar-1.33.7}/src/isar/config/log.py +0 -0
  70. {isar-1.33.6 → isar-1.33.7}/src/isar/config/logging.conf +0 -0
  71. {isar-1.33.6 → isar-1.33.7}/src/isar/config/maps/JSP1_intermediate_deck.json +0 -0
  72. {isar-1.33.6 → isar-1.33.7}/src/isar/config/maps/JSP1_weather_deck.json +0 -0
  73. {isar-1.33.6 → isar-1.33.7}/src/isar/config/maps/default_map.json +0 -0
  74. {isar-1.33.6 → isar-1.33.7}/src/isar/config/maps/klab_b.json +0 -0
  75. {isar-1.33.6 → isar-1.33.7}/src/isar/config/maps/klab_compressor.json +0 -0
  76. {isar-1.33.6 → isar-1.33.7}/src/isar/config/maps/klab_turtlebot.json +0 -0
  77. {isar-1.33.6 → isar-1.33.7}/src/isar/config/maps/turtleworld.json +0 -0
  78. {isar-1.33.6 → isar-1.33.7}/src/isar/config/open_telemetry.py +0 -0
  79. {isar-1.33.6 → isar-1.33.7}/src/isar/config/predefined_mission_definition/__init__.py +0 -0
  80. {isar-1.33.6 → isar-1.33.7}/src/isar/config/predefined_mission_definition/default_exr.json +0 -0
  81. {isar-1.33.6 → isar-1.33.7}/src/isar/config/predefined_mission_definition/default_mission.json +0 -0
  82. {isar-1.33.6 → isar-1.33.7}/src/isar/config/predefined_mission_definition/default_turtlebot.json +0 -0
  83. {isar-1.33.6 → isar-1.33.7}/src/isar/config/predefined_missions/__init__.py +0 -0
  84. {isar-1.33.6 → isar-1.33.7}/src/isar/config/predefined_missions/default.json +0 -0
  85. {isar-1.33.6 → isar-1.33.7}/src/isar/config/predefined_missions/default_turtlebot.json +0 -0
  86. {isar-1.33.6 → isar-1.33.7}/src/isar/eventhandlers/eventhandler.py +0 -0
  87. {isar-1.33.6 → isar-1.33.7}/src/isar/mission_planner/__init__.py +0 -0
  88. {isar-1.33.6 → isar-1.33.7}/src/isar/mission_planner/local_planner.py +0 -0
  89. {isar-1.33.6 → isar-1.33.7}/src/isar/mission_planner/mission_planner_interface.py +0 -0
  90. {isar-1.33.6 → isar-1.33.7}/src/isar/mission_planner/sequential_task_selector.py +0 -0
  91. {isar-1.33.6 → isar-1.33.7}/src/isar/mission_planner/task_selector_interface.py +0 -0
  92. {isar-1.33.6 → isar-1.33.7}/src/isar/models/__init__.py +0 -0
  93. {isar-1.33.6 → isar-1.33.7}/src/isar/modules.py +0 -0
  94. {isar-1.33.6 → isar-1.33.7}/src/isar/robot/robot_pause_mission.py +0 -0
  95. {isar-1.33.6 → isar-1.33.7}/src/isar/robot/robot_start_mission.py +0 -0
  96. {isar-1.33.6 → isar-1.33.7}/src/isar/robot/robot_stop_mission.py +0 -0
  97. {isar-1.33.6 → isar-1.33.7}/src/isar/robot/robot_task_status.py +0 -0
  98. {isar-1.33.6 → isar-1.33.7}/src/isar/script.py +0 -0
  99. {isar-1.33.6 → isar-1.33.7}/src/isar/services/__init__.py +0 -0
  100. {isar-1.33.6 → isar-1.33.7}/src/isar/services/auth/__init__.py +0 -0
  101. {isar-1.33.6 → isar-1.33.7}/src/isar/services/auth/azure_credentials.py +0 -0
  102. {isar-1.33.6 → isar-1.33.7}/src/isar/services/service_connections/__init__.py +0 -0
  103. {isar-1.33.6 → isar-1.33.7}/src/isar/services/service_connections/mqtt/__init__.py +0 -0
  104. {isar-1.33.6 → isar-1.33.7}/src/isar/services/service_connections/mqtt/mqtt_client.py +0 -0
  105. {isar-1.33.6 → isar-1.33.7}/src/isar/services/service_connections/mqtt/robot_heartbeat_publisher.py +0 -0
  106. {isar-1.33.6 → isar-1.33.7}/src/isar/services/service_connections/mqtt/robot_info_publisher.py +0 -0
  107. {isar-1.33.6 → isar-1.33.7}/src/isar/services/service_connections/request_handler.py +0 -0
  108. {isar-1.33.6 → isar-1.33.7}/src/isar/services/utilities/__init__.py +0 -0
  109. {isar-1.33.6 → isar-1.33.7}/src/isar/services/utilities/robot_utilities.py +0 -0
  110. {isar-1.33.6 → isar-1.33.7}/src/isar/services/utilities/scheduling_utilities.py +0 -0
  111. {isar-1.33.6 → isar-1.33.7}/src/isar/services/utilities/threaded_request.py +0 -0
  112. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/__init__.py +0 -0
  113. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/state_machine.py +0 -0
  114. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/states/__init__.py +0 -0
  115. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/states/await_next_mission.py +0 -0
  116. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/states/going_to_lockdown.py +0 -0
  117. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/states/intervention_needed.py +0 -0
  118. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/states/lockdown.py +0 -0
  119. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/states/monitor.py +0 -0
  120. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/states/paused.py +0 -0
  121. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/states/pausing.py +0 -0
  122. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/states/pausing_return_home.py +0 -0
  123. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/states/recharging.py +0 -0
  124. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/states/return_home_paused.py +0 -0
  125. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/states/returning_home.py +0 -0
  126. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/states/stopping.py +0 -0
  127. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/states/stopping_go_to_lockdown.py +0 -0
  128. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/states/stopping_return_home.py +0 -0
  129. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/states/unknown_status.py +0 -0
  130. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/states_enum.py +0 -0
  131. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/transitions/functions/fail_mission.py +0 -0
  132. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/transitions/functions/finish_mission.py +0 -0
  133. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/transitions/functions/pause.py +0 -0
  134. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/transitions/functions/resume.py +0 -0
  135. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/transitions/functions/return_home.py +0 -0
  136. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/transitions/functions/start_mission.py +0 -0
  137. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/transitions/functions/stop.py +0 -0
  138. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/transitions/functions/utils.py +0 -0
  139. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/transitions/mission.py +0 -0
  140. {isar-1.33.6 → isar-1.33.7}/src/isar/state_machine/transitions/robot_status.py +0 -0
  141. {isar-1.33.6 → isar-1.33.7}/src/isar/storage/__init__.py +0 -0
  142. {isar-1.33.6 → isar-1.33.7}/src/isar/storage/blob_storage.py +0 -0
  143. {isar-1.33.6 → isar-1.33.7}/src/isar/storage/local_storage.py +0 -0
  144. {isar-1.33.6 → isar-1.33.7}/src/isar/storage/storage_interface.py +0 -0
  145. {isar-1.33.6 → isar-1.33.7}/src/isar/storage/uploader.py +0 -0
  146. {isar-1.33.6 → isar-1.33.7}/src/isar/storage/utilities.py +0 -0
  147. {isar-1.33.6 → isar-1.33.7}/src/isar.egg-info/dependency_links.txt +0 -0
  148. {isar-1.33.6 → isar-1.33.7}/src/isar.egg-info/entry_points.txt +0 -0
  149. {isar-1.33.6 → isar-1.33.7}/src/isar.egg-info/requires.txt +0 -0
  150. {isar-1.33.6 → isar-1.33.7}/src/isar.egg-info/top_level.txt +0 -0
  151. {isar-1.33.6 → isar-1.33.7}/src/robot_interface/__init__.py +0 -0
  152. {isar-1.33.6 → isar-1.33.7}/src/robot_interface/models/__init__.py +0 -0
  153. {isar-1.33.6 → isar-1.33.7}/src/robot_interface/models/exceptions/__init__.py +0 -0
  154. {isar-1.33.6 → isar-1.33.7}/src/robot_interface/models/exceptions/robot_exceptions.py +0 -0
  155. {isar-1.33.6 → isar-1.33.7}/src/robot_interface/models/initialize/__init__.py +0 -0
  156. {isar-1.33.6 → isar-1.33.7}/src/robot_interface/models/inspection/__init__.py +0 -0
  157. {isar-1.33.6 → isar-1.33.7}/src/robot_interface/models/inspection/inspection.py +0 -0
  158. {isar-1.33.6 → isar-1.33.7}/src/robot_interface/models/mission/__init__.py +0 -0
  159. {isar-1.33.6 → isar-1.33.7}/src/robot_interface/models/mission/mission.py +0 -0
  160. {isar-1.33.6 → isar-1.33.7}/src/robot_interface/models/mission/status.py +0 -0
  161. {isar-1.33.6 → isar-1.33.7}/src/robot_interface/models/mission/task.py +0 -0
  162. {isar-1.33.6 → isar-1.33.7}/src/robot_interface/models/robots/__init__.py +0 -0
  163. {isar-1.33.6 → isar-1.33.7}/src/robot_interface/models/robots/battery_state.py +0 -0
  164. {isar-1.33.6 → isar-1.33.7}/src/robot_interface/models/robots/media.py +0 -0
  165. {isar-1.33.6 → isar-1.33.7}/src/robot_interface/models/robots/robot_model.py +0 -0
  166. {isar-1.33.6 → isar-1.33.7}/src/robot_interface/robot_interface.py +0 -0
  167. {isar-1.33.6 → isar-1.33.7}/src/robot_interface/telemetry/__init__.py +0 -0
  168. {isar-1.33.6 → isar-1.33.7}/src/robot_interface/telemetry/mqtt_client.py +0 -0
  169. {isar-1.33.6 → isar-1.33.7}/src/robot_interface/telemetry/payloads.py +0 -0
  170. {isar-1.33.6 → isar-1.33.7}/src/robot_interface/test_robot_interface.py +0 -0
  171. {isar-1.33.6 → isar-1.33.7}/src/robot_interface/utilities/__init__.py +0 -0
  172. {isar-1.33.6 → isar-1.33.7}/src/robot_interface/utilities/json_service.py +0 -0
  173. {isar-1.33.6 → isar-1.33.7}/src/robot_interface/utilities/uuid_string_factory.py +0 -0
  174. {isar-1.33.6 → isar-1.33.7}/tests/__init__.py +0 -0
  175. {isar-1.33.6 → isar-1.33.7}/tests/conftest.py +0 -0
  176. {isar-1.33.6 → isar-1.33.7}/tests/integration/__init__.py +0 -0
  177. {isar-1.33.6 → isar-1.33.7}/tests/integration/turtlebot/__init__.py +0 -0
  178. {isar-1.33.6 → isar-1.33.7}/tests/integration/turtlebot/config/__init__.py +0 -0
  179. {isar-1.33.6 → isar-1.33.7}/tests/integration/turtlebot/config/maps/__init__.py +0 -0
  180. {isar-1.33.6 → isar-1.33.7}/tests/integration/turtlebot/config/maps/turtleworld.json +0 -0
  181. {isar-1.33.6 → isar-1.33.7}/tests/integration/turtlebot/config/missions/__init__.py +0 -0
  182. {isar-1.33.6 → isar-1.33.7}/tests/integration/turtlebot/config/missions/default.json +0 -0
  183. {isar-1.33.6 → isar-1.33.7}/tests/integration/turtlebot/test_successful_mission.py +0 -0
  184. {isar-1.33.6 → isar-1.33.7}/tests/isar/__init__.py +0 -0
  185. {isar-1.33.6 → isar-1.33.7}/tests/isar/apis/__init__.py +0 -0
  186. {isar-1.33.6 → isar-1.33.7}/tests/isar/apis/models/__init__.py +0 -0
  187. {isar-1.33.6 → isar-1.33.7}/tests/isar/apis/models/example_mission_definition.json +0 -0
  188. {isar-1.33.6 → isar-1.33.7}/tests/isar/apis/models/test_start_mission_definition.py +0 -0
  189. {isar-1.33.6 → isar-1.33.7}/tests/isar/apis/scheduler/__init__.py +0 -0
  190. {isar-1.33.6 → isar-1.33.7}/tests/isar/apis/scheduler/test_scheduler_router.py +0 -0
  191. {isar-1.33.6 → isar-1.33.7}/tests/isar/apis/security/__init__.py +0 -0
  192. {isar-1.33.6 → isar-1.33.7}/tests/isar/apis/security/test_authentication.py +0 -0
  193. {isar-1.33.6 → isar-1.33.7}/tests/isar/mission/__init__.py +0 -0
  194. {isar-1.33.6 → isar-1.33.7}/tests/isar/mission/test_mission.py +0 -0
  195. {isar-1.33.6 → isar-1.33.7}/tests/isar/models/__init__.py +0 -0
  196. {isar-1.33.6 → isar-1.33.7}/tests/isar/models/communication/__init__.py +0 -0
  197. {isar-1.33.6 → isar-1.33.7}/tests/isar/models/communication/test_events.py +0 -0
  198. {isar-1.33.6 → isar-1.33.7}/tests/isar/services/__init__.py +0 -0
  199. {isar-1.33.6 → isar-1.33.7}/tests/isar/services/readers/__init__.py +0 -0
  200. {isar-1.33.6 → isar-1.33.7}/tests/isar/services/readers/test_mission_reader.py +0 -0
  201. {isar-1.33.6 → isar-1.33.7}/tests/isar/services/service_connections/__init__.py +0 -0
  202. {isar-1.33.6 → isar-1.33.7}/tests/isar/services/service_connections/echo/__init__.py +0 -0
  203. {isar-1.33.6 → isar-1.33.7}/tests/isar/services/service_connections/test_base_request_handler.py +0 -0
  204. {isar-1.33.6 → isar-1.33.7}/tests/isar/services/utilities/__init__.py +0 -0
  205. {isar-1.33.6 → isar-1.33.7}/tests/isar/services/utilities/test_queue_utilities.py +0 -0
  206. {isar-1.33.6 → isar-1.33.7}/tests/isar/services/utilities/test_scheduling_utilities.py +0 -0
  207. {isar-1.33.6 → isar-1.33.7}/tests/isar/state_machine/__init__.py +0 -0
  208. {isar-1.33.6 → isar-1.33.7}/tests/isar/state_machine/states/__init__.py +0 -0
  209. {isar-1.33.6 → isar-1.33.7}/tests/isar/state_machine/states/test_monitor.py +0 -0
  210. {isar-1.33.6 → isar-1.33.7}/tests/isar/storage/test_blob_storage.py +0 -0
  211. {isar-1.33.6 → isar-1.33.7}/tests/isar/storage/test_uploader.py +0 -0
  212. {isar-1.33.6 → isar-1.33.7}/tests/test_data/test_map_config/test_map_config.json +0 -0
  213. {isar-1.33.6 → isar-1.33.7}/tests/test_data/test_mission_not_working.json +0 -0
  214. {isar-1.33.6 → isar-1.33.7}/tests/test_data/test_mission_working.json +0 -0
  215. {isar-1.33.6 → isar-1.33.7}/tests/test_data/test_mission_working_no_tasks.json +0 -0
  216. {isar-1.33.6 → isar-1.33.7}/tests/test_data/test_thermal_image_mission.json +0 -0
  217. {isar-1.33.6 → isar-1.33.7}/tests/test_double/__init__.py +0 -0
  218. {isar-1.33.6 → isar-1.33.7}/tests/test_double/blob_storage.py +0 -0
  219. {isar-1.33.6 → isar-1.33.7}/tests/test_double/mission_definition.py +0 -0
  220. {isar-1.33.6 → isar-1.33.7}/tests/test_double/mqtt_client.py +0 -0
  221. {isar-1.33.6 → isar-1.33.7}/tests/test_double/pose.py +0 -0
  222. {isar-1.33.6 → isar-1.33.7}/tests/test_double/request.py +0 -0
  223. {isar-1.33.6 → isar-1.33.7}/tests/test_double/status.py +0 -0
  224. {isar-1.33.6 → isar-1.33.7}/tests/test_double/task.py +0 -0
  225. {isar-1.33.6 → isar-1.33.7}/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.6
3
+ Version: 1.33.7
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
@@ -59,6 +59,9 @@ 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
+
62
65
  # Number of attempts for state transitions resume and pause if failed
63
66
  STATE_TRANSITION_NUM_RETIRES: int = Field(default=10)
64
67
 
@@ -78,6 +81,7 @@ class Settings(BaseSettings):
78
81
  ROBOT_STATUS_PUBLISH_INTERVAL: float = Field(default=1)
79
82
  ROBOT_HEARTBEAT_PUBLISH_INTERVAL: float = Field(default=1)
80
83
  ROBOT_INFO_PUBLISH_INTERVAL: float = Field(default=5)
84
+ ROBOT_API_BATTERY_POLL_INTERVAL: float = Field(default=5)
81
85
  ROBOT_API_STATUS_POLL_INTERVAL: float = Field(default=5)
82
86
  THREAD_CHECK_INTERVAL: float = Field(default=0.01)
83
87
 
@@ -123,6 +123,7 @@ class StateMachineEvents:
123
123
  self.stop_mission: Event[bool] = Event("stop_mission")
124
124
  self.pause_mission: Event[bool] = Event("pause_mission")
125
125
  self.task_status_request: Event[str] = Event("task_status_request")
126
+ self.clear_robot_status: Event[bool] = Event("clear_robot_status")
126
127
 
127
128
 
128
129
  class RobotServiceEvents:
@@ -132,6 +133,7 @@ class RobotServiceEvents:
132
133
  self.mission_started: Event[bool] = Event("mission_started")
133
134
  self.mission_failed: Event[ErrorMessage] = Event("mission_failed")
134
135
  self.robot_status_changed: Event[bool] = Event("robot_status_changed")
136
+ self.robot_status_cleared: Event[bool] = Event("robot_status_cleared")
135
137
  self.mission_failed_to_stop: Event[ErrorMessage] = Event(
136
138
  "mission_failed_to_stop"
137
139
  )
@@ -9,6 +9,7 @@ from isar.models.events import (
9
9
  SharedState,
10
10
  StateMachineEvents,
11
11
  )
12
+ from isar.robot.robot_battery import RobotBatteryThread
12
13
  from isar.robot.robot_pause_mission import RobotPauseMissionThread
13
14
  from isar.robot.robot_start_mission import RobotStartMissionThread
14
15
  from isar.robot.robot_status import RobotStatusThread
@@ -29,6 +30,7 @@ class Robot(object):
29
30
  self.shared_state: SharedState = shared_state
30
31
  self.robot: RobotInterface = robot
31
32
  self.start_mission_thread: Optional[RobotStartMissionThread] = None
33
+ self.robot_battery_thread: Optional[RobotBatteryThread] = None
32
34
  self.robot_status_thread: Optional[RobotStatusThread] = None
33
35
  self.robot_task_status_thread: Optional[RobotTaskStatusThread] = None
34
36
  self.stop_mission_thread: Optional[RobotStopMissionThread] = None
@@ -39,6 +41,11 @@ class Robot(object):
39
41
  self.signal_thread_quitting.set()
40
42
  if self.robot_status_thread is not None and self.robot_status_thread.is_alive():
41
43
  self.robot_status_thread.join()
44
+ if (
45
+ self.robot_battery_thread is not None
46
+ and self.robot_battery_thread.is_alive()
47
+ ):
48
+ self.robot_battery_thread.join()
42
49
  if (
43
50
  self.robot_task_status_thread is not None
44
51
  and self.robot_task_status_thread.is_alive()
@@ -52,6 +59,7 @@ class Robot(object):
52
59
  if self.stop_mission_thread is not None and self.stop_mission_thread.is_alive():
53
60
  self.stop_mission_thread.join()
54
61
  self.robot_status_thread = None
62
+ self.robot_battery_thread = None
55
63
  self.robot_task_status_thread = None
56
64
  self.start_mission_thread = None
57
65
 
@@ -143,10 +151,19 @@ class Robot(object):
143
151
 
144
152
  def run(self) -> None:
145
153
  self.robot_status_thread = RobotStatusThread(
146
- self.robot, self.signal_thread_quitting, self.shared_state
154
+ robot=self.robot,
155
+ signal_thread_quitting=self.signal_thread_quitting,
156
+ shared_state=self.shared_state,
157
+ state_machine_events=self.state_machine_events,
158
+ robot_service_events=self.robot_service_events,
147
159
  )
148
160
  self.robot_status_thread.start()
149
161
 
162
+ self.robot_battery_thread = RobotBatteryThread(
163
+ self.robot, self.signal_thread_quitting, self.shared_state
164
+ )
165
+ self.robot_battery_thread.start()
166
+
150
167
  while not self.signal_thread_quitting.wait(0):
151
168
  self._start_mission_event_handler(self.state_machine_events.start_mission)
152
169
 
@@ -8,7 +8,7 @@ from robot_interface.models.exceptions.robot_exceptions import RobotException
8
8
  from robot_interface.robot_interface import RobotInterface
9
9
 
10
10
 
11
- class RobotStatusThread(Thread):
11
+ class RobotBatteryThread(Thread):
12
12
  def __init__(
13
13
  self,
14
14
  robot: RobotInterface,
@@ -19,20 +19,24 @@ class RobotStatusThread(Thread):
19
19
  self.shared_state: SharedState = shared_state
20
20
  self.robot: RobotInterface = robot
21
21
  self.signal_thread_quitting: Event = signal_thread_quitting
22
- self.last_robot_status_poll_time: float = (
23
- time.time() - settings.ROBOT_API_STATUS_POLL_INTERVAL
24
- )
25
- Thread.__init__(self, name="Robot status thread")
22
+ self.last_robot_battery_poll_time: float = time.time()
23
+ self.force_battery_poll_next_iteration: bool = True
24
+ Thread.__init__(self, name="Robot battery thread")
26
25
 
27
26
  def stop(self) -> None:
28
27
  return
29
28
 
30
- def _is_ready_to_poll_for_status(self) -> bool:
31
- time_since_last_robot_status_poll = (
32
- time.time() - self.last_robot_status_poll_time
29
+ def _is_ready_to_poll_for_battery(self) -> bool:
30
+ if self.force_battery_poll_next_iteration:
31
+ self.force_battery_poll_next_iteration = False
32
+ return True
33
+
34
+ time_since_last_robot_battery_poll = (
35
+ time.time() - self.last_robot_battery_poll_time
33
36
  )
34
37
  return (
35
- time_since_last_robot_status_poll > settings.ROBOT_API_STATUS_POLL_INTERVAL
38
+ time_since_last_robot_battery_poll
39
+ > settings.ROBOT_API_BATTERY_POLL_INTERVAL
36
40
  )
37
41
 
38
42
  def run(self):
@@ -42,17 +46,15 @@ class RobotStatusThread(Thread):
42
46
  thread_check_interval = settings.THREAD_CHECK_INTERVAL
43
47
 
44
48
  while not self.signal_thread_quitting.wait(thread_check_interval):
45
- if not self._is_ready_to_poll_for_status():
49
+ if not self._is_ready_to_poll_for_battery():
46
50
  continue
47
51
  try:
48
- self.last_robot_status_poll_time = time.time()
52
+ self.last_robot_battery_poll_time = time.time()
49
53
 
50
- robot_status = self.robot.robot_status()
51
54
  robot_battery_level = self.robot.get_battery_level()
52
55
 
53
- self.shared_state.robot_status.update(robot_status)
54
56
  self.shared_state.robot_battery_level.update(robot_battery_level)
55
57
  except RobotException as e:
56
- self.logger.error(f"Failed to retrieve robot status: {e}")
58
+ self.logger.error(f"Failed to retrieve robot battery level: {e}")
57
59
  continue
58
- self.logger.info("Exiting robot status thread")
60
+ self.logger.info("Exiting robot battery thread")
@@ -0,0 +1,71 @@
1
+ import logging
2
+ import time
3
+ from threading import Event, Thread
4
+
5
+ from isar.config.settings import settings
6
+ from isar.models.events import RobotServiceEvents, SharedState, StateMachineEvents
7
+ from robot_interface.models.exceptions.robot_exceptions import RobotException
8
+ from robot_interface.robot_interface import RobotInterface
9
+
10
+
11
+ class RobotStatusThread(Thread):
12
+ def __init__(
13
+ self,
14
+ robot: RobotInterface,
15
+ signal_thread_quitting: Event,
16
+ shared_state: SharedState,
17
+ robot_service_events: RobotServiceEvents,
18
+ state_machine_events: StateMachineEvents,
19
+ ):
20
+ self.logger = logging.getLogger("robot")
21
+ self.shared_state: SharedState = shared_state
22
+ self.robot_service_events: RobotServiceEvents = robot_service_events
23
+ self.state_machine_events: StateMachineEvents = state_machine_events
24
+ self.robot: RobotInterface = robot
25
+ self.signal_thread_quitting: Event = signal_thread_quitting
26
+ self.robot_status_poll_interval: float = settings.ROBOT_API_STATUS_POLL_INTERVAL
27
+ self.last_robot_status_poll_time: float = time.time()
28
+ self.force_status_poll_next_iteration: bool = True
29
+ Thread.__init__(self, name="Robot status thread")
30
+
31
+ def stop(self) -> None:
32
+ return
33
+
34
+ def _is_ready_to_poll_for_status(self) -> bool:
35
+ if self.force_status_poll_next_iteration:
36
+ self.force_status_poll_next_iteration = False
37
+ return True
38
+
39
+ time_since_last_robot_status_poll = (
40
+ time.time() - self.last_robot_status_poll_time
41
+ )
42
+ return time_since_last_robot_status_poll > self.robot_status_poll_interval
43
+
44
+ def run(self):
45
+ if self.signal_thread_quitting.is_set():
46
+ return
47
+
48
+ thread_check_interval = settings.THREAD_CHECK_INTERVAL
49
+
50
+ while not self.signal_thread_quitting.wait(thread_check_interval):
51
+ if self.state_machine_events.clear_robot_status.consume_event() is not None:
52
+ self.shared_state.robot_status.clear_event()
53
+ self.robot_service_events.robot_status_changed.clear_event()
54
+ self.robot_service_events.robot_status_cleared.trigger_event(True)
55
+ self.force_status_poll_next_iteration = True
56
+
57
+ if not self._is_ready_to_poll_for_status():
58
+ continue
59
+
60
+ try:
61
+ self.last_robot_status_poll_time = time.time()
62
+
63
+ robot_status = self.robot.robot_status()
64
+
65
+ if robot_status is not self.shared_state.robot_status.check():
66
+ self.shared_state.robot_status.update(robot_status)
67
+ self.robot_service_events.robot_status_changed.trigger_event(True)
68
+ except RobotException as e:
69
+ self.logger.error(f"Failed to retrieve robot status: {e}")
70
+ continue
71
+ self.logger.info("Exiting robot status thread")
@@ -1,7 +1,7 @@
1
1
  from typing import TYPE_CHECKING, List
2
2
 
3
3
  from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
4
- from isar.models.events import Event
4
+ from isar.state_machine.utils.common_event_handlers import robot_status_event_handler
5
5
  from robot_interface.models.mission.status import RobotStatus
6
6
 
7
7
  if TYPE_CHECKING:
@@ -11,19 +11,19 @@ if TYPE_CHECKING:
11
11
  class BlockedProtectiveStop(EventHandlerBase):
12
12
 
13
13
  def __init__(self, state_machine: "StateMachine"):
14
+ events = state_machine.events
14
15
  shared_state = state_machine.shared_state
15
16
 
16
- def _robot_status_event_handler(event: Event[RobotStatus]):
17
- robot_status: RobotStatus = event.check()
18
- if robot_status != RobotStatus.BlockedProtectiveStop:
19
- return state_machine.robot_status_changed # type: ignore
20
- return None
21
-
22
17
  event_handlers: List[EventHandlerMapping] = [
23
18
  EventHandlerMapping(
24
19
  name="robot_status_event",
25
- event=shared_state.robot_status,
26
- handler=_robot_status_event_handler,
20
+ event=events.robot_service_events.robot_status_changed,
21
+ handler=lambda event: robot_status_event_handler(
22
+ state_machine=state_machine,
23
+ expected_status=RobotStatus.BlockedProtectiveStop,
24
+ status_changed_event=event,
25
+ status_event=shared_state.robot_status,
26
+ ),
27
27
  ),
28
28
  ]
29
29
  super().__init__(
@@ -20,17 +20,6 @@ class Home(EventHandlerBase):
20
20
  events = state_machine.events
21
21
  shared_state = state_machine.shared_state
22
22
 
23
- def _robot_status_event_handler(
24
- event: Event[RobotStatus],
25
- ) -> Optional[Callable]:
26
- robot_status: RobotStatus = event.check()
27
- if not (
28
- robot_status == RobotStatus.Available
29
- or robot_status == RobotStatus.Home
30
- ):
31
- return state_machine.robot_status_changed # type: ignore
32
- return None
33
-
34
23
  def _send_to_lockdown_event_handler(event: Event[bool]):
35
24
  should_send_robot_home: bool = event.consume_event()
36
25
  if should_send_robot_home:
@@ -40,6 +29,21 @@ class Home(EventHandlerBase):
40
29
  return state_machine.reached_lockdown # type: ignore
41
30
  return None
42
31
 
32
+ def _robot_status_event_handler(
33
+ state_machine: "StateMachine",
34
+ status_changed_event: Event[bool],
35
+ status_event: Event[RobotStatus],
36
+ ) -> Optional[Callable]:
37
+ if not status_changed_event.consume_event():
38
+ return None
39
+ robot_status: Optional[RobotStatus] = status_event.check()
40
+ if not (
41
+ robot_status == RobotStatus.Available
42
+ or robot_status == RobotStatus.Home
43
+ ):
44
+ return state_machine.robot_status_changed # type: ignore
45
+ return None
46
+
43
47
  event_handlers: List[EventHandlerMapping] = [
44
48
  EventHandlerMapping(
45
49
  name="start_mission_event",
@@ -60,8 +64,12 @@ class Home(EventHandlerBase):
60
64
  ),
61
65
  EventHandlerMapping(
62
66
  name="robot_status_event",
63
- event=shared_state.robot_status,
64
- handler=_robot_status_event_handler,
67
+ event=events.robot_service_events.robot_status_changed,
68
+ handler=lambda event: _robot_status_event_handler(
69
+ state_machine=state_machine,
70
+ status_changed_event=event,
71
+ status_event=shared_state.robot_status,
72
+ ),
65
73
  ),
66
74
  EventHandlerMapping(
67
75
  name="send_to_lockdown_event",
@@ -1,7 +1,7 @@
1
1
  from typing import TYPE_CHECKING, List
2
2
 
3
3
  from isar.eventhandlers.eventhandler import EventHandlerBase, EventHandlerMapping
4
- from isar.models.events import Event
4
+ from isar.state_machine.utils.common_event_handlers import robot_status_event_handler
5
5
  from robot_interface.models.mission.status import RobotStatus
6
6
 
7
7
  if TYPE_CHECKING:
@@ -11,20 +11,19 @@ if TYPE_CHECKING:
11
11
  class Offline(EventHandlerBase):
12
12
 
13
13
  def __init__(self, state_machine: "StateMachine"):
14
-
14
+ events = state_machine.events
15
15
  shared_state = state_machine.shared_state
16
16
 
17
- def _robot_status_event_handler(event: Event[RobotStatus]):
18
- robot_status: RobotStatus = event.check()
19
- if robot_status != RobotStatus.Offline:
20
- return state_machine.robot_status_changed # type: ignore
21
- return None
22
-
23
17
  event_handlers: List[EventHandlerMapping] = [
24
18
  EventHandlerMapping(
25
19
  name="robot_status_event",
26
- event=shared_state.robot_status,
27
- handler=_robot_status_event_handler,
20
+ event=events.robot_service_events.robot_status_changed,
21
+ handler=lambda event: robot_status_event_handler(
22
+ state_machine=state_machine,
23
+ expected_status=RobotStatus.Offline,
24
+ status_changed_event=event,
25
+ status_event=shared_state.robot_status,
26
+ ),
28
27
  ),
29
28
  ]
30
29
  super().__init__(
@@ -1,5 +1,7 @@
1
+ import time
1
2
  from typing import TYPE_CHECKING
2
3
 
4
+ from isar.config.settings import settings
3
5
  from robot_interface.models.mission.status import RobotStatus
4
6
 
5
7
  if TYPE_CHECKING:
@@ -19,3 +21,16 @@ def is_available_or_home(state_machine: "StateMachine") -> bool:
19
21
  def is_blocked_protective_stop(state_machine: "StateMachine") -> bool:
20
22
  robot_status = state_machine.shared_state.robot_status.check()
21
23
  return robot_status == RobotStatus.BlockedProtectiveStop
24
+
25
+
26
+ def clear_robot_status(state_machine: "StateMachine") -> bool:
27
+ state_machine.events.state_machine_events.clear_robot_status.trigger_event(True)
28
+ start_time: float = time.time()
29
+ while time.time() - start_time < settings.CLEAR_ROBOT_STATUS_TIMEOUT:
30
+ if (
31
+ state_machine.events.robot_service_events.robot_status_cleared.consume_event()
32
+ ):
33
+ return True
34
+ time.sleep(settings.FSM_SLEEP_TIME)
35
+ state_machine.logger.error("Timed out waiting for robot status to be cleared")
36
+ return False
@@ -12,6 +12,7 @@ from isar.state_machine.transitions.functions.return_home import (
12
12
  should_retry_return_home,
13
13
  start_return_home_mission,
14
14
  )
15
+ from isar.state_machine.transitions.functions.robot_status import clear_robot_status
15
16
  from isar.state_machine.transitions.functions.start_mission import (
16
17
  initialize_robot,
17
18
  trigger_start_mission_event,
@@ -58,11 +59,19 @@ def get_return_home_transitions(state_machine: "StateMachine") -> List[dict]:
58
59
  "trigger": "returned_home",
59
60
  "source": state_machine.returning_home_state,
60
61
  "dest": state_machine.home_state,
62
+ "conditions": [
63
+ def_transition(state_machine, clear_robot_status),
64
+ ],
61
65
  "before": [
62
66
  def_transition(state_machine, reset_return_home_failure_counter),
63
67
  def_transition(state_machine, return_home_finished),
64
68
  ],
65
69
  },
70
+ {
71
+ "trigger": "returned_home",
72
+ "source": state_machine.returning_home_state,
73
+ "dest": state_machine.intervention_needed_state,
74
+ },
66
75
  {
67
76
  "trigger": "starting_recharging",
68
77
  "source": state_machine.returning_home_state,
@@ -43,9 +43,12 @@ def return_home_event_handler(
43
43
  def robot_status_event_handler(
44
44
  state_machine: "StateMachine",
45
45
  expected_status: RobotStatus,
46
- event: Event[RobotStatus],
46
+ status_changed_event: Event[bool],
47
+ status_event: Event[RobotStatus],
47
48
  ) -> Optional[Callable]:
48
- robot_status: RobotStatus = event.check()
49
+ if not status_changed_event.consume_event():
50
+ return None
51
+ robot_status: Optional[RobotStatus] = status_event.check()
49
52
  if robot_status != expected_status:
50
53
  return state_machine.robot_status_changed # type: ignore
51
54
  return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: isar
3
- Version: 1.33.6
3
+ Version: 1.33.7
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
@@ -81,6 +81,7 @@ src/isar/mission_planner/task_selector_interface.py
81
81
  src/isar/models/__init__.py
82
82
  src/isar/models/events.py
83
83
  src/isar/robot/robot.py
84
+ src/isar/robot/robot_battery.py
84
85
  src/isar/robot/robot_pause_mission.py
85
86
  src/isar/robot/robot_start_mission.py
86
87
  src/isar/robot/robot_status.py
@@ -37,6 +37,7 @@ from tests.test_double.robot_interface import (
37
37
  StubRobot,
38
38
  StubRobotBlockedProtectiveStopToHomeTest,
39
39
  StubRobotOfflineToHomeTest,
40
+ StubRobotRobotStatusBusyIfNotHomeOrUnknownStatus,
40
41
  )
41
42
  from tests.test_double.task import StubTask
42
43
 
@@ -95,21 +96,34 @@ def test_state_machine_transitions_when_running_full_mission(
95
96
  container: ApplicationContainer,
96
97
  state_machine_thread: StateMachineThreadMock,
97
98
  robot_service_thread: RobotServiceThreadMock,
98
- mocker,
99
99
  ) -> None:
100
100
  state_machine_thread.state_machine.await_next_mission_state.timers[
101
101
  0
102
102
  ].timeout_in_seconds = 0.01
103
+
104
+ robot_service_thread.robot_service.robot = (
105
+ StubRobotRobotStatusBusyIfNotHomeOrUnknownStatus(
106
+ current_state=robot_service_thread.robot_service.shared_state.state,
107
+ initiate_mission_delay=1,
108
+ )
109
+ )
103
110
  state_machine_thread.start()
104
- mocker.patch.object(StubRobot, "robot_status", return_value=RobotStatus.Home)
105
111
  robot_service_thread.start()
112
+
113
+ # Setting the poll interval to a lower value to ensure that the robot status is
114
+ # updated during the mission. This value needs to be set after the robot service
115
+ # thread has been started.
116
+ robot_service_thread.robot_service.robot_status_thread.robot_status_poll_interval = (
117
+ 0.5
118
+ )
119
+
106
120
  task_1: Task = TakeImage(
107
121
  target=DummyPose.default_pose().position, robot_pose=DummyPose.default_pose()
108
122
  )
109
123
  task_2: Task = TakeImage(
110
124
  target=DummyPose.default_pose().position, robot_pose=DummyPose.default_pose()
111
125
  )
112
- mission: Mission = Mission(name="Dummy misson", tasks=[task_1, task_2])
126
+ mission: Mission = Mission(name="Dummy mission", tasks=[task_1, task_2])
113
127
 
114
128
  scheduling_utilities: SchedulingUtilities = container.scheduling_utilities()
115
129
  scheduling_utilities.start_mission(mission=mission)
@@ -965,7 +979,11 @@ def test_state_machine_with_return_home_failure_successful_retries(
965
979
  ].timeout_in_seconds = 0.01
966
980
  scheduling_utilities: SchedulingUtilities = container.scheduling_utilities()
967
981
  state_machine_thread.start()
968
- mocker.patch.object(StubRobot, "robot_status", return_value=RobotStatus.Available)
982
+ mocker.patch.object(
983
+ StubRobot,
984
+ "robot_status",
985
+ side_effect=[RobotStatus.Available, RobotStatus.Home],
986
+ )
969
987
  mocker.patch.object(
970
988
  StubRobot, "task_status", side_effect=[TaskStatus.Failed, TaskStatus.Successful]
971
989
  )
@@ -1,7 +1,8 @@
1
+ import time
1
2
  from datetime import datetime
2
3
  from queue import Queue
3
4
  from threading import Thread
4
- from typing import Callable, List
5
+ from typing import Callable, List, Optional
5
6
 
6
7
  from alitra import Frame, Orientation, Pose, Position
7
8
 
@@ -33,14 +34,19 @@ class StubRobot(RobotInterface):
33
34
  frame=Frame("robot"),
34
35
  ),
35
36
  robot_status: RobotStatus = RobotStatus.Available,
37
+ initiate_mission_delay: float = 0.0,
36
38
  ):
37
39
  self.mission_status_return_value: MissionStatus = mission_status
38
40
  self.task_status_return_value: TaskStatus = task_status
39
41
  self.stop_return_value: bool = stop
40
42
  self.robot_pose_return_value: Pose = pose
41
43
  self.robot_status_return_value: RobotStatus = robot_status
44
+ self.initiate_mission_delay: float = initiate_mission_delay
45
+ self.mission: Optional[Mission] = None
42
46
 
43
47
  def initiate_mission(self, mission: Mission) -> None:
48
+ time.sleep(self.initiate_mission_delay)
49
+ self.mission = mission
44
50
  return
45
51
 
46
52
  def task_status(self, task_id: str) -> TaskStatus:
@@ -153,3 +159,34 @@ class StubRobotOfflineToHomeTest(StubRobot):
153
159
  if not self.entered_offline:
154
160
  return RobotStatus.Offline
155
161
  return RobotStatus.Home
162
+
163
+
164
+ class StubRobotRobotStatusBusyIfNotHomeOrUnknownStatus(StubRobot):
165
+ def __init__(
166
+ self,
167
+ current_state: Event,
168
+ initiate_mission_delay: float = 0.0,
169
+ ):
170
+ super().__init__()
171
+ self.current_state = current_state
172
+ self.initiate_mission_delay: float = initiate_mission_delay
173
+ self.return_home_mission_just_finished_successfully = False
174
+
175
+ def task_status(self, task_id: str) -> TaskStatus:
176
+ if self.mission._is_return_to_home_mission():
177
+ if self.task_status_return_value == TaskStatus.Successful:
178
+ self.return_home_mission_just_finished_successfully = True
179
+ return self.task_status_return_value
180
+
181
+ def robot_status(self) -> RobotStatus:
182
+ current_state = self.current_state.check()
183
+ if current_state is None:
184
+ raise RobotCommunicationException("Could not read state machine state")
185
+ if current_state == "home":
186
+ return RobotStatus.Home
187
+ elif current_state == "unknown_status":
188
+ return RobotStatus.Home
189
+ elif self.return_home_mission_just_finished_successfully:
190
+ return RobotStatus.Home
191
+
192
+ return RobotStatus.Busy
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes