reachy-mini 1.2.5rc1__py3-none-any.whl

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.
Files changed (479) hide show
  1. reachy_mini/__init__.py +4 -0
  2. reachy_mini/apps/__init__.py +25 -0
  3. reachy_mini/apps/app.py +258 -0
  4. reachy_mini/apps/assistant.py +787 -0
  5. reachy_mini/apps/manager.py +312 -0
  6. reachy_mini/apps/sources/__init__.py +4 -0
  7. reachy_mini/apps/sources/hf_space.py +106 -0
  8. reachy_mini/apps/sources/local_common_venv.py +567 -0
  9. reachy_mini/apps/templates/README.md.j2 +12 -0
  10. reachy_mini/apps/templates/gitignore.j2 +3 -0
  11. reachy_mini/apps/templates/index.html.j2 +40 -0
  12. reachy_mini/apps/templates/main.py.j2 +74 -0
  13. reachy_mini/apps/templates/pyproject.toml.j2 +28 -0
  14. reachy_mini/apps/templates/static/index.html.j2 +27 -0
  15. reachy_mini/apps/templates/static/main.js.j2 +47 -0
  16. reachy_mini/apps/templates/static/style.css.j2 +25 -0
  17. reachy_mini/apps/templates/style.css.j2 +411 -0
  18. reachy_mini/apps/utils.py +30 -0
  19. reachy_mini/assets/config/hardware_config.yaml +164 -0
  20. reachy_mini/assets/confused1.wav +0 -0
  21. reachy_mini/assets/count.wav +0 -0
  22. reachy_mini/assets/dance1.wav +0 -0
  23. reachy_mini/assets/firmware/CHANGELOG.md +15 -0
  24. reachy_mini/assets/firmware/reachymini_ua_io16_lin_v2.1.2.bin +0 -0
  25. reachy_mini/assets/firmware/reachymini_ua_io16_lin_v2.1.3.bin +0 -0
  26. reachy_mini/assets/firmware/update.sh +9 -0
  27. reachy_mini/assets/go_sleep.wav +0 -0
  28. reachy_mini/assets/impatient1.wav +0 -0
  29. reachy_mini/assets/kinematics_data.json +253 -0
  30. reachy_mini/assets/models/fknetwork.dynamic.onnx +0 -0
  31. reachy_mini/assets/models/fknetwork.onnx +0 -0
  32. reachy_mini/assets/models/fknetwork_int8.onnx +0 -0
  33. reachy_mini/assets/models/iknetwork.onnx +0 -0
  34. reachy_mini/assets/wake_up.wav +0 -0
  35. reachy_mini/daemon/__init__.py +1 -0
  36. reachy_mini/daemon/app/__init__.py +1 -0
  37. reachy_mini/daemon/app/bg_job_register.py +142 -0
  38. reachy_mini/daemon/app/dashboard/static/assets/KO-cartoon-static.svg +40 -0
  39. reachy_mini/daemon/app/dashboard/static/assets/awake-cartoon-static.svg +42 -0
  40. reachy_mini/daemon/app/dashboard/static/assets/awake-cartoon.svg +6 -0
  41. reachy_mini/daemon/app/dashboard/static/assets/go-to-sleep-cartoon.svg +6 -0
  42. reachy_mini/daemon/app/dashboard/static/assets/no-wifi-cartoon-static.svg +50 -0
  43. reachy_mini/daemon/app/dashboard/static/assets/no-wifi-cartoon.svg +6 -0
  44. reachy_mini/daemon/app/dashboard/static/assets/reachy-mini-awake.svg +18 -0
  45. reachy_mini/daemon/app/dashboard/static/assets/reachy-mini-connection-lost-animation.svg +6 -0
  46. reachy_mini/daemon/app/dashboard/static/assets/reachy-mini-go-to-sleep-animation.svg +6 -0
  47. reachy_mini/daemon/app/dashboard/static/assets/reachy-mini-ko-animation.svg +6 -0
  48. reachy_mini/daemon/app/dashboard/static/assets/reachy-mini-ko.svg +22 -0
  49. reachy_mini/daemon/app/dashboard/static/assets/reachy-mini-sleeping-static.svg +41 -0
  50. reachy_mini/daemon/app/dashboard/static/assets/reachy-mini-sleeping.svg +18 -0
  51. reachy_mini/daemon/app/dashboard/static/assets/reachy-mini-wake-up-animation.svg +6 -0
  52. reachy_mini/daemon/app/dashboard/static/css/app.css +1433 -0
  53. reachy_mini/daemon/app/dashboard/static/fonts/Archivo-Italic-VariableFont_wdth,wght.ttf +0 -0
  54. reachy_mini/daemon/app/dashboard/static/fonts/Archivo-VariableFont_wdth,wght.ttf +0 -0
  55. reachy_mini/daemon/app/dashboard/static/fonts/Asap-Italic-VariableFont_wdth,wght.ttf +0 -0
  56. reachy_mini/daemon/app/dashboard/static/fonts/Asap-VariableFont_wdth,wght.ttf +0 -0
  57. reachy_mini/daemon/app/dashboard/static/js/3rdparty/gstwebrtc-api-2.0.0.min.js +5 -0
  58. reachy_mini/daemon/app/dashboard/static/js/apps.js +323 -0
  59. reachy_mini/daemon/app/dashboard/static/js/appstore.js +167 -0
  60. reachy_mini/daemon/app/dashboard/static/js/daemon.js +169 -0
  61. reachy_mini/daemon/app/dashboard/static/js/health_check.js +9 -0
  62. reachy_mini/daemon/app/dashboard/static/js/move_player.js +132 -0
  63. reachy_mini/daemon/app/dashboard/static/js/notification.js +41 -0
  64. reachy_mini/daemon/app/dashboard/static/js/update.js +132 -0
  65. reachy_mini/daemon/app/dashboard/static/js/volume_control.js +252 -0
  66. reachy_mini/daemon/app/dashboard/static/js/wifi.js +176 -0
  67. reachy_mini/daemon/app/dashboard/tailwindcss/README.md +15 -0
  68. reachy_mini/daemon/app/dashboard/tailwindcss/package-lock.json +1127 -0
  69. reachy_mini/daemon/app/dashboard/tailwindcss/package.json +6 -0
  70. reachy_mini/daemon/app/dashboard/tailwindcss/pnpm-lock.yaml +608 -0
  71. reachy_mini/daemon/app/dashboard/tailwindcss/postcss.config.js +6 -0
  72. reachy_mini/daemon/app/dashboard/tailwindcss/styles/app.css +185 -0
  73. reachy_mini/daemon/app/dashboard/tailwindcss/tailwind.config.js +11 -0
  74. reachy_mini/daemon/app/dashboard/templates/base.html +21 -0
  75. reachy_mini/daemon/app/dashboard/templates/index.html +20 -0
  76. reachy_mini/daemon/app/dashboard/templates/sections/apps.html +8 -0
  77. reachy_mini/daemon/app/dashboard/templates/sections/appstore.html +35 -0
  78. reachy_mini/daemon/app/dashboard/templates/sections/daemon.html +45 -0
  79. reachy_mini/daemon/app/dashboard/templates/sections/move_player.html +121 -0
  80. reachy_mini/daemon/app/dashboard/templates/sections/notification.html +19 -0
  81. reachy_mini/daemon/app/dashboard/templates/sections/update.html +54 -0
  82. reachy_mini/daemon/app/dashboard/templates/sections/wifi.html +46 -0
  83. reachy_mini/daemon/app/dashboard/templates/settings.html +14 -0
  84. reachy_mini/daemon/app/dependencies.py +41 -0
  85. reachy_mini/daemon/app/main.py +469 -0
  86. reachy_mini/daemon/app/models.py +149 -0
  87. reachy_mini/daemon/app/routers/apps.py +114 -0
  88. reachy_mini/daemon/app/routers/daemon.py +85 -0
  89. reachy_mini/daemon/app/routers/kinematics.py +57 -0
  90. reachy_mini/daemon/app/routers/motors.py +41 -0
  91. reachy_mini/daemon/app/routers/move.py +265 -0
  92. reachy_mini/daemon/app/routers/state.py +146 -0
  93. reachy_mini/daemon/app/routers/update.py +86 -0
  94. reachy_mini/daemon/app/routers/volume.py +423 -0
  95. reachy_mini/daemon/app/routers/wifi_config.py +219 -0
  96. reachy_mini/daemon/app/services/__init__.py +1 -0
  97. reachy_mini/daemon/app/services/bluetooth/bluetooth_service.py +796 -0
  98. reachy_mini/daemon/app/services/bluetooth/commands/HOTSPOT.sh +7 -0
  99. reachy_mini/daemon/app/services/bluetooth/commands/RESTART_DAEMON.sh +4 -0
  100. reachy_mini/daemon/app/services/bluetooth/commands/SOFTWARE_RESET.sh +7 -0
  101. reachy_mini/daemon/app/services/bluetooth/install_service_bluetooth.sh +39 -0
  102. reachy_mini/daemon/app/services/gpio_shutdown/__init__.py +1 -0
  103. reachy_mini/daemon/app/services/gpio_shutdown/install_service.sh +33 -0
  104. reachy_mini/daemon/app/services/gpio_shutdown/launcher.sh +3 -0
  105. reachy_mini/daemon/app/services/gpio_shutdown/shutdown_monitor.py +28 -0
  106. reachy_mini/daemon/app/services/wireless/generate_asoundrc.sh +70 -0
  107. reachy_mini/daemon/app/services/wireless/install_service.sh +33 -0
  108. reachy_mini/daemon/app/services/wireless/launcher.sh +5 -0
  109. reachy_mini/daemon/backend/__init__.py +1 -0
  110. reachy_mini/daemon/backend/abstract.py +815 -0
  111. reachy_mini/daemon/backend/mujoco/__init__.py +36 -0
  112. reachy_mini/daemon/backend/mujoco/backend.py +395 -0
  113. reachy_mini/daemon/backend/mujoco/utils.py +59 -0
  114. reachy_mini/daemon/backend/mujoco/video_udp.py +57 -0
  115. reachy_mini/daemon/backend/robot/__init__.py +8 -0
  116. reachy_mini/daemon/backend/robot/backend.py +597 -0
  117. reachy_mini/daemon/daemon.py +651 -0
  118. reachy_mini/daemon/utils.py +116 -0
  119. reachy_mini/descriptions/reachy_mini/mjcf/additional.xml +6 -0
  120. reachy_mini/descriptions/reachy_mini/mjcf/assets/5w_speaker.part +13 -0
  121. reachy_mini/descriptions/reachy_mini/mjcf/assets/5w_speaker.stl +0 -0
  122. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna.part +13 -0
  123. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna.stl +0 -0
  124. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_body_3dprint.part +13 -0
  125. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_body_3dprint.stl +0 -0
  126. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_holder_l_3dprint.part +13 -0
  127. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_holder_l_3dprint.stl +0 -0
  128. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_holder_r_3dprint.part +13 -0
  129. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_holder_r_3dprint.stl +0 -0
  130. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_interface_3dprint.part +13 -0
  131. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_interface_3dprint.stl +0 -0
  132. reachy_mini/descriptions/reachy_mini/mjcf/assets/arducam.part +13 -0
  133. reachy_mini/descriptions/reachy_mini/mjcf/assets/arducam.stl +0 -0
  134. reachy_mini/descriptions/reachy_mini/mjcf/assets/b3b_eh.part +13 -0
  135. reachy_mini/descriptions/reachy_mini/mjcf/assets/b3b_eh.stl +0 -0
  136. reachy_mini/descriptions/reachy_mini/mjcf/assets/b3b_eh_1.part +13 -0
  137. reachy_mini/descriptions/reachy_mini/mjcf/assets/b3b_eh_1.stl +0 -0
  138. reachy_mini/descriptions/reachy_mini/mjcf/assets/bearing_85x110x13.part +13 -0
  139. reachy_mini/descriptions/reachy_mini/mjcf/assets/bearing_85x110x13.stl +0 -0
  140. reachy_mini/descriptions/reachy_mini/mjcf/assets/big_lens_d40.part +13 -0
  141. reachy_mini/descriptions/reachy_mini/mjcf/assets/big_lens_d40.stl +0 -0
  142. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_down_3dprint.part +13 -0
  143. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_down_3dprint.stl +0 -0
  144. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_foot_3dprint.part +13 -0
  145. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_foot_3dprint.stl +0 -0
  146. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_top_3dprint.part +13 -0
  147. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_top_3dprint.stl +0 -0
  148. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_turning_3dprint.part +13 -0
  149. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_turning_3dprint.stl +0 -0
  150. reachy_mini/descriptions/reachy_mini/mjcf/assets/bts2_m2_6x8.part +13 -0
  151. reachy_mini/descriptions/reachy_mini/mjcf/assets/bts2_m2_6x8.stl +0 -0
  152. reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/README.m +1 -0
  153. reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_back_0.stl +0 -0
  154. reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_back_1.stl +0 -0
  155. reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_back_2.stl +0 -0
  156. reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_back_3.stl +0 -0
  157. reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_front_0.stl +0 -0
  158. reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_front_1.stl +0 -0
  159. reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_front_2.stl +0 -0
  160. reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/head_one_3dprint_collider_0.stl +0 -0
  161. reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_back_0.stl +0 -0
  162. reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_back_1.stl +0 -0
  163. reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_back_2.stl +0 -0
  164. reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_back_3.stl +0 -0
  165. reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_front_0.stl +0 -0
  166. reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_front_1.stl +0 -0
  167. reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_front_2.stl +0 -0
  168. reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/head_one_3dprint_collider_0.stl +0 -0
  169. reachy_mini/descriptions/reachy_mini/mjcf/assets/croissant_1k.blend/croissant_1k.obj +5021 -0
  170. reachy_mini/descriptions/reachy_mini/mjcf/assets/croissant_1k.blend/textures/croissant_diff_1k.png +0 -0
  171. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_b_dummy.part +13 -0
  172. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_b_dummy.stl +0 -0
  173. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_f_dummy.part +13 -0
  174. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_f_dummy.stl +0 -0
  175. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_m_dummy.part +13 -0
  176. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_m_dummy.stl +0 -0
  177. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_horn_dummy.part +13 -0
  178. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_horn_dummy.stl +0 -0
  179. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_led_cap2_dummy.part +13 -0
  180. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_led_cap2_dummy.stl +0 -0
  181. reachy_mini/descriptions/reachy_mini/mjcf/assets/food_apple_01_1k.blend/food_apple_01_1k.obj +18045 -0
  182. reachy_mini/descriptions/reachy_mini/mjcf/assets/food_apple_01_1k.blend/textures/food_apple_01_diff_1k.png +0 -0
  183. reachy_mini/descriptions/reachy_mini/mjcf/assets/glasses_dolder_3dprint.part +13 -0
  184. reachy_mini/descriptions/reachy_mini/mjcf/assets/glasses_dolder_3dprint.stl +0 -0
  185. reachy_mini/descriptions/reachy_mini/mjcf/assets/head_back_3dprint.part +13 -0
  186. reachy_mini/descriptions/reachy_mini/mjcf/assets/head_back_3dprint.stl +0 -0
  187. reachy_mini/descriptions/reachy_mini/mjcf/assets/head_front_3dprint.part +13 -0
  188. reachy_mini/descriptions/reachy_mini/mjcf/assets/head_front_3dprint.stl +0 -0
  189. reachy_mini/descriptions/reachy_mini/mjcf/assets/head_mic_3dprint.part +13 -0
  190. reachy_mini/descriptions/reachy_mini/mjcf/assets/head_mic_3dprint.stl +0 -0
  191. reachy_mini/descriptions/reachy_mini/mjcf/assets/lens_cap_d30_3dprint.part +13 -0
  192. reachy_mini/descriptions/reachy_mini/mjcf/assets/lens_cap_d30_3dprint.stl +0 -0
  193. reachy_mini/descriptions/reachy_mini/mjcf/assets/lens_cap_d40_3dprint.part +13 -0
  194. reachy_mini/descriptions/reachy_mini/mjcf/assets/lens_cap_d40_3dprint.stl +0 -0
  195. reachy_mini/descriptions/reachy_mini/mjcf/assets/m12_fisheye_lens_1_8mm.part +13 -0
  196. reachy_mini/descriptions/reachy_mini/mjcf/assets/m12_fisheye_lens_1_8mm.stl +0 -0
  197. reachy_mini/descriptions/reachy_mini/mjcf/assets/mp01062_stewart_arm_3.part +13 -0
  198. reachy_mini/descriptions/reachy_mini/mjcf/assets/mp01062_stewart_arm_3.stl +0 -0
  199. reachy_mini/descriptions/reachy_mini/mjcf/assets/neck_reference_3dprint.part +13 -0
  200. reachy_mini/descriptions/reachy_mini/mjcf/assets/neck_reference_3dprint.stl +0 -0
  201. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10.part +13 -0
  202. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10.stl +0 -0
  203. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_1.part +13 -0
  204. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_1.stl +0 -0
  205. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_2.part +13 -0
  206. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_2.stl +0 -0
  207. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_3.part +13 -0
  208. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_3.stl +0 -0
  209. reachy_mini/descriptions/reachy_mini/mjcf/assets/pp01102_arducam_carter.part +13 -0
  210. reachy_mini/descriptions/reachy_mini/mjcf/assets/pp01102_arducam_carter.stl +0 -0
  211. reachy_mini/descriptions/reachy_mini/mjcf/assets/rubber_duck_toy_1k.blend/rubber_duck_toy_1k.obj +8940 -0
  212. reachy_mini/descriptions/reachy_mini/mjcf/assets/rubber_duck_toy_1k.blend/textures/rubber_duck_toy_diff_1k.png +0 -0
  213. reachy_mini/descriptions/reachy_mini/mjcf/assets/small_lens_d30.part +13 -0
  214. reachy_mini/descriptions/reachy_mini/mjcf/assets/small_lens_d30.stl +0 -0
  215. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_ball.part +13 -0
  216. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_ball.stl +0 -0
  217. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_ball__2.part +13 -0
  218. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_ball__2.stl +0 -0
  219. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_rod.part +13 -0
  220. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_rod.stl +0 -0
  221. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_main_plate_3dprint.part +13 -0
  222. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_main_plate_3dprint.stl +0 -0
  223. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_tricap_3dprint.part +13 -0
  224. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_tricap_3dprint.stl +0 -0
  225. reachy_mini/descriptions/reachy_mini/mjcf/assets/wooden_table_02_1k.blend/textures/wooden_table_02_diff_1k.png +0 -0
  226. reachy_mini/descriptions/reachy_mini/mjcf/assets/wooden_table_02_1k.blend/wooden_table_02_1k.obj +485 -0
  227. reachy_mini/descriptions/reachy_mini/mjcf/config.json +21 -0
  228. reachy_mini/descriptions/reachy_mini/mjcf/joints_properties.xml +29 -0
  229. reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml +642 -0
  230. reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml.bak +442 -0
  231. reachy_mini/descriptions/reachy_mini/mjcf/scene.xml +24 -0
  232. reachy_mini/descriptions/reachy_mini/mjcf/scenes/empty.xml +27 -0
  233. reachy_mini/descriptions/reachy_mini/mjcf/scenes/minimal.xml +132 -0
  234. reachy_mini/descriptions/reachy_mini/urdf/assets/5w_speaker.part +13 -0
  235. reachy_mini/descriptions/reachy_mini/urdf/assets/5w_speaker.stl +0 -0
  236. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna.part +13 -0
  237. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna.stl +0 -0
  238. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_body_3dprint.part +13 -0
  239. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_body_3dprint.stl +0 -0
  240. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_holder_l_3dprint.part +13 -0
  241. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_holder_l_3dprint.stl +0 -0
  242. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_holder_r_3dprint.part +13 -0
  243. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_holder_r_3dprint.stl +0 -0
  244. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_interface_3dprint.part +13 -0
  245. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_interface_3dprint.stl +0 -0
  246. reachy_mini/descriptions/reachy_mini/urdf/assets/arducam.part +13 -0
  247. reachy_mini/descriptions/reachy_mini/urdf/assets/arducam.stl +0 -0
  248. reachy_mini/descriptions/reachy_mini/urdf/assets/arm.part +13 -0
  249. reachy_mini/descriptions/reachy_mini/urdf/assets/arm.stl +0 -0
  250. reachy_mini/descriptions/reachy_mini/urdf/assets/b3b_eh.part +13 -0
  251. reachy_mini/descriptions/reachy_mini/urdf/assets/b3b_eh.stl +0 -0
  252. reachy_mini/descriptions/reachy_mini/urdf/assets/b3b_eh_1.part +13 -0
  253. reachy_mini/descriptions/reachy_mini/urdf/assets/b3b_eh_1.stl +0 -0
  254. reachy_mini/descriptions/reachy_mini/urdf/assets/ball.part +13 -0
  255. reachy_mini/descriptions/reachy_mini/urdf/assets/ball.stl +0 -0
  256. reachy_mini/descriptions/reachy_mini/urdf/assets/bearing_85x110x13.part +13 -0
  257. reachy_mini/descriptions/reachy_mini/urdf/assets/bearing_85x110x13.stl +0 -0
  258. reachy_mini/descriptions/reachy_mini/urdf/assets/big_lens.part +13 -0
  259. reachy_mini/descriptions/reachy_mini/urdf/assets/big_lens.stl +0 -0
  260. reachy_mini/descriptions/reachy_mini/urdf/assets/big_lens_d40.part +13 -0
  261. reachy_mini/descriptions/reachy_mini/urdf/assets/big_lens_d40.stl +0 -0
  262. reachy_mini/descriptions/reachy_mini/urdf/assets/body_down_3dprint.part +13 -0
  263. reachy_mini/descriptions/reachy_mini/urdf/assets/body_down_3dprint.stl +0 -0
  264. reachy_mini/descriptions/reachy_mini/urdf/assets/body_foot_3dprint.part +13 -0
  265. reachy_mini/descriptions/reachy_mini/urdf/assets/body_foot_3dprint.stl +0 -0
  266. reachy_mini/descriptions/reachy_mini/urdf/assets/body_top_3dprint.part +13 -0
  267. reachy_mini/descriptions/reachy_mini/urdf/assets/body_top_3dprint.stl +0 -0
  268. reachy_mini/descriptions/reachy_mini/urdf/assets/body_turning_3dprint.part +13 -0
  269. reachy_mini/descriptions/reachy_mini/urdf/assets/body_turning_3dprint.stl +0 -0
  270. reachy_mini/descriptions/reachy_mini/urdf/assets/bottom_body.part +13 -0
  271. reachy_mini/descriptions/reachy_mini/urdf/assets/bottom_body.stl +0 -0
  272. reachy_mini/descriptions/reachy_mini/urdf/assets/bts2_m2_6x8.part +13 -0
  273. reachy_mini/descriptions/reachy_mini/urdf/assets/bts2_m2_6x8.stl +0 -0
  274. reachy_mini/descriptions/reachy_mini/urdf/assets/collision/README.m +1 -0
  275. reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_back_0.stl +0 -0
  276. reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_back_1.stl +0 -0
  277. reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_back_2.stl +0 -0
  278. reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_back_3.stl +0 -0
  279. reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_front_0.stl +0 -0
  280. reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_front_1.stl +0 -0
  281. reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_front_2.stl +0 -0
  282. reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/head_one_3dprint_collider_0.stl +0 -0
  283. reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_back_0.stl +0 -0
  284. reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_back_1.stl +0 -0
  285. reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_back_2.stl +0 -0
  286. reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_back_3.stl +0 -0
  287. reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_front_0.stl +0 -0
  288. reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_front_1.stl +0 -0
  289. reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_front_2.stl +0 -0
  290. reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/head_one_3dprint_collider_0.stl +0 -0
  291. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_b_dummy.part +13 -0
  292. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_b_dummy.stl +0 -0
  293. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_f_dummy.part +13 -0
  294. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_f_dummy.stl +0 -0
  295. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_m_dummy.part +13 -0
  296. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_m_dummy.stl +0 -0
  297. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_horn_dummy.part +13 -0
  298. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_horn_dummy.stl +0 -0
  299. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_led_cap2_dummy.part +13 -0
  300. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_led_cap2_dummy.stl +0 -0
  301. reachy_mini/descriptions/reachy_mini/urdf/assets/drive_palonier__configuration_default.part +14 -0
  302. reachy_mini/descriptions/reachy_mini/urdf/assets/drive_palonier__configuration_default.stl +0 -0
  303. reachy_mini/descriptions/reachy_mini/urdf/assets/drive_palonier__configuration_simple_axe.part +14 -0
  304. reachy_mini/descriptions/reachy_mini/urdf/assets/drive_palonier__configuration_simple_axe.stl +0 -0
  305. reachy_mini/descriptions/reachy_mini/urdf/assets/eye_support.part +13 -0
  306. reachy_mini/descriptions/reachy_mini/urdf/assets/eye_support.stl +0 -0
  307. reachy_mini/descriptions/reachy_mini/urdf/assets/foot.part +13 -0
  308. reachy_mini/descriptions/reachy_mini/urdf/assets/foot.stl +0 -0
  309. reachy_mini/descriptions/reachy_mini/urdf/assets/glasses_dolder_3dprint.part +13 -0
  310. reachy_mini/descriptions/reachy_mini/urdf/assets/glasses_dolder_3dprint.stl +0 -0
  311. reachy_mini/descriptions/reachy_mini/urdf/assets/head_back_3dprint.part +13 -0
  312. reachy_mini/descriptions/reachy_mini/urdf/assets/head_back_3dprint.stl +0 -0
  313. reachy_mini/descriptions/reachy_mini/urdf/assets/head_front_3dprint.part +13 -0
  314. reachy_mini/descriptions/reachy_mini/urdf/assets/head_front_3dprint.stl +0 -0
  315. reachy_mini/descriptions/reachy_mini/urdf/assets/head_head_back.part +13 -0
  316. reachy_mini/descriptions/reachy_mini/urdf/assets/head_head_back.stl +0 -0
  317. reachy_mini/descriptions/reachy_mini/urdf/assets/head_interface.part +13 -0
  318. reachy_mini/descriptions/reachy_mini/urdf/assets/head_interface.stl +0 -0
  319. reachy_mini/descriptions/reachy_mini/urdf/assets/head_mic_3dprint.part +13 -0
  320. reachy_mini/descriptions/reachy_mini/urdf/assets/head_mic_3dprint.stl +0 -0
  321. reachy_mini/descriptions/reachy_mini/urdf/assets/head_shell_front.part +13 -0
  322. reachy_mini/descriptions/reachy_mini/urdf/assets/head_shell_front.stl +0 -0
  323. reachy_mini/descriptions/reachy_mini/urdf/assets/lens_cap_d30_3dprint.part +13 -0
  324. reachy_mini/descriptions/reachy_mini/urdf/assets/lens_cap_d30_3dprint.stl +0 -0
  325. reachy_mini/descriptions/reachy_mini/urdf/assets/lens_cap_d40_3dprint.part +13 -0
  326. reachy_mini/descriptions/reachy_mini/urdf/assets/lens_cap_d40_3dprint.stl +0 -0
  327. reachy_mini/descriptions/reachy_mini/urdf/assets/m12_fisheye_lens_1_8mm.part +13 -0
  328. reachy_mini/descriptions/reachy_mini/urdf/assets/m12_fisheye_lens_1_8mm.stl +0 -0
  329. reachy_mini/descriptions/reachy_mini/urdf/assets/m12_lens.part +13 -0
  330. reachy_mini/descriptions/reachy_mini/urdf/assets/m12_lens.stl +0 -0
  331. reachy_mini/descriptions/reachy_mini/urdf/assets/main_plate.part +13 -0
  332. reachy_mini/descriptions/reachy_mini/urdf/assets/main_plate.stl +0 -0
  333. reachy_mini/descriptions/reachy_mini/urdf/assets/mid_plate.part +13 -0
  334. reachy_mini/descriptions/reachy_mini/urdf/assets/mid_plate.stl +0 -0
  335. reachy_mini/descriptions/reachy_mini/urdf/assets/mp01062_stewart_arm_3.part +13 -0
  336. reachy_mini/descriptions/reachy_mini/urdf/assets/mp01062_stewart_arm_3.stl +0 -0
  337. reachy_mini/descriptions/reachy_mini/urdf/assets/neck_reference_3dprint.part +13 -0
  338. reachy_mini/descriptions/reachy_mini/urdf/assets/neck_reference_3dprint.stl +0 -0
  339. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10.part +13 -0
  340. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10.stl +0 -0
  341. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_1.part +13 -0
  342. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_1.stl +0 -0
  343. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_2.part +13 -0
  344. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_2.stl +0 -0
  345. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_3.part +13 -0
  346. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_3.stl +0 -0
  347. reachy_mini/descriptions/reachy_mini/urdf/assets/plateform.part +13 -0
  348. reachy_mini/descriptions/reachy_mini/urdf/assets/plateform.stl +0 -0
  349. reachy_mini/descriptions/reachy_mini/urdf/assets/pp00xxx_stewart_rod.part +13 -0
  350. reachy_mini/descriptions/reachy_mini/urdf/assets/pp00xxx_stewart_rod.stl +0 -0
  351. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01062_stewart_arm.part +13 -0
  352. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01062_stewart_arm.stl +0 -0
  353. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01063_stewart_plateform.part +13 -0
  354. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01063_stewart_plateform.stl +0 -0
  355. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01064_stewart_main_plate.part +13 -0
  356. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01064_stewart_main_plate.stl +0 -0
  357. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01065_stewart_side_plate.part +13 -0
  358. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01065_stewart_side_plate.stl +0 -0
  359. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01066_stewart_mid_plate.part +13 -0
  360. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01066_stewart_mid_plate.stl +0 -0
  361. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01067_bottom_body.part +13 -0
  362. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01067_bottom_body.stl +0 -0
  363. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01068_top_body.part +13 -0
  364. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01068_top_body.stl +0 -0
  365. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01069_head_shell_front.part +13 -0
  366. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01069_head_shell_front.stl +0 -0
  367. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01070_head_head_back.part +13 -0
  368. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01070_head_head_back.stl +0 -0
  369. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01071_turning_bowl.part +13 -0
  370. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01071_turning_bowl.stl +0 -0
  371. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01072_turning_end.part +13 -0
  372. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01072_turning_end.stl +0 -0
  373. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01078_glasses.part +13 -0
  374. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01078_glasses.stl +0 -0
  375. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01079_back_big_eye.part +13 -0
  376. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01079_back_big_eye.stl +0 -0
  377. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01080_back_small_eye.part +13 -0
  378. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01080_back_small_eye.stl +0 -0
  379. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01102_arducam_carter.part +13 -0
  380. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01102_arducam_carter.stl +0 -0
  381. reachy_mini/descriptions/reachy_mini/urdf/assets/rod.part +13 -0
  382. reachy_mini/descriptions/reachy_mini/urdf/assets/rod.stl +0 -0
  383. reachy_mini/descriptions/reachy_mini/urdf/assets/shape.part +13 -0
  384. reachy_mini/descriptions/reachy_mini/urdf/assets/shape.stl +0 -0
  385. reachy_mini/descriptions/reachy_mini/urdf/assets/side_plate.part +13 -0
  386. reachy_mini/descriptions/reachy_mini/urdf/assets/side_plate.stl +0 -0
  387. reachy_mini/descriptions/reachy_mini/urdf/assets/small_lens.part +13 -0
  388. reachy_mini/descriptions/reachy_mini/urdf/assets/small_lens.stl +0 -0
  389. reachy_mini/descriptions/reachy_mini/urdf/assets/small_lens_d30.part +13 -0
  390. reachy_mini/descriptions/reachy_mini/urdf/assets/small_lens_d30.stl +0 -0
  391. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_ball.part +13 -0
  392. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_ball.stl +0 -0
  393. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_ball__2.part +13 -0
  394. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_ball__2.stl +0 -0
  395. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_rod.part +13 -0
  396. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_rod.stl +0 -0
  397. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_main_plate_3dprint.part +13 -0
  398. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_main_plate_3dprint.stl +0 -0
  399. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_tricap_3dprint.part +13 -0
  400. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_tricap_3dprint.stl +0 -0
  401. reachy_mini/descriptions/reachy_mini/urdf/assets/test_antenna.part +13 -0
  402. reachy_mini/descriptions/reachy_mini/urdf/assets/test_antenna.stl +0 -0
  403. reachy_mini/descriptions/reachy_mini/urdf/assets/test_antenna_body.part +13 -0
  404. reachy_mini/descriptions/reachy_mini/urdf/assets/test_antenna_body.stl +0 -0
  405. reachy_mini/descriptions/reachy_mini/urdf/assets/top_body.part +13 -0
  406. reachy_mini/descriptions/reachy_mini/urdf/assets/top_body.stl +0 -0
  407. reachy_mini/descriptions/reachy_mini/urdf/assets/turning_bowl.part +13 -0
  408. reachy_mini/descriptions/reachy_mini/urdf/assets/turning_bowl.stl +0 -0
  409. reachy_mini/descriptions/reachy_mini/urdf/assets/uc_a37_rev_a_step.part +13 -0
  410. reachy_mini/descriptions/reachy_mini/urdf/assets/uc_a37_rev_a_step.stl +0 -0
  411. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0122topcabinetcase_95__configuration_default.part +14 -0
  412. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0122topcabinetcase_95__configuration_default.stl +0 -0
  413. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0122topcabinetcase_95__configuration_simple_axe.part +14 -0
  414. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0122topcabinetcase_95__configuration_simple_axe.stl +0 -0
  415. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0123middlecase_56__configuration_default.part +14 -0
  416. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0123middlecase_56__configuration_default.stl +0 -0
  417. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0123middlecase_56__configuration_simple_axe.part +14 -0
  418. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0123middlecase_56__configuration_simple_axe.stl +0 -0
  419. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0124bottomcase_45__configuration_default.part +14 -0
  420. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0124bottomcase_45__configuration_default.stl +0 -0
  421. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0124bottomcase_45__configuration_simple_axe.part +14 -0
  422. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0124bottomcase_45__configuration_simple_axe.stl +0 -0
  423. reachy_mini/descriptions/reachy_mini/urdf/config.json +18 -0
  424. reachy_mini/descriptions/reachy_mini/urdf/robot.urdf +3281 -0
  425. reachy_mini/descriptions/reachy_mini/urdf/robot.urdf.bak +3282 -0
  426. reachy_mini/descriptions/reachy_mini/urdf/robot_no_collision.urdf +2316 -0
  427. reachy_mini/descriptions/reachy_mini/urdf/robot_simple_collision.urdf +2399 -0
  428. reachy_mini/io/__init__.py +15 -0
  429. reachy_mini/io/abstract.py +70 -0
  430. reachy_mini/io/audio_ws.py +242 -0
  431. reachy_mini/io/protocol.py +44 -0
  432. reachy_mini/io/video_ws.py +135 -0
  433. reachy_mini/io/ws_controller.py +120 -0
  434. reachy_mini/io/zenoh_client.py +273 -0
  435. reachy_mini/io/zenoh_server.py +230 -0
  436. reachy_mini/kinematics/__init__.py +68 -0
  437. reachy_mini/kinematics/analytical_kinematics.py +151 -0
  438. reachy_mini/kinematics/nn_kinematics.py +109 -0
  439. reachy_mini/kinematics/placo_kinematics.py +656 -0
  440. reachy_mini/media/__init__.py +1 -0
  441. reachy_mini/media/audio_base.py +111 -0
  442. reachy_mini/media/audio_control_utils.py +455 -0
  443. reachy_mini/media/audio_gstreamer.py +272 -0
  444. reachy_mini/media/audio_sounddevice.py +321 -0
  445. reachy_mini/media/audio_utils.py +114 -0
  446. reachy_mini/media/camera_base.py +100 -0
  447. reachy_mini/media/camera_constants.py +152 -0
  448. reachy_mini/media/camera_gstreamer.py +231 -0
  449. reachy_mini/media/camera_opencv.py +89 -0
  450. reachy_mini/media/camera_utils.py +111 -0
  451. reachy_mini/media/media_manager.py +281 -0
  452. reachy_mini/media/webrtc_client_gstreamer.py +288 -0
  453. reachy_mini/media/webrtc_daemon.py +334 -0
  454. reachy_mini/motion/__init__.py +4 -0
  455. reachy_mini/motion/goto.py +71 -0
  456. reachy_mini/motion/move.py +43 -0
  457. reachy_mini/motion/recorded_move.py +146 -0
  458. reachy_mini/reachy_mini.py +753 -0
  459. reachy_mini/tools/reflash_motors.py +116 -0
  460. reachy_mini/tools/setup_motor.py +422 -0
  461. reachy_mini/tools/setup_motor_rpi.py +108 -0
  462. reachy_mini/utils/__init__.py +46 -0
  463. reachy_mini/utils/constants.py +9 -0
  464. reachy_mini/utils/hardware_config/__init__.py +1 -0
  465. reachy_mini/utils/hardware_config/parser.py +65 -0
  466. reachy_mini/utils/interpolation.py +227 -0
  467. reachy_mini/utils/parse_urdf_for_kinematics.py +110 -0
  468. reachy_mini/utils/rerun.py +320 -0
  469. reachy_mini/utils/wireless_version/__init__.py +1 -0
  470. reachy_mini/utils/wireless_version/startup_check.py +144 -0
  471. reachy_mini/utils/wireless_version/update.py +20 -0
  472. reachy_mini/utils/wireless_version/update_available.py +61 -0
  473. reachy_mini/utils/wireless_version/utils.py +39 -0
  474. reachy_mini-1.2.5rc1.dist-info/METADATA +161 -0
  475. reachy_mini-1.2.5rc1.dist-info/RECORD +479 -0
  476. reachy_mini-1.2.5rc1.dist-info/WHEEL +5 -0
  477. reachy_mini-1.2.5rc1.dist-info/entry_points.txt +4 -0
  478. reachy_mini-1.2.5rc1.dist-info/licenses/LICENSE +201 -0
  479. reachy_mini-1.2.5rc1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,815 @@
1
+ """Base class for robot backends, simulated or real.
2
+
3
+ This module defines the `Backend` class, which serves as a base for implementing
4
+ different types of robot backends, whether they are simulated (like Mujoco) or real
5
+ (connected via serial port). The class provides methods for managing joint positions,
6
+ torque control, and other backend-specific functionalities.
7
+ It is designed to be extended by subclasses that implement the specific behavior for
8
+ each type of backend.
9
+ """
10
+
11
+ import asyncio
12
+ import json
13
+ import logging
14
+ import threading
15
+ import time
16
+ import typing
17
+ from abc import abstractmethod
18
+ from enum import Enum
19
+ from pathlib import Path
20
+ from typing import Annotated, Any, Dict, Optional
21
+
22
+ import numpy as np
23
+ import zenoh
24
+ from numpy.typing import NDArray
25
+ from scipy.spatial.transform import Rotation as R
26
+
27
+ if typing.TYPE_CHECKING:
28
+ from reachy_mini.daemon.backend.mujoco.backend import MujocoBackendStatus
29
+ from reachy_mini.daemon.backend.robot.backend import RobotBackendStatus
30
+ from reachy_mini.kinematics import AnyKinematics
31
+ from reachy_mini.media.media_manager import MediaBackend, MediaManager
32
+ from reachy_mini.motion.goto import GotoMove
33
+ from reachy_mini.motion.move import Move
34
+ from reachy_mini.utils.constants import MODELS_ROOT_PATH, URDF_ROOT_PATH
35
+ from reachy_mini.utils.interpolation import (
36
+ InterpolationTechnique,
37
+ distance_between_poses,
38
+ time_trajectory,
39
+ )
40
+
41
+
42
+ class MotorControlMode(str, Enum):
43
+ """Enum for motor control modes."""
44
+
45
+ Enabled = "enabled" # Torque ON and controlled in position
46
+ Disabled = "disabled" # Torque OFF
47
+ GravityCompensation = "gravity_compensation" # Torque ON and controlled in current to compensate for gravity
48
+
49
+
50
+ class Backend:
51
+ """Base class for robot backends, simulated or real."""
52
+
53
+ def __init__(
54
+ self,
55
+ log_level: str = "INFO",
56
+ check_collision: bool = False,
57
+ kinematics_engine: str = "AnalyticalKinematics",
58
+ use_audio: bool = True,
59
+ wireless_version: bool = False,
60
+ ) -> None:
61
+ """Initialize the backend."""
62
+ self.logger = logging.getLogger(__name__)
63
+ self.logger.setLevel(log_level)
64
+
65
+ self.use_audio = use_audio
66
+
67
+ self.should_stop = threading.Event()
68
+ self.ready = threading.Event()
69
+
70
+ self.check_collision = (
71
+ check_collision # Flag to enable/disable collision checking
72
+ )
73
+ self.kinematics_engine = kinematics_engine
74
+
75
+ self.logger.info(f"Using {self.kinematics_engine} kinematics engine")
76
+
77
+ if self.check_collision:
78
+ assert self.kinematics_engine == "Placo", (
79
+ "Collision checking is only available with Placo Kinematics"
80
+ )
81
+
82
+ self.gravity_compensation_mode = False # Flag for gravity compensation mode
83
+
84
+ if self.gravity_compensation_mode:
85
+ assert self.kinematics_engine == "Placo", (
86
+ "Gravity compensation is only available with Placo kinematics"
87
+ )
88
+
89
+ if self.kinematics_engine == "Placo":
90
+ from reachy_mini.kinematics import PlacoKinematics
91
+
92
+ self.head_kinematics: AnyKinematics = PlacoKinematics(
93
+ URDF_ROOT_PATH, check_collision=self.check_collision
94
+ )
95
+ elif self.kinematics_engine == "NN":
96
+ from reachy_mini.kinematics import NNKinematics
97
+
98
+ self.head_kinematics = NNKinematics(MODELS_ROOT_PATH)
99
+ elif self.kinematics_engine == "AnalyticalKinematics":
100
+ from reachy_mini.kinematics import AnalyticalKinematics
101
+
102
+ self.head_kinematics = AnalyticalKinematics()
103
+ else:
104
+ raise ValueError(
105
+ f"Unknown kinematics engine: {self.kinematics_engine}. Use 'Placo', 'NN' or 'AnalyticalKinematics'."
106
+ )
107
+
108
+ self.current_head_pose: Annotated[NDArray[np.float64], (4, 4)] | None = (
109
+ None # 4x4 pose matrix
110
+ )
111
+ self.target_head_pose: Annotated[NDArray[np.float64], (4, 4)] | None = (
112
+ None # 4x4 pose matrix
113
+ )
114
+ self.target_body_yaw: float | None = (
115
+ None # Last body yaw used in IK computations
116
+ )
117
+
118
+ self.target_head_joint_positions: (
119
+ Annotated[NDArray[np.float64], (7,)] | None
120
+ ) = None # [yaw, 0, 1, 2, 3, 4, 5]
121
+ self.current_head_joint_positions: (
122
+ Annotated[NDArray[np.float64], (7,)] | None
123
+ ) = None # [yaw, 0, 1, 2, 3, 4, 5]
124
+ self.target_antenna_joint_positions: (
125
+ Annotated[NDArray[np.float64], (2,)] | None
126
+ ) = None # [0, 1]
127
+ self.current_antenna_joint_positions: (
128
+ Annotated[NDArray[np.float64], (2,)] | None
129
+ ) = None # [0, 1]
130
+
131
+ self.joint_positions_publisher: zenoh.Publisher | None = None
132
+ self.pose_publisher: zenoh.Publisher | None = None
133
+ self.recording_publisher: zenoh.Publisher | None = None
134
+ self.error: str | None = None # To store any error that occurs during execution
135
+ self.is_recording = False # Flag to indicate if recording is active
136
+ self.recorded_data: list[dict[str, Any]] = [] # List to store recorded data
137
+
138
+ # variables to store the last computed head joint positions and pose
139
+ self._last_target_body_yaw: float | None = (
140
+ None # Last body yaw used in IK computations
141
+ )
142
+ self._last_target_head_pose: Annotated[NDArray[np.float64], (4, 4)] | None = (
143
+ None # Last head pose used in IK computations
144
+ )
145
+ self.target_head_joint_current: Annotated[NDArray[np.float64], (7,)] | None = (
146
+ None # Placeholder for head joint torque
147
+ )
148
+ self.ik_required = False # Flag to indicate if IK computation is required
149
+
150
+ self.is_shutting_down = False
151
+
152
+ # Tolerance for kinematics computations
153
+ # For Forward kinematics (around 0.25deg)
154
+ # - FK is calculated at each timestep and is susceptible to noise
155
+ self._fk_kin_tolerance = 1e-3 # rads
156
+ # For Inverse kinematics (around 0.5mm and 0.1 degrees)
157
+ # - IK is calculated only when the head pose is set by the user
158
+ self._ik_kin_tolerance = {
159
+ "rad": 2e-3, # rads
160
+ "m": 0.5e-3, # m
161
+ }
162
+
163
+ # Recording lock to guard buffer swaps and appends
164
+ self._rec_lock = threading.Lock()
165
+
166
+ self.audio: Optional[MediaManager] = None
167
+ if self.use_audio:
168
+ if wireless_version:
169
+ self.logger.debug(
170
+ "Initializing daemon audio backend for wireless version."
171
+ )
172
+ self.audio = MediaManager(
173
+ backend=MediaBackend.GSTREAMER_NO_VIDEO, log_level=log_level
174
+ )
175
+ else:
176
+ self.logger.debug(
177
+ "Initializing daemon audio backend for non-wireless version."
178
+ )
179
+ self.audio = MediaManager(
180
+ backend=MediaBackend.DEFAULT_NO_VIDEO, log_level=log_level
181
+ )
182
+
183
+ # Guard to ensure only one play_move/goto is executed at a time (goto itself uses play_move, so we need an RLock)
184
+ self._play_move_lock = threading.RLock()
185
+ self._active_move_depth = 0 # Tracks nested acquisitions within the owning thread
186
+
187
+ # Life cycle methods
188
+ def wrapped_run(self) -> None:
189
+ """Run the backend in a try-except block to store errors."""
190
+ try:
191
+ self.run()
192
+ except Exception as e:
193
+ self.error = str(e)
194
+ self.close()
195
+ raise e
196
+
197
+ def run(self) -> None:
198
+ """Run the backend.
199
+
200
+ This method is a placeholder and should be overridden by subclasses.
201
+ """
202
+ raise NotImplementedError("The method run should be overridden by subclasses.")
203
+
204
+ def close(self) -> None:
205
+ """Close the backend.
206
+
207
+ This method is a placeholder and should be overridden by subclasses.
208
+ """
209
+ raise NotImplementedError(
210
+ "The method close should be overridden by subclasses."
211
+ )
212
+
213
+ @property
214
+ def is_move_running(self) -> bool:
215
+ """Return True if a move is currently executing."""
216
+ return self._active_move_depth > 0
217
+
218
+ def _try_start_move(self) -> bool:
219
+ """Attempt to acquire the move guard, returning False if another client already owns it."""
220
+ if not self._play_move_lock.acquire(blocking=False):
221
+ return False
222
+ self._active_move_depth += 1
223
+ return True
224
+
225
+ def _end_move(self) -> None:
226
+ """Release the move guard; paired with every successful _try_start_move()."""
227
+ if self._active_move_depth > 0:
228
+ self._active_move_depth -= 1
229
+ self._play_move_lock.release()
230
+
231
+ def get_status(self) -> "RobotBackendStatus | MujocoBackendStatus":
232
+ """Return backend statistics.
233
+
234
+ This method is a placeholder and should be overridden by subclasses.
235
+ """
236
+ raise NotImplementedError(
237
+ "The method get_status should be overridden by subclasses."
238
+ )
239
+
240
+ # Present/Target joint positions
241
+ def set_joint_positions_publisher(self, publisher: zenoh.Publisher) -> None:
242
+ """Set the publisher for joint positions.
243
+
244
+ Args:
245
+ publisher: A publisher object that will be used to publish joint positions.
246
+
247
+ """
248
+ self.joint_positions_publisher = publisher
249
+
250
+ def set_pose_publisher(self, publisher: zenoh.Publisher) -> None:
251
+ """Set the publisher for head pose.
252
+
253
+ Args:
254
+ publisher: A publisher object that will be used to publish head pose.
255
+
256
+ """
257
+ self.pose_publisher = publisher
258
+
259
+ def update_target_head_joints_from_ik(
260
+ self,
261
+ pose: Annotated[NDArray[np.float64], (4, 4)] | None = None,
262
+ body_yaw: float | None = None,
263
+ ) -> None:
264
+ """Update the target head joint positions from inverse kinematics.
265
+
266
+ Args:
267
+ pose (np.ndarray): 4x4 pose matrix representing the head pose.
268
+ body_yaw (float): The yaw angle of the body, used to adjust the head pose.
269
+
270
+ """
271
+ if pose is None:
272
+ pose = (
273
+ self.target_head_pose
274
+ if self.target_head_pose is not None
275
+ else np.eye(4)
276
+ )
277
+
278
+ if body_yaw is None:
279
+ body_yaw = self.target_body_yaw if self.target_body_yaw is not None else 0.0
280
+
281
+ # Compute the inverse kinematics to get the head joint positions
282
+ joints = self.head_kinematics.ik(pose, body_yaw=body_yaw)
283
+ if joints is None or np.any(np.isnan(joints)):
284
+ raise ValueError("WARNING: Collision detected or head pose not achievable!")
285
+
286
+ # update the target head pose and body yaw
287
+ self._last_target_head_pose = pose
288
+ self._last_target_body_yaw = body_yaw
289
+
290
+ self.target_head_joint_positions = joints
291
+
292
+ def set_target_head_pose(
293
+ self,
294
+ pose: Annotated[NDArray[np.float64], (4, 4)],
295
+ ) -> None:
296
+ """Set the target head pose for the robot.
297
+
298
+ Args:
299
+ pose (np.ndarray): 4x4 pose matrix representing the head pose.
300
+
301
+ """
302
+ self.target_head_pose = pose
303
+ self.ik_required = True
304
+
305
+ def set_target_body_yaw(self, body_yaw: float) -> None:
306
+ """Set the target body yaw for the robot.
307
+
308
+ Only used when doing a set_target() with a standalone body_yaw (no head pose).
309
+
310
+ Args:
311
+ body_yaw (float): The yaw angle of the body
312
+
313
+ """
314
+ self.target_body_yaw = body_yaw
315
+ self.ik_required = True # Do we need that here?
316
+
317
+ def set_target_head_joint_positions(
318
+ self, positions: Annotated[NDArray[np.float64], (7,)] | None
319
+ ) -> None:
320
+ """Set the head joint positions.
321
+
322
+ Args:
323
+ positions (List[float]): A list of joint positions for the head.
324
+
325
+ """
326
+ self.target_head_joint_positions = positions
327
+ self.ik_required = False
328
+
329
+ def set_target(
330
+ self,
331
+ head: Annotated[NDArray[np.float64], (4, 4)] | None = None, # 4x4 pose matrix
332
+ antennas: Annotated[NDArray[np.float64], (2,)]
333
+ | None = None, # [right_angle, left_angle] (in rads)
334
+ body_yaw: float | None = None, # Body yaw angle in radians
335
+ ) -> None:
336
+ """Set the target head pose and/or antenna positions and/or body_yaw."""
337
+ if head is not None:
338
+ self.set_target_head_pose(head)
339
+
340
+ if body_yaw is not None:
341
+ self.set_target_body_yaw(body_yaw)
342
+
343
+ if antennas is not None:
344
+ self.set_target_antenna_joint_positions(antennas)
345
+
346
+ def set_target_antenna_joint_positions(
347
+ self,
348
+ positions: Annotated[NDArray[np.float64], (2,)],
349
+ ) -> None:
350
+ """Set the antenna joint positions.
351
+
352
+ Args:
353
+ positions (List[float]): A list of joint positions for the antenna.
354
+
355
+ """
356
+ self.target_antenna_joint_positions = positions
357
+
358
+ def set_target_head_joint_current(
359
+ self,
360
+ current: Annotated[NDArray[np.float64], (7,)],
361
+ ) -> None:
362
+ """Set the head joint current.
363
+
364
+ Args:
365
+ current (Annotated[NDArray[np.float64], (7,)]): A list of current values for the head motors.
366
+
367
+ """
368
+ self.target_head_joint_current = current
369
+ self.ik_required = False
370
+
371
+ async def play_move(
372
+ self,
373
+ move: Move,
374
+ play_frequency: float = 100.0,
375
+ initial_goto_duration: float = 0.0,
376
+ ) -> None:
377
+ """Asynchronously play a Move.
378
+
379
+ Args:
380
+ move (Move): The Move object to be played.
381
+ play_frequency (float): The frequency at which to evaluate the move (in Hz).
382
+ initial_goto_duration (float): Duration for an initial goto to the move's starting position. If 0.0, no initial goto is performed.
383
+
384
+ """
385
+ if not self._try_start_move():
386
+ self.logger.warning("Ignoring play_move request: another move is running.")
387
+ return
388
+
389
+ try:
390
+ if initial_goto_duration > 0.0:
391
+ start_head_pose, start_antennas_positions, start_body_yaw = move.evaluate(
392
+ 0.0
393
+ )
394
+ await self.goto_target(
395
+ head=start_head_pose,
396
+ antennas=start_antennas_positions,
397
+ duration=initial_goto_duration,
398
+ body_yaw=start_body_yaw,
399
+ )
400
+ sleep_period = 1.0 / play_frequency
401
+
402
+ if move.sound_path is not None and self.audio is not None:
403
+ self.play_sound(str(move.sound_path))
404
+
405
+ t0 = time.time()
406
+ while time.time() - t0 < move.duration:
407
+ t = time.time() - t0
408
+
409
+ head, antennas, body_yaw = move.evaluate(t)
410
+ if head is not None:
411
+ self.set_target_head_pose(head)
412
+ if body_yaw is not None:
413
+ self.set_target_body_yaw(body_yaw)
414
+ if antennas is not None:
415
+ self.set_target_antenna_joint_positions(antennas)
416
+
417
+ elapsed = time.time() - t0 - t
418
+ if elapsed < sleep_period:
419
+ await asyncio.sleep(sleep_period - elapsed)
420
+ else:
421
+ await asyncio.sleep(0.001)
422
+ finally:
423
+ if move.sound_path is not None and self.audio is not None:
424
+ # release audio resources after playing the move sound
425
+ self.audio.stop_playing()
426
+ self._end_move()
427
+
428
+ async def goto_target(
429
+ self,
430
+ head: Annotated[NDArray[np.float64], (4, 4)] | None = None, # 4x4 pose matrix
431
+ antennas: Annotated[NDArray[np.float64], (2,)]
432
+ | None = None, # [right_angle, left_angle] (in rads)
433
+ duration: float = 0.5, # Duration in seconds for the movement, default is 0.5 seconds.
434
+ method: InterpolationTechnique = InterpolationTechnique.MIN_JERK, # can be "linear", "minjerk", "ease" or "cartoon", default is "minjerk"
435
+ body_yaw: float | None = 0.0, # Body yaw angle in radians
436
+ ) -> None:
437
+ """Asynchronously go to a target head pose and/or antennas position using task space interpolation, in "duration" seconds.
438
+
439
+ Args:
440
+ head (np.ndarray | None): 4x4 pose matrix representing the target head pose.
441
+ antennas (np.ndarray | list[float] | None): 1D array with two elements representing the angles of the antennas in radians.
442
+ duration (float): Duration of the movement in seconds.
443
+ method (str): Interpolation method to use ("linear", "minjerk", "ease", "cartoon"). Default is "minjerk".
444
+ body_yaw (float | None): Body yaw angle in radians.
445
+
446
+ Raises:
447
+ ValueError: If neither head nor antennas are provided, or if duration is not positive.
448
+
449
+ """
450
+ return await self.play_move(
451
+ move=GotoMove(
452
+ start_head_pose=self.get_present_head_pose(),
453
+ target_head_pose=head,
454
+ start_body_yaw=self.get_present_body_yaw(),
455
+ target_body_yaw=body_yaw,
456
+ start_antennas=np.array(self.get_present_antenna_joint_positions()),
457
+ target_antennas=np.array(antennas) if antennas is not None else None,
458
+ duration=duration,
459
+ method=method,
460
+ )
461
+ )
462
+
463
+ async def goto_joint_positions(
464
+ self,
465
+ head_joint_positions: list[float]
466
+ | None = None, # [yaw, stewart_platform x 6] length 7
467
+ antennas_joint_positions: list[float]
468
+ | None = None, # [right_angle, left_angle] length 2
469
+ duration: float = 0.5, # Duration in seconds for the movement
470
+ method: InterpolationTechnique = InterpolationTechnique.MIN_JERK, # can be "linear", "minjerk", "ease" or "cartoon", default is "minjerk"
471
+ ) -> None:
472
+ """Asynchronously go to a target head joint positions and/or antennas joint positions using joint space interpolation, in "duration" seconds.
473
+
474
+ Go to a target head joint positions and/or antennas joint positions using joint space interpolation, in "duration" seconds.
475
+
476
+ Args:
477
+ head_joint_positions (Optional[List[float]]): List of head joint positions in radians (length 7).
478
+ antennas_joint_positions (Optional[List[float]]): List of antennas joint positions in radians (length 2).
479
+ duration (float): Duration of the movement in seconds. Default is 0.5 seconds.
480
+ method (str): Interpolation method to use ("linear", "minjerk", "ease", "cartoon"). Default is "minjerk".
481
+
482
+ Raises:
483
+ ValueError: If neither head_joint_positions nor antennas_joint_positions are provided, or if duration is not positive.
484
+
485
+ """
486
+ if duration <= 0.0:
487
+ raise ValueError(
488
+ "Duration must be positive and non-zero. Use set_target() for immediate position setting."
489
+ )
490
+
491
+ start_head = np.array(self.get_present_head_joint_positions())
492
+ start_antennas = np.array(self.get_present_antenna_joint_positions())
493
+
494
+ target_head = (
495
+ np.array(head_joint_positions)
496
+ if head_joint_positions is not None
497
+ else start_head
498
+ )
499
+ target_antennas = (
500
+ np.array(antennas_joint_positions)
501
+ if antennas_joint_positions is not None
502
+ else start_antennas
503
+ )
504
+
505
+ t0 = time.time()
506
+ while time.time() - t0 < duration:
507
+ t = time.time() - t0
508
+
509
+ interp_time = time_trajectory(t / duration, method=method)
510
+
511
+ head_joint = start_head + (target_head - start_head) * interp_time
512
+ antennas_joint = (
513
+ start_antennas + (target_antennas - start_antennas) * interp_time
514
+ )
515
+
516
+ self.set_target_head_joint_positions(head_joint)
517
+ self.set_target_antenna_joint_positions(antennas_joint)
518
+ await asyncio.sleep(0.01)
519
+
520
+ def set_recording_publisher(self, publisher: zenoh.Publisher) -> None:
521
+ """Set the publisher for recording data.
522
+
523
+ Args:
524
+ publisher: A publisher object that will be used to publish recorded data.
525
+
526
+ """
527
+ self.recording_publisher = publisher
528
+
529
+ def append_record(self, record: dict[str, Any]) -> None:
530
+ """Append a record to the recorded data.
531
+
532
+ Args:
533
+ record (dict): A dictionary containing the record data to be appended.
534
+
535
+ """
536
+ if not self.is_recording:
537
+ return
538
+ # Double-check under lock to avoid race with stop_recording
539
+ with self._rec_lock:
540
+ if self.is_recording:
541
+ self.recorded_data.append(record)
542
+
543
+ def start_recording(self) -> None:
544
+ """Start recording data."""
545
+ with self._rec_lock:
546
+ self.recorded_data = []
547
+ self.is_recording = True
548
+
549
+ def stop_recording(self) -> None:
550
+ """Stop recording data and publish the recorded data."""
551
+ # Swap buffer under lock so writers cannot touch the published list
552
+ with self._rec_lock:
553
+ self.is_recording = False
554
+ recorded_data, self.recorded_data = self.recorded_data, []
555
+ # Publish outside the lock
556
+ if self.recording_publisher is not None:
557
+ self.recording_publisher.put(json.dumps(recorded_data))
558
+ else:
559
+ self.logger.warning(
560
+ "stop_recording called but recording_publisher is not set; dropping data."
561
+ )
562
+
563
+ def get_present_head_joint_positions(self) -> Annotated[NDArray[np.float64], (7,)]:
564
+ """Return the present head joint positions.
565
+
566
+ This method is a placeholder and should be overridden by subclasses.
567
+ """
568
+ raise NotImplementedError(
569
+ "The method get_present_head_joint_positions should be overridden by subclasses."
570
+ )
571
+
572
+ def get_present_body_yaw(self) -> float:
573
+ """Return the present body yaw."""
574
+ yaw: float = self.get_present_head_joint_positions()[0]
575
+ return yaw
576
+
577
+ def get_present_head_pose(self) -> Annotated[NDArray[np.float64], (4, 4)]:
578
+ """Return the present head pose as a 4x4 matrix."""
579
+ assert self.current_head_pose is not None, (
580
+ "The current head pose is not set. Please call the update_head_kinematics_model method first."
581
+ )
582
+ return self.current_head_pose
583
+
584
+ def get_current_head_pose(self) -> Annotated[NDArray[np.float64], (4, 4)]:
585
+ """Return the present head pose as a 4x4 matrix."""
586
+ return self.get_present_head_pose()
587
+
588
+ def get_present_antenna_joint_positions(
589
+ self,
590
+ ) -> Annotated[NDArray[np.float64], (2,)]:
591
+ """Return the present antenna joint positions.
592
+
593
+ This method is a placeholder and should be overridden by subclasses.
594
+ """
595
+ raise NotImplementedError(
596
+ "The method get_present_antenna_joint_positions should be overridden by subclasses."
597
+ )
598
+
599
+ # Kinematics methods
600
+ def update_head_kinematics_model(
601
+ self,
602
+ head_joint_positions: Annotated[NDArray[np.float64], (7,)] | None = None,
603
+ antennas_joint_positions: Annotated[NDArray[np.float64], (2,)] | None = None,
604
+ ) -> None:
605
+ """Update the placo kinematics of the robot.
606
+
607
+ Args:
608
+ head_joint_positions (List[float] | None): The joint positions of the head.
609
+ antennas_joint_positions (List[float] | None): The joint positions of the antennas.
610
+
611
+ Returns:
612
+ None: This method does not return anything.
613
+
614
+ This method updates the head kinematics model with the given joint positions.
615
+ - If the joint positions are not provided, it will use the current joint positions.
616
+ - If the head joint positions have not changed, it will return without recomputing the forward kinematics.
617
+ - If the head joint positions have changed, it will compute the forward kinematics to get the current head pose.
618
+ - If the forward kinematics fails, it will raise an assertion error.
619
+ - If the antennas joint positions are provided, it will update the current antenna joint positions.
620
+
621
+ Note:
622
+ This method will update the `current_head_pose` and `current_head_joint_positions`
623
+ attributes of the backend instance with the computed values. And the `current_antenna_joint_positions` if provided.
624
+
625
+ """
626
+ if head_joint_positions is None:
627
+ head_joint_positions = self.get_present_head_joint_positions()
628
+
629
+ # Compute the forward kinematics to get the current head pose
630
+ self.current_head_pose = self.head_kinematics.fk(head_joint_positions)
631
+
632
+ # Check if the FK was successful
633
+ assert self.current_head_pose is not None, (
634
+ "FK failed to compute the current head pose."
635
+ )
636
+
637
+ # Store the last head joint positions
638
+ self.current_head_joint_positions = head_joint_positions
639
+
640
+ if antennas_joint_positions is not None:
641
+ self.current_antenna_joint_positions = antennas_joint_positions
642
+
643
+ def set_automatic_body_yaw(self, body_yaw: bool) -> None:
644
+ """Set the automatic body yaw.
645
+
646
+ Args:
647
+ body_yaw (bool): The yaw angle of the body.
648
+
649
+ """
650
+ self.head_kinematics.set_automatic_body_yaw(automatic_body_yaw=body_yaw)
651
+
652
+ def get_urdf(self) -> str:
653
+ """Get the URDF representation of the robot."""
654
+ urdf_path = Path(URDF_ROOT_PATH) / "robot.urdf"
655
+
656
+ with open(urdf_path, "r") as f:
657
+ return f.read()
658
+
659
+ # Multimedia methods
660
+ def play_sound(self, sound_file: str) -> None:
661
+ """Play a sound file from the assets directory.
662
+
663
+ If the file is not found in the assets directory, try to load the path itself.
664
+
665
+ Args:
666
+ sound_file (str): The name of the sound file to play (e.g., "wake_up.wav").
667
+
668
+ """
669
+ if self.audio:
670
+ self.audio.start_playing()
671
+ self.audio.play_sound(sound_file)
672
+
673
+ # Basic move definitions
674
+ INIT_HEAD_POSE = np.eye(4)
675
+
676
+ SLEEP_HEAD_JOINT_POSITIONS = [
677
+ 0,
678
+ -0.9848156658225817,
679
+ 1.2624661884298831,
680
+ -0.24390294527381684,
681
+ 0.20555342557667577,
682
+ -1.2363885150358267,
683
+ 1.0032234352772091,
684
+ ]
685
+
686
+ SLEEP_ANTENNAS_JOINT_POSITIONS = np.array((-3.05, 3.05))
687
+ SLEEP_HEAD_POSE = np.array(
688
+ [
689
+ [0.911, 0.004, 0.413, -0.021],
690
+ [-0.004, 1.0, -0.001, 0.001],
691
+ [-0.413, -0.001, 0.911, -0.044],
692
+ [0.0, 0.0, 0.0, 1.0],
693
+ ]
694
+ )
695
+
696
+ async def wake_up(self) -> None:
697
+ """Wake up the robot - go to the initial head position and play the wake up emote and sound."""
698
+ await asyncio.sleep(0.1)
699
+
700
+ _, _, magic_distance = distance_between_poses(
701
+ self.get_current_head_pose(), self.INIT_HEAD_POSE
702
+ )
703
+
704
+ await self.goto_target(
705
+ self.INIT_HEAD_POSE,
706
+ antennas=np.array((0.0, 0.0)),
707
+ duration=magic_distance * 20 / 1000, # ms_per_magic_mm = 10
708
+ )
709
+ await asyncio.sleep(0.1)
710
+
711
+ # Toudoum
712
+ self.play_sound("wake_up.wav")
713
+
714
+ # Roll 20° to the left
715
+ pose = self.INIT_HEAD_POSE.copy()
716
+ pose[:3, :3] = R.from_euler("xyz", [20, 0, 0], degrees=True).as_matrix()
717
+ await self.goto_target(pose, duration=0.2)
718
+
719
+ # Go back to the initial position
720
+ await self.goto_target(self.INIT_HEAD_POSE, duration=0.2)
721
+ if self.audio:
722
+ self.audio.stop_playing()
723
+
724
+ async def goto_sleep(self) -> None:
725
+ """Put the robot to sleep by moving the head and antennas to a predefined sleep position.
726
+
727
+ - If we are already very close to the sleep position, we do nothing.
728
+ - If we are far from the sleep position:
729
+ - If we are far from the initial position, we move there first.
730
+ - If we are close to the initial position, we move directly to the sleep position.
731
+ """
732
+ # Magic units
733
+ _, _, dist_to_sleep_pose = distance_between_poses(
734
+ self.get_current_head_pose(), self.SLEEP_HEAD_POSE
735
+ )
736
+ _, _, dist_to_init_pose = distance_between_poses(
737
+ self.get_current_head_pose(), self.INIT_HEAD_POSE
738
+ )
739
+ sleep_time = 2.0
740
+
741
+ # Thresholds found empirically.
742
+ if dist_to_sleep_pose > 10:
743
+ if dist_to_init_pose > 30:
744
+ # Move to the initial position
745
+ await self.goto_target(
746
+ self.INIT_HEAD_POSE, antennas=np.array((0.0, 0.0)), duration=1
747
+ )
748
+ await asyncio.sleep(0.2)
749
+
750
+ self.play_sound("go_sleep.wav")
751
+
752
+ # Move to the sleep position
753
+ await self.goto_target(
754
+ self.SLEEP_HEAD_POSE,
755
+ antennas=self.SLEEP_ANTENNAS_JOINT_POSITIONS,
756
+ duration=2,
757
+ )
758
+ else:
759
+ # The sound doesn't play fully if we don't wait enough
760
+ self.play_sound("go_sleep.wav")
761
+ sleep_time += 3
762
+
763
+ self._last_head_pose = self.SLEEP_HEAD_POSE
764
+ await asyncio.sleep(sleep_time)
765
+ if self.audio:
766
+ self.audio.stop_playing()
767
+
768
+ # Motor control modes
769
+ @abstractmethod
770
+ def get_motor_control_mode(self) -> MotorControlMode:
771
+ """Get the motor control mode."""
772
+ pass
773
+
774
+ @abstractmethod
775
+ def set_motor_control_mode(self, mode: MotorControlMode) -> None:
776
+ """Set the motor control mode."""
777
+ pass
778
+
779
+ @abstractmethod
780
+ def set_motor_torque_ids(self, ids: list[str], on: bool) -> None:
781
+ """Set the motor torque for specific motor names."""
782
+ pass
783
+
784
+ def get_present_passive_joint_positions(self) -> Optional[Dict[str, float]]:
785
+ """Get the present passive joint positions.
786
+
787
+ Requires the Placo kinematics engine.
788
+ """
789
+ # This is would be better, and fix mypy issues, but Placo is dynamically imported
790
+ # if not isinstance(self.head_kinematics, PlacoKinematics):
791
+ if self.kinematics_engine != "Placo":
792
+ return None
793
+ return {
794
+ "passive_1_x": self.head_kinematics.get_joint("passive_1_x"), # type: ignore [union-attr]
795
+ "passive_1_y": self.head_kinematics.get_joint("passive_1_y"), # type: ignore [union-attr]
796
+ "passive_1_z": self.head_kinematics.get_joint("passive_1_z"), # type: ignore [union-attr]
797
+ "passive_2_x": self.head_kinematics.get_joint("passive_2_x"), # type: ignore [union-attr]
798
+ "passive_2_y": self.head_kinematics.get_joint("passive_2_y"), # type: ignore [union-attr]
799
+ "passive_2_z": self.head_kinematics.get_joint("passive_2_z"), # type: ignore [union-attr]
800
+ "passive_3_x": self.head_kinematics.get_joint("passive_3_x"), # type: ignore [union-attr]
801
+ "passive_3_y": self.head_kinematics.get_joint("passive_3_y"), # type: ignore [union-attr]
802
+ "passive_3_z": self.head_kinematics.get_joint("passive_3_z"), # type: ignore [union-attr]
803
+ "passive_4_x": self.head_kinematics.get_joint("passive_4_x"), # type: ignore [union-attr]
804
+ "passive_4_y": self.head_kinematics.get_joint("passive_4_y"), # type: ignore [union-attr]
805
+ "passive_4_z": self.head_kinematics.get_joint("passive_4_z"), # type: ignore [union-attr]
806
+ "passive_5_x": self.head_kinematics.get_joint("passive_5_x"), # type: ignore [union-attr]
807
+ "passive_5_y": self.head_kinematics.get_joint("passive_5_y"), # type: ignore [union-attr]
808
+ "passive_5_z": self.head_kinematics.get_joint("passive_5_z"), # type: ignore [union-attr]
809
+ "passive_6_x": self.head_kinematics.get_joint("passive_6_x"), # type: ignore [union-attr]
810
+ "passive_6_y": self.head_kinematics.get_joint("passive_6_y"), # type: ignore [union-attr]
811
+ "passive_6_z": self.head_kinematics.get_joint("passive_6_z"), # type: ignore [union-attr]
812
+ "passive_7_x": self.head_kinematics.get_joint("passive_7_x"), # type: ignore [union-attr]
813
+ "passive_7_y": self.head_kinematics.get_joint("passive_7_y"), # type: ignore [union-attr]
814
+ "passive_7_z": self.head_kinematics.get_joint("passive_7_z"), # type: ignore [union-attr]
815
+ }