reachy-mini 1.0.0rc1__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.

Potentially problematic release.


This version of reachy-mini might be problematic. Click here for more details.

Files changed (359) hide show
  1. reachy_mini/__init__.py +4 -0
  2. reachy_mini/apps/__init__.py +23 -0
  3. reachy_mini/apps/app.py +119 -0
  4. reachy_mini/apps/manager.py +178 -0
  5. reachy_mini/apps/sources/__init__.py +4 -0
  6. reachy_mini/apps/sources/hf_space.py +25 -0
  7. reachy_mini/apps/sources/local_common_venv.py +38 -0
  8. reachy_mini/apps/templates/README.md.j2 +1 -0
  9. reachy_mini/apps/templates/main.py.j2 +46 -0
  10. reachy_mini/apps/templates/pyproject.toml.j2 +18 -0
  11. reachy_mini/apps/utils.py +30 -0
  12. reachy_mini/assets/config/hardware_config.yaml +119 -0
  13. reachy_mini/assets/confused1.wav +0 -0
  14. reachy_mini/assets/count.wav +0 -0
  15. reachy_mini/assets/dance1.wav +0 -0
  16. reachy_mini/assets/go_sleep.wav +0 -0
  17. reachy_mini/assets/impatient1.wav +0 -0
  18. reachy_mini/assets/kinematics_data.json +253 -0
  19. reachy_mini/assets/models/fknetwork.dynamic.onnx +3 -0
  20. reachy_mini/assets/models/fknetwork.onnx +3 -0
  21. reachy_mini/assets/models/fknetwork_int8.onnx +3 -0
  22. reachy_mini/assets/models/iknetwork.onnx +3 -0
  23. reachy_mini/assets/wake_up.wav +0 -0
  24. reachy_mini/daemon/__init__.py +1 -0
  25. reachy_mini/daemon/app/__init__.py +1 -0
  26. reachy_mini/daemon/app/dashboard/apps_manager.html +202 -0
  27. reachy_mini/daemon/app/dashboard/js/3rdparty/gstwebrtc-api-2.0.0.min.js +5 -0
  28. reachy_mini/daemon/app/dashboard/js/dashboard.js +121 -0
  29. reachy_mini/daemon/app/dashboard/live_robot_state.html +242 -0
  30. reachy_mini/daemon/app/dashboard/style.css +37 -0
  31. reachy_mini/daemon/app/dependencies.py +36 -0
  32. reachy_mini/daemon/app/main.py +271 -0
  33. reachy_mini/daemon/app/models.py +146 -0
  34. reachy_mini/daemon/app/routers/apps.py +220 -0
  35. reachy_mini/daemon/app/routers/daemon.py +53 -0
  36. reachy_mini/daemon/app/routers/kinematics.py +36 -0
  37. reachy_mini/daemon/app/routers/motors.py +41 -0
  38. reachy_mini/daemon/app/routers/move.py +200 -0
  39. reachy_mini/daemon/app/routers/state.py +137 -0
  40. reachy_mini/daemon/app/templates/dashboard.html +40 -0
  41. reachy_mini/daemon/backend/__init__.py +1 -0
  42. reachy_mini/daemon/backend/abstract.py +717 -0
  43. reachy_mini/daemon/backend/mujoco/__init__.py +36 -0
  44. reachy_mini/daemon/backend/mujoco/backend.py +304 -0
  45. reachy_mini/daemon/backend/mujoco/utils.py +59 -0
  46. reachy_mini/daemon/backend/mujoco/video_udp.py +53 -0
  47. reachy_mini/daemon/backend/robot/__init__.py +8 -0
  48. reachy_mini/daemon/backend/robot/backend.py +490 -0
  49. reachy_mini/daemon/daemon.py +442 -0
  50. reachy_mini/daemon/utils.py +114 -0
  51. reachy_mini/descriptions/reachy_mini/mjcf/additional.xml +6 -0
  52. reachy_mini/descriptions/reachy_mini/mjcf/assets/5w_speaker.part +13 -0
  53. reachy_mini/descriptions/reachy_mini/mjcf/assets/5w_speaker.stl +3 -0
  54. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna.part +13 -0
  55. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna.stl +3 -0
  56. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_body_3dprint.part +13 -0
  57. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_body_3dprint.stl +3 -0
  58. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_holder_l_3dprint.part +13 -0
  59. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_holder_l_3dprint.stl +3 -0
  60. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_holder_r_3dprint.part +13 -0
  61. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_holder_r_3dprint.stl +3 -0
  62. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_interface_3dprint.part +13 -0
  63. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_interface_3dprint.stl +3 -0
  64. reachy_mini/descriptions/reachy_mini/mjcf/assets/arducam.part +13 -0
  65. reachy_mini/descriptions/reachy_mini/mjcf/assets/arducam.stl +3 -0
  66. reachy_mini/descriptions/reachy_mini/mjcf/assets/b3b_eh.part +13 -0
  67. reachy_mini/descriptions/reachy_mini/mjcf/assets/b3b_eh.stl +3 -0
  68. reachy_mini/descriptions/reachy_mini/mjcf/assets/b3b_eh_1.part +13 -0
  69. reachy_mini/descriptions/reachy_mini/mjcf/assets/b3b_eh_1.stl +3 -0
  70. reachy_mini/descriptions/reachy_mini/mjcf/assets/bearing_85x110x13.part +13 -0
  71. reachy_mini/descriptions/reachy_mini/mjcf/assets/bearing_85x110x13.stl +3 -0
  72. reachy_mini/descriptions/reachy_mini/mjcf/assets/big_lens_d40.part +13 -0
  73. reachy_mini/descriptions/reachy_mini/mjcf/assets/big_lens_d40.stl +3 -0
  74. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_down_3dprint.part +13 -0
  75. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_down_3dprint.stl +3 -0
  76. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_foot_3dprint.part +13 -0
  77. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_foot_3dprint.stl +3 -0
  78. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_top_3dprint.part +13 -0
  79. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_top_3dprint.stl +3 -0
  80. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_turning_3dprint.part +13 -0
  81. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_turning_3dprint.stl +3 -0
  82. reachy_mini/descriptions/reachy_mini/mjcf/assets/bts2_m2_6x8.part +13 -0
  83. reachy_mini/descriptions/reachy_mini/mjcf/assets/bts2_m2_6x8.stl +3 -0
  84. reachy_mini/descriptions/reachy_mini/mjcf/assets/croissant_1k.blend/croissant_1k.obj +3 -0
  85. reachy_mini/descriptions/reachy_mini/mjcf/assets/croissant_1k.blend/textures/croissant_diff_1k.png +3 -0
  86. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_b_dummy.part +13 -0
  87. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_b_dummy.stl +3 -0
  88. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_f_dummy.part +13 -0
  89. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_f_dummy.stl +3 -0
  90. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_m_dummy.part +13 -0
  91. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_m_dummy.stl +3 -0
  92. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_horn_dummy.part +13 -0
  93. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_horn_dummy.stl +3 -0
  94. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_led_cap2_dummy.part +13 -0
  95. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_led_cap2_dummy.stl +3 -0
  96. reachy_mini/descriptions/reachy_mini/mjcf/assets/food_apple_01_1k.blend/food_apple_01_1k.obj +3 -0
  97. reachy_mini/descriptions/reachy_mini/mjcf/assets/food_apple_01_1k.blend/textures/food_apple_01_diff_1k.png +3 -0
  98. reachy_mini/descriptions/reachy_mini/mjcf/assets/glasses_dolder_3dprint.part +13 -0
  99. reachy_mini/descriptions/reachy_mini/mjcf/assets/glasses_dolder_3dprint.stl +3 -0
  100. reachy_mini/descriptions/reachy_mini/mjcf/assets/head_back_3dprint.part +13 -0
  101. reachy_mini/descriptions/reachy_mini/mjcf/assets/head_back_3dprint.stl +3 -0
  102. reachy_mini/descriptions/reachy_mini/mjcf/assets/head_front_3dprint.part +13 -0
  103. reachy_mini/descriptions/reachy_mini/mjcf/assets/head_front_3dprint.stl +3 -0
  104. reachy_mini/descriptions/reachy_mini/mjcf/assets/head_mic_3dprint.part +13 -0
  105. reachy_mini/descriptions/reachy_mini/mjcf/assets/head_mic_3dprint.stl +3 -0
  106. reachy_mini/descriptions/reachy_mini/mjcf/assets/lens_cap_d30_3dprint.part +13 -0
  107. reachy_mini/descriptions/reachy_mini/mjcf/assets/lens_cap_d30_3dprint.stl +3 -0
  108. reachy_mini/descriptions/reachy_mini/mjcf/assets/lens_cap_d40_3dprint.part +13 -0
  109. reachy_mini/descriptions/reachy_mini/mjcf/assets/lens_cap_d40_3dprint.stl +3 -0
  110. reachy_mini/descriptions/reachy_mini/mjcf/assets/m12_fisheye_lens_1_8mm.part +13 -0
  111. reachy_mini/descriptions/reachy_mini/mjcf/assets/m12_fisheye_lens_1_8mm.stl +3 -0
  112. reachy_mini/descriptions/reachy_mini/mjcf/assets/mp01062_stewart_arm_3.part +13 -0
  113. reachy_mini/descriptions/reachy_mini/mjcf/assets/mp01062_stewart_arm_3.stl +3 -0
  114. reachy_mini/descriptions/reachy_mini/mjcf/assets/neck_reference_3dprint.part +13 -0
  115. reachy_mini/descriptions/reachy_mini/mjcf/assets/neck_reference_3dprint.stl +3 -0
  116. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10.part +13 -0
  117. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10.stl +3 -0
  118. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_1.part +13 -0
  119. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_1.stl +3 -0
  120. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_2.part +13 -0
  121. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_2.stl +3 -0
  122. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_3.part +13 -0
  123. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_3.stl +3 -0
  124. reachy_mini/descriptions/reachy_mini/mjcf/assets/pp01102_arducam_carter.part +13 -0
  125. reachy_mini/descriptions/reachy_mini/mjcf/assets/pp01102_arducam_carter.stl +3 -0
  126. reachy_mini/descriptions/reachy_mini/mjcf/assets/rubber_duck_toy_1k.blend/rubber_duck_toy_1k.obj +3 -0
  127. reachy_mini/descriptions/reachy_mini/mjcf/assets/rubber_duck_toy_1k.blend/textures/rubber_duck_toy_diff_1k.png +3 -0
  128. reachy_mini/descriptions/reachy_mini/mjcf/assets/small_lens_d30.part +13 -0
  129. reachy_mini/descriptions/reachy_mini/mjcf/assets/small_lens_d30.stl +3 -0
  130. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_ball.part +13 -0
  131. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_ball.stl +3 -0
  132. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_ball__2.part +13 -0
  133. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_ball__2.stl +3 -0
  134. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_rod.part +13 -0
  135. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_rod.stl +3 -0
  136. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_main_plate_3dprint.part +13 -0
  137. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_main_plate_3dprint.stl +3 -0
  138. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_tricap_3dprint.part +13 -0
  139. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_tricap_3dprint.stl +3 -0
  140. reachy_mini/descriptions/reachy_mini/mjcf/assets/wooden_table_02_1k.blend/textures/wooden_table_02_diff_1k.png +3 -0
  141. reachy_mini/descriptions/reachy_mini/mjcf/assets/wooden_table_02_1k.blend/wooden_table_02_1k.obj +3 -0
  142. reachy_mini/descriptions/reachy_mini/mjcf/config.json +21 -0
  143. reachy_mini/descriptions/reachy_mini/mjcf/joints_properties.xml +29 -0
  144. reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml +613 -0
  145. reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml.bak +442 -0
  146. reachy_mini/descriptions/reachy_mini/mjcf/scene.xml +24 -0
  147. reachy_mini/descriptions/reachy_mini/mjcf/scenes/empty.xml +27 -0
  148. reachy_mini/descriptions/reachy_mini/mjcf/scenes/minimal.xml +131 -0
  149. reachy_mini/descriptions/reachy_mini/urdf/assets/5w_speaker.part +13 -0
  150. reachy_mini/descriptions/reachy_mini/urdf/assets/5w_speaker.stl +3 -0
  151. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna.part +13 -0
  152. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna.stl +3 -0
  153. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_body_3dprint.part +13 -0
  154. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_body_3dprint.stl +3 -0
  155. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_holder_l_3dprint.part +13 -0
  156. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_holder_l_3dprint.stl +3 -0
  157. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_holder_r_3dprint.part +13 -0
  158. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_holder_r_3dprint.stl +3 -0
  159. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_interface_3dprint.part +13 -0
  160. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_interface_3dprint.stl +3 -0
  161. reachy_mini/descriptions/reachy_mini/urdf/assets/arducam.part +13 -0
  162. reachy_mini/descriptions/reachy_mini/urdf/assets/arducam.stl +3 -0
  163. reachy_mini/descriptions/reachy_mini/urdf/assets/arm.part +13 -0
  164. reachy_mini/descriptions/reachy_mini/urdf/assets/arm.stl +3 -0
  165. reachy_mini/descriptions/reachy_mini/urdf/assets/b3b_eh.part +13 -0
  166. reachy_mini/descriptions/reachy_mini/urdf/assets/b3b_eh.stl +3 -0
  167. reachy_mini/descriptions/reachy_mini/urdf/assets/b3b_eh_1.part +13 -0
  168. reachy_mini/descriptions/reachy_mini/urdf/assets/b3b_eh_1.stl +3 -0
  169. reachy_mini/descriptions/reachy_mini/urdf/assets/ball.part +13 -0
  170. reachy_mini/descriptions/reachy_mini/urdf/assets/ball.stl +3 -0
  171. reachy_mini/descriptions/reachy_mini/urdf/assets/bearing_85x110x13.part +13 -0
  172. reachy_mini/descriptions/reachy_mini/urdf/assets/bearing_85x110x13.stl +3 -0
  173. reachy_mini/descriptions/reachy_mini/urdf/assets/big_lens.part +13 -0
  174. reachy_mini/descriptions/reachy_mini/urdf/assets/big_lens.stl +3 -0
  175. reachy_mini/descriptions/reachy_mini/urdf/assets/big_lens_d40.part +13 -0
  176. reachy_mini/descriptions/reachy_mini/urdf/assets/big_lens_d40.stl +3 -0
  177. reachy_mini/descriptions/reachy_mini/urdf/assets/body_down_3dprint.part +13 -0
  178. reachy_mini/descriptions/reachy_mini/urdf/assets/body_down_3dprint.stl +3 -0
  179. reachy_mini/descriptions/reachy_mini/urdf/assets/body_foot_3dprint.part +13 -0
  180. reachy_mini/descriptions/reachy_mini/urdf/assets/body_foot_3dprint.stl +3 -0
  181. reachy_mini/descriptions/reachy_mini/urdf/assets/body_top_3dprint.part +13 -0
  182. reachy_mini/descriptions/reachy_mini/urdf/assets/body_top_3dprint.stl +3 -0
  183. reachy_mini/descriptions/reachy_mini/urdf/assets/body_turning_3dprint.part +13 -0
  184. reachy_mini/descriptions/reachy_mini/urdf/assets/body_turning_3dprint.stl +3 -0
  185. reachy_mini/descriptions/reachy_mini/urdf/assets/bottom_body.part +13 -0
  186. reachy_mini/descriptions/reachy_mini/urdf/assets/bottom_body.stl +3 -0
  187. reachy_mini/descriptions/reachy_mini/urdf/assets/bts2_m2_6x8.part +13 -0
  188. reachy_mini/descriptions/reachy_mini/urdf/assets/bts2_m2_6x8.stl +3 -0
  189. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_b_dummy.part +13 -0
  190. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_b_dummy.stl +3 -0
  191. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_f_dummy.part +13 -0
  192. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_f_dummy.stl +3 -0
  193. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_m_dummy.part +13 -0
  194. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_m_dummy.stl +3 -0
  195. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_horn_dummy.part +13 -0
  196. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_horn_dummy.stl +3 -0
  197. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_led_cap2_dummy.part +13 -0
  198. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_led_cap2_dummy.stl +3 -0
  199. reachy_mini/descriptions/reachy_mini/urdf/assets/drive_palonier__configuration_default.part +14 -0
  200. reachy_mini/descriptions/reachy_mini/urdf/assets/drive_palonier__configuration_default.stl +3 -0
  201. reachy_mini/descriptions/reachy_mini/urdf/assets/drive_palonier__configuration_simple_axe.part +14 -0
  202. reachy_mini/descriptions/reachy_mini/urdf/assets/drive_palonier__configuration_simple_axe.stl +3 -0
  203. reachy_mini/descriptions/reachy_mini/urdf/assets/eye_support.part +13 -0
  204. reachy_mini/descriptions/reachy_mini/urdf/assets/eye_support.stl +3 -0
  205. reachy_mini/descriptions/reachy_mini/urdf/assets/foot.part +13 -0
  206. reachy_mini/descriptions/reachy_mini/urdf/assets/foot.stl +3 -0
  207. reachy_mini/descriptions/reachy_mini/urdf/assets/glasses_dolder_3dprint.part +13 -0
  208. reachy_mini/descriptions/reachy_mini/urdf/assets/glasses_dolder_3dprint.stl +3 -0
  209. reachy_mini/descriptions/reachy_mini/urdf/assets/head_back_3dprint.part +13 -0
  210. reachy_mini/descriptions/reachy_mini/urdf/assets/head_back_3dprint.stl +3 -0
  211. reachy_mini/descriptions/reachy_mini/urdf/assets/head_front_3dprint.part +13 -0
  212. reachy_mini/descriptions/reachy_mini/urdf/assets/head_front_3dprint.stl +3 -0
  213. reachy_mini/descriptions/reachy_mini/urdf/assets/head_head_back.part +13 -0
  214. reachy_mini/descriptions/reachy_mini/urdf/assets/head_head_back.stl +3 -0
  215. reachy_mini/descriptions/reachy_mini/urdf/assets/head_interface.part +13 -0
  216. reachy_mini/descriptions/reachy_mini/urdf/assets/head_interface.stl +3 -0
  217. reachy_mini/descriptions/reachy_mini/urdf/assets/head_mic_3dprint.part +13 -0
  218. reachy_mini/descriptions/reachy_mini/urdf/assets/head_mic_3dprint.stl +3 -0
  219. reachy_mini/descriptions/reachy_mini/urdf/assets/head_shell_front.part +13 -0
  220. reachy_mini/descriptions/reachy_mini/urdf/assets/head_shell_front.stl +3 -0
  221. reachy_mini/descriptions/reachy_mini/urdf/assets/lens_cap_d30_3dprint.part +13 -0
  222. reachy_mini/descriptions/reachy_mini/urdf/assets/lens_cap_d30_3dprint.stl +3 -0
  223. reachy_mini/descriptions/reachy_mini/urdf/assets/lens_cap_d40_3dprint.part +13 -0
  224. reachy_mini/descriptions/reachy_mini/urdf/assets/lens_cap_d40_3dprint.stl +3 -0
  225. reachy_mini/descriptions/reachy_mini/urdf/assets/m12_fisheye_lens_1_8mm.part +13 -0
  226. reachy_mini/descriptions/reachy_mini/urdf/assets/m12_fisheye_lens_1_8mm.stl +3 -0
  227. reachy_mini/descriptions/reachy_mini/urdf/assets/m12_lens.part +13 -0
  228. reachy_mini/descriptions/reachy_mini/urdf/assets/m12_lens.stl +3 -0
  229. reachy_mini/descriptions/reachy_mini/urdf/assets/main_plate.part +13 -0
  230. reachy_mini/descriptions/reachy_mini/urdf/assets/main_plate.stl +3 -0
  231. reachy_mini/descriptions/reachy_mini/urdf/assets/mid_plate.part +13 -0
  232. reachy_mini/descriptions/reachy_mini/urdf/assets/mid_plate.stl +3 -0
  233. reachy_mini/descriptions/reachy_mini/urdf/assets/mp01062_stewart_arm_3.part +13 -0
  234. reachy_mini/descriptions/reachy_mini/urdf/assets/mp01062_stewart_arm_3.stl +3 -0
  235. reachy_mini/descriptions/reachy_mini/urdf/assets/neck_reference_3dprint.part +13 -0
  236. reachy_mini/descriptions/reachy_mini/urdf/assets/neck_reference_3dprint.stl +3 -0
  237. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10.part +13 -0
  238. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10.stl +3 -0
  239. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_1.part +13 -0
  240. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_1.stl +3 -0
  241. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_2.part +13 -0
  242. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_2.stl +3 -0
  243. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_3.part +13 -0
  244. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_3.stl +3 -0
  245. reachy_mini/descriptions/reachy_mini/urdf/assets/plateform.part +13 -0
  246. reachy_mini/descriptions/reachy_mini/urdf/assets/plateform.stl +3 -0
  247. reachy_mini/descriptions/reachy_mini/urdf/assets/pp00xxx_stewart_rod.part +13 -0
  248. reachy_mini/descriptions/reachy_mini/urdf/assets/pp00xxx_stewart_rod.stl +3 -0
  249. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01062_stewart_arm.part +13 -0
  250. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01062_stewart_arm.stl +3 -0
  251. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01063_stewart_plateform.part +13 -0
  252. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01063_stewart_plateform.stl +3 -0
  253. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01064_stewart_main_plate.part +13 -0
  254. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01064_stewart_main_plate.stl +3 -0
  255. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01065_stewart_side_plate.part +13 -0
  256. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01065_stewart_side_plate.stl +3 -0
  257. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01066_stewart_mid_plate.part +13 -0
  258. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01066_stewart_mid_plate.stl +3 -0
  259. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01067_bottom_body.part +13 -0
  260. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01067_bottom_body.stl +3 -0
  261. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01068_top_body.part +13 -0
  262. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01068_top_body.stl +3 -0
  263. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01069_head_shell_front.part +13 -0
  264. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01069_head_shell_front.stl +3 -0
  265. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01070_head_head_back.part +13 -0
  266. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01070_head_head_back.stl +3 -0
  267. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01071_turning_bowl.part +13 -0
  268. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01071_turning_bowl.stl +3 -0
  269. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01072_turning_end.part +13 -0
  270. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01072_turning_end.stl +3 -0
  271. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01078_glasses.part +13 -0
  272. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01078_glasses.stl +3 -0
  273. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01079_back_big_eye.part +13 -0
  274. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01079_back_big_eye.stl +3 -0
  275. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01080_back_small_eye.part +13 -0
  276. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01080_back_small_eye.stl +3 -0
  277. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01102_arducam_carter.part +13 -0
  278. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01102_arducam_carter.stl +3 -0
  279. reachy_mini/descriptions/reachy_mini/urdf/assets/rod.part +13 -0
  280. reachy_mini/descriptions/reachy_mini/urdf/assets/rod.stl +3 -0
  281. reachy_mini/descriptions/reachy_mini/urdf/assets/shape.part +13 -0
  282. reachy_mini/descriptions/reachy_mini/urdf/assets/shape.stl +3 -0
  283. reachy_mini/descriptions/reachy_mini/urdf/assets/side_plate.part +13 -0
  284. reachy_mini/descriptions/reachy_mini/urdf/assets/side_plate.stl +3 -0
  285. reachy_mini/descriptions/reachy_mini/urdf/assets/small_lens.part +13 -0
  286. reachy_mini/descriptions/reachy_mini/urdf/assets/small_lens.stl +3 -0
  287. reachy_mini/descriptions/reachy_mini/urdf/assets/small_lens_d30.part +13 -0
  288. reachy_mini/descriptions/reachy_mini/urdf/assets/small_lens_d30.stl +3 -0
  289. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_ball.part +13 -0
  290. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_ball.stl +3 -0
  291. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_ball__2.part +13 -0
  292. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_ball__2.stl +3 -0
  293. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_rod.part +13 -0
  294. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_rod.stl +3 -0
  295. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_main_plate_3dprint.part +13 -0
  296. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_main_plate_3dprint.stl +3 -0
  297. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_tricap_3dprint.part +13 -0
  298. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_tricap_3dprint.stl +3 -0
  299. reachy_mini/descriptions/reachy_mini/urdf/assets/test_antenna.part +13 -0
  300. reachy_mini/descriptions/reachy_mini/urdf/assets/test_antenna.stl +3 -0
  301. reachy_mini/descriptions/reachy_mini/urdf/assets/test_antenna_body.part +13 -0
  302. reachy_mini/descriptions/reachy_mini/urdf/assets/test_antenna_body.stl +3 -0
  303. reachy_mini/descriptions/reachy_mini/urdf/assets/top_body.part +13 -0
  304. reachy_mini/descriptions/reachy_mini/urdf/assets/top_body.stl +3 -0
  305. reachy_mini/descriptions/reachy_mini/urdf/assets/turning_bowl.part +13 -0
  306. reachy_mini/descriptions/reachy_mini/urdf/assets/turning_bowl.stl +3 -0
  307. reachy_mini/descriptions/reachy_mini/urdf/assets/uc_a37_rev_a_step.part +13 -0
  308. reachy_mini/descriptions/reachy_mini/urdf/assets/uc_a37_rev_a_step.stl +3 -0
  309. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0122topcabinetcase_95__configuration_default.part +14 -0
  310. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0122topcabinetcase_95__configuration_default.stl +3 -0
  311. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0122topcabinetcase_95__configuration_simple_axe.part +14 -0
  312. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0122topcabinetcase_95__configuration_simple_axe.stl +3 -0
  313. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0123middlecase_56__configuration_default.part +14 -0
  314. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0123middlecase_56__configuration_default.stl +3 -0
  315. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0123middlecase_56__configuration_simple_axe.part +14 -0
  316. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0123middlecase_56__configuration_simple_axe.stl +3 -0
  317. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0124bottomcase_45__configuration_default.part +14 -0
  318. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0124bottomcase_45__configuration_default.stl +3 -0
  319. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0124bottomcase_45__configuration_simple_axe.part +14 -0
  320. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0124bottomcase_45__configuration_simple_axe.stl +3 -0
  321. reachy_mini/descriptions/reachy_mini/urdf/config.json +18 -0
  322. reachy_mini/descriptions/reachy_mini/urdf/robot.urdf +3282 -0
  323. reachy_mini/descriptions/reachy_mini/urdf/robot.urdf.bak +3282 -0
  324. reachy_mini/descriptions/reachy_mini/urdf/robot_no_collision.urdf +2316 -0
  325. reachy_mini/io/__init__.py +1 -0
  326. reachy_mini/io/abstract.py +70 -0
  327. reachy_mini/io/protocol.py +44 -0
  328. reachy_mini/io/zenoh_client.py +258 -0
  329. reachy_mini/io/zenoh_server.py +183 -0
  330. reachy_mini/kinematics/__init__.py +68 -0
  331. reachy_mini/kinematics/analytical_kinematics.py +102 -0
  332. reachy_mini/kinematics/nn_kinematics.py +100 -0
  333. reachy_mini/kinematics/placo_kinematics.py +662 -0
  334. reachy_mini/media/__init__.py +1 -0
  335. reachy_mini/media/audio_base.py +75 -0
  336. reachy_mini/media/audio_gstreamer.py +194 -0
  337. reachy_mini/media/audio_sounddevice.py +207 -0
  338. reachy_mini/media/audio_utils.py +27 -0
  339. reachy_mini/media/camera_base.py +58 -0
  340. reachy_mini/media/camera_constants.py +13 -0
  341. reachy_mini/media/camera_gstreamer.py +144 -0
  342. reachy_mini/media/camera_opencv.py +61 -0
  343. reachy_mini/media/camera_utils.py +60 -0
  344. reachy_mini/media/media_manager.py +186 -0
  345. reachy_mini/motion/__init__.py +4 -0
  346. reachy_mini/motion/goto.py +71 -0
  347. reachy_mini/motion/move.py +36 -0
  348. reachy_mini/motion/recorded_move.py +132 -0
  349. reachy_mini/reachy_mini.py +705 -0
  350. reachy_mini/utils/__init__.py +46 -0
  351. reachy_mini/utils/constants.py +9 -0
  352. reachy_mini/utils/interpolation.py +227 -0
  353. reachy_mini/utils/parse_urdf_for_kinematics.py +85 -0
  354. reachy_mini-1.0.0rc1.dist-info/METADATA +261 -0
  355. reachy_mini-1.0.0rc1.dist-info/RECORD +359 -0
  356. reachy_mini-1.0.0rc1.dist-info/WHEEL +5 -0
  357. reachy_mini-1.0.0rc1.dist-info/entry_points.txt +3 -0
  358. reachy_mini-1.0.0rc1.dist-info/licenses/LICENSE +201 -0
  359. reachy_mini-1.0.0rc1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,75 @@
1
+ """Base classes for audio implementations.
2
+
3
+ The audio implementations support various backends and provide a unified
4
+ interface for audio input/output.
5
+ """
6
+
7
+ import logging
8
+ from abc import ABC, abstractmethod
9
+ from enum import Enum
10
+ from typing import Optional
11
+
12
+ import numpy as np
13
+ import numpy.typing as npt
14
+
15
+
16
+ class AudioBackend(Enum):
17
+ """Audio backends."""
18
+
19
+ SOUNDDEVICE = "sounddevice"
20
+ GSTREAMER = "gstreamer"
21
+
22
+
23
+ class AudioBase(ABC):
24
+ """Abstract class for opening and managing audio devices."""
25
+
26
+ def __init__(self, backend: AudioBackend, log_level: str = "INFO") -> None:
27
+ """Initialize the audio device."""
28
+ self.logger = logging.getLogger(__name__)
29
+ self.logger.setLevel(log_level)
30
+ self.backend = backend
31
+
32
+ @abstractmethod
33
+ def start_recording(self) -> None:
34
+ """Start recording audio."""
35
+ pass
36
+
37
+ @abstractmethod
38
+ def get_audio_sample(self) -> Optional[bytes | npt.NDArray[np.float32]]:
39
+ """Read audio data from the device. Returns the data or None if error."""
40
+ pass
41
+
42
+ @abstractmethod
43
+ def get_audio_samplerate(self) -> int:
44
+ """Return the samplerate of the audio device."""
45
+ pass
46
+
47
+ @abstractmethod
48
+ def stop_recording(self) -> None:
49
+ """Close the audio device and release resources."""
50
+ pass
51
+
52
+ @abstractmethod
53
+ def start_playing(self) -> None:
54
+ """Start playing audio."""
55
+ pass
56
+
57
+ @abstractmethod
58
+ def push_audio_sample(self, data: bytes) -> None:
59
+ """Push audio data to the output device."""
60
+ pass
61
+
62
+ @abstractmethod
63
+ def stop_playing(self) -> None:
64
+ """Stop playing audio and release resources."""
65
+ pass
66
+
67
+ @abstractmethod
68
+ def play_sound(self, sound_file: str) -> None:
69
+ """Play a sound file.
70
+
71
+ Args:
72
+ sound_file (str): Path to the sound file to play.
73
+
74
+ """
75
+ pass
@@ -0,0 +1,194 @@
1
+ """GStreamer camera backend.
2
+
3
+ This module provides an implementation of the CameraBase class using GStreamer.
4
+ By default the module directly returns JPEG images as output by the camera.
5
+ """
6
+
7
+ from threading import Thread
8
+ from typing import Optional
9
+
10
+ try:
11
+ import gi
12
+ except ImportError as e:
13
+ raise ImportError(
14
+ "The 'gi' module is required for GStreamerCamera but could not be imported. \
15
+ Please install the GStreamer backend: pip install .[gstreamer]."
16
+ ) from e
17
+
18
+ gi.require_version("Gst", "1.0")
19
+ gi.require_version("GstApp", "1.0")
20
+
21
+
22
+ from gi.repository import GLib, Gst, GstApp # noqa: E402
23
+
24
+ from .audio_base import AudioBackend, AudioBase # noqa: E402
25
+
26
+
27
+ class GStreamerAudio(AudioBase):
28
+ """Audio implementation using GStreamer."""
29
+
30
+ def __init__(self, log_level: str = "INFO") -> None:
31
+ """Initialize the GStreamer audio."""
32
+ super().__init__(backend=AudioBackend.GSTREAMER, log_level=log_level)
33
+ Gst.init(None)
34
+ self._loop = GLib.MainLoop()
35
+ self._thread_bus_calls = Thread(target=lambda: self._loop.run(), daemon=True)
36
+ self._thread_bus_calls.start()
37
+
38
+ self._samplerate = 24000
39
+
40
+ self._pipeline_record = Gst.Pipeline.new("audio_recorder")
41
+ self._appsink_audio: Optional[GstApp] = None
42
+ self._init_pipeline_record(self._pipeline_record)
43
+ self._bus_record = self._pipeline_record.get_bus()
44
+ self._bus_record.add_watch(
45
+ GLib.PRIORITY_DEFAULT, self._on_bus_message, self._loop
46
+ )
47
+
48
+ self._pipeline_playback = Gst.Pipeline.new("audio_player")
49
+ self._appsrc: Optional[GstApp] = None
50
+ self._init_pipeline_playback(self._pipeline_playback)
51
+ self._bus_playback = self._pipeline_playback.get_bus()
52
+ self._bus_playback.add_watch(
53
+ GLib.PRIORITY_DEFAULT, self._on_bus_message, self._loop
54
+ )
55
+
56
+ def _init_pipeline_record(self, pipeline: Gst.Pipeline) -> None:
57
+ self._appsink_audio = Gst.ElementFactory.make("appsink")
58
+ caps = Gst.Caps.from_string(
59
+ f"audio/x-raw,channels=1,rate={self._samplerate},format=S16LE"
60
+ )
61
+ self._appsink_audio.set_property("caps", caps)
62
+ self._appsink_audio.set_property("drop", True) # avoid overflow
63
+ self._appsink_audio.set_property("max-buffers", 200)
64
+
65
+ autoaudiosrc = Gst.ElementFactory.make("autoaudiosrc") # use default mic
66
+ # caps_respeaker = Gst.Caps.from_string(
67
+ # "audio/x-raw, layout=interleaved, format=S16LE, rate=16000, channels=2"
68
+ # )
69
+ # autoaudiosrc.set_property("filter-caps", caps_respeaker)
70
+ queue = Gst.ElementFactory.make("queue")
71
+ audioconvert = Gst.ElementFactory.make("audioconvert")
72
+ audioresample = Gst.ElementFactory.make("audioresample")
73
+
74
+ if not all(
75
+ [autoaudiosrc, queue, audioconvert, audioresample, self._appsink_audio]
76
+ ):
77
+ raise RuntimeError("Failed to create GStreamer elements")
78
+
79
+ pipeline.add(autoaudiosrc)
80
+ pipeline.add(queue)
81
+ pipeline.add(audioconvert)
82
+ pipeline.add(audioresample)
83
+ pipeline.add(self._appsink_audio)
84
+
85
+ autoaudiosrc.link(queue)
86
+ queue.link(audioconvert)
87
+ audioconvert.link(audioresample)
88
+ audioresample.link(self._appsink_audio)
89
+
90
+ def __del__(self) -> None:
91
+ """Destructor to ensure gstreamer resources are released."""
92
+ self._loop.quit()
93
+ self._bus_record.remove_watch()
94
+ self._bus_playback.remove_watch()
95
+
96
+ def _init_pipeline_playback(self, pipeline: Gst.Pipeline) -> None:
97
+ self._appsrc = Gst.ElementFactory.make("appsrc")
98
+ self._appsrc.set_property("format", Gst.Format.TIME)
99
+ self._appsrc.set_property("is-live", True)
100
+ caps = Gst.Caps.from_string(
101
+ f"audio/x-raw,format=F32LE,channels=1,rate={self._samplerate},layout=interleaved"
102
+ )
103
+ self._appsrc.set_property("caps", caps)
104
+
105
+ audioconvert = Gst.ElementFactory.make("audioconvert")
106
+ audioresample = Gst.ElementFactory.make("audioresample")
107
+
108
+ queue = Gst.ElementFactory.make("queue")
109
+ audiosink = Gst.ElementFactory.make("autoaudiosink") # use default speaker
110
+
111
+ pipeline.add(queue)
112
+ pipeline.add(audiosink)
113
+ pipeline.add(self._appsrc)
114
+ pipeline.add(audioconvert)
115
+ pipeline.add(audioresample)
116
+
117
+ self._appsrc.link(queue)
118
+ queue.link(audioconvert)
119
+ audioconvert.link(audioresample)
120
+ audioresample.link(audiosink)
121
+
122
+ def _on_bus_message(self, bus: Gst.Bus, msg: Gst.Message, loop) -> bool: # type: ignore[no-untyped-def]
123
+ t = msg.type
124
+ if t == Gst.MessageType.EOS:
125
+ self.logger.warning("End-of-stream")
126
+ return False
127
+
128
+ elif t == Gst.MessageType.ERROR:
129
+ err, debug = msg.parse_error()
130
+ self.logger.error(f"Error: {err} {debug}")
131
+ return False
132
+
133
+ return True
134
+
135
+ def start_recording(self) -> None:
136
+ """Open the audio card using GStreamer."""
137
+ self._pipeline_record.set_state(Gst.State.PLAYING)
138
+
139
+ def _get_sample(self, appsink: Gst.AppSink) -> Optional[bytes]:
140
+ sample = appsink.try_pull_sample(20_000_000)
141
+ if sample is None:
142
+ return None
143
+ data = None
144
+ if isinstance(sample, Gst.Sample):
145
+ buf = sample.get_buffer()
146
+ if buf is None:
147
+ self.logger.warning("Buffer is None")
148
+
149
+ data = buf.extract_dup(0, buf.get_size())
150
+ return data
151
+
152
+ def get_audio_sample(self) -> Optional[bytes]:
153
+ """Read a sample from the audio card. Returns the sample or None if error.
154
+
155
+ Returns:
156
+ Optional[bytes]: The captured sample in raw format, or None if error.
157
+
158
+ """
159
+ return self._get_sample(self._appsink_audio)
160
+
161
+ def get_audio_samplerate(self) -> int:
162
+ """Return the samplerate of the audio device."""
163
+ return self._samplerate
164
+
165
+ def stop_recording(self) -> None:
166
+ """Release the camera resource."""
167
+ self._pipeline_record.set_state(Gst.State.NULL)
168
+
169
+ def start_playing(self) -> None:
170
+ """Open the audio output using GStreamer."""
171
+ self._pipeline_playback.set_state(Gst.State.PLAYING)
172
+
173
+ def stop_playing(self) -> None:
174
+ """Stop playing audio and release resources."""
175
+ self._pipeline_playback.set_state(Gst.State.NULL)
176
+
177
+ def push_audio_sample(self, data: bytes) -> None:
178
+ """Push audio data to the output device."""
179
+ if self._appsrc is not None:
180
+ buf = Gst.Buffer.new_wrapped(data)
181
+ self._appsrc.push_buffer(buf)
182
+ else:
183
+ self.logger.warning(
184
+ "AppSrc is not initialized. Call start_playing() first."
185
+ )
186
+
187
+ def play_sound(self, sound_file: str) -> None:
188
+ """Play a sound file.
189
+
190
+ Args:
191
+ sound_file (str): Path to the sound file to play.
192
+
193
+ """
194
+ self.logger.warning("play_sound is not implemented for GStreamerAudio.")
@@ -0,0 +1,207 @@
1
+ """Audio implementation using sounddevice backend."""
2
+
3
+ import os
4
+ import threading
5
+ import time
6
+ from typing import Any, List, Optional
7
+
8
+ import numpy as np
9
+ import numpy.typing as npt
10
+ import scipy
11
+ import sounddevice as sd
12
+ import soundfile as sf
13
+
14
+ from reachy_mini.utils.constants import ASSETS_ROOT_PATH
15
+
16
+ from .audio_base import AudioBackend, AudioBase
17
+
18
+
19
+ class SoundDeviceAudio(AudioBase):
20
+ """Audio device implementation using sounddevice."""
21
+
22
+ def __init__(
23
+ self,
24
+ frames_per_buffer: int = 1024,
25
+ log_level: str = "INFO",
26
+ ) -> None:
27
+ """Initialize the SoundDevice audio device."""
28
+ super().__init__(backend=AudioBackend.SOUNDDEVICE, log_level=log_level)
29
+ self.frames_per_buffer = frames_per_buffer
30
+ self.stream = None
31
+ self._output_stream = None
32
+ self._buffer: List[npt.NDArray[np.float32]] = []
33
+ self._device_id = self.get_output_device_id("respeaker")
34
+ self._samplerate = (
35
+ -1
36
+ ) # will be set on first use to avoid issues if device is not present (CI)
37
+
38
+ def start_recording(self) -> None:
39
+ """Open the audio input stream, using ReSpeaker card if available."""
40
+ self.stream = sd.InputStream(
41
+ blocksize=self.frames_per_buffer,
42
+ device=self._device_id,
43
+ callback=self._callback,
44
+ )
45
+ if self.stream is None:
46
+ raise RuntimeError("Failed to open SoundDevice audio stream.")
47
+ self._buffer.clear()
48
+ self.stream.start()
49
+ self.logger.info("SoundDevice audio stream opened.")
50
+
51
+ def _callback(
52
+ self,
53
+ indata: npt.NDArray[np.float32],
54
+ frames: int,
55
+ time: int,
56
+ status: sd.CallbackFlags,
57
+ ) -> None:
58
+ if status:
59
+ self.logger.warning(f"SoundDevice status: {status}")
60
+
61
+ self._buffer.append(indata.copy())
62
+
63
+ def get_audio_sample(self) -> Optional[bytes | npt.NDArray[np.float32]]:
64
+ """Read audio data from the buffer. Returns numpy array or None if empty."""
65
+ if self._buffer and len(self._buffer) > 0:
66
+ data: npt.NDArray[np.float32] = np.concatenate(self._buffer, axis=0)
67
+ self._buffer.clear()
68
+ return data
69
+ self.logger.debug("No audio data available in buffer.")
70
+ return None
71
+
72
+ def get_audio_samplerate(self) -> int:
73
+ """Return the samplerate of the audio device."""
74
+ if self._samplerate == -1:
75
+ self._samplerate = int(
76
+ sd.query_devices(self._device_id)["default_samplerate"]
77
+ )
78
+ return self._samplerate
79
+
80
+ def stop_recording(self) -> None:
81
+ """Close the audio stream and release resources."""
82
+ if self.stream is not None:
83
+ self.stream.stop()
84
+ self.stream.close()
85
+ self.stream = None
86
+ self.logger.info("SoundDevice audio stream closed.")
87
+
88
+ def push_audio_sample(self, data: bytes) -> None:
89
+ """Push audio data to the output device."""
90
+ if self._output_stream is not None:
91
+ self._output_stream.write(data)
92
+ else:
93
+ self.logger.warning(
94
+ "Output stream is not open. Call start_playing() first."
95
+ )
96
+
97
+ def start_playing(self) -> None:
98
+ """Open the audio output stream."""
99
+ self._output_stream = sd.OutputStream(
100
+ samplerate=self.get_audio_samplerate(),
101
+ device=self._device_id,
102
+ channels=1,
103
+ )
104
+ if self._output_stream is None:
105
+ raise RuntimeError("Failed to open SoundDevice audio output stream.")
106
+ self._output_stream.start()
107
+
108
+ def stop_playing(self) -> None:
109
+ """Close the audio output stream."""
110
+ if self._output_stream is not None:
111
+ self._output_stream.stop()
112
+ self._output_stream.close()
113
+ self._output_stream = None
114
+ self.logger.info("SoundDevice audio output stream closed.")
115
+
116
+ def play_sound(self, sound_file: str, autoclean: bool = False) -> None:
117
+ """Play a sound file from the assets directory or a given path using sounddevice and soundfile."""
118
+ file_path = f"{ASSETS_ROOT_PATH}/{sound_file}"
119
+ if not os.path.exists(file_path):
120
+ raise FileNotFoundError(f"Sound file {file_path} not found.")
121
+
122
+ data, samplerate_in = sf.read(file_path, dtype="float32")
123
+
124
+ if samplerate_in != self.get_audio_samplerate():
125
+ data = scipy.signal.resample(
126
+ data, int(len(data) * (self.get_audio_samplerate() / samplerate_in))
127
+ )
128
+ if data.ndim > 1: # convert to mono
129
+ data = np.mean(data, axis=1)
130
+
131
+ self.logger.debug(f"Playing sound '{file_path}' at {samplerate_in} Hz")
132
+
133
+ self.stop_playing()
134
+ start = [0] # using list to modify in callback
135
+ length = len(data)
136
+
137
+ def callback(
138
+ outdata: npt.NDArray[np.float32],
139
+ frames: int,
140
+ time: Any, # cdata 'struct PaStreamCallbackTimeInfo *
141
+ status: sd.CallbackFlags,
142
+ ) -> None:
143
+ """Actual playback."""
144
+ if status:
145
+ self.logger.warning(f"SoundDevice output status: {status}")
146
+
147
+ end = start[0] + frames
148
+ if end > length:
149
+ # Fill the output buffer with the audio data, or zeros if finished
150
+ outdata[: length - start[0], 0] = data[start[0] :]
151
+ outdata[length - start[0] :, 0] = 0
152
+ raise sd.CallbackStop()
153
+ else:
154
+ outdata[:, 0] = data[start[0] : end]
155
+ start[0] = end
156
+
157
+ event = threading.Event()
158
+
159
+ self._output_stream = sd.OutputStream(
160
+ samplerate=self.get_audio_samplerate(),
161
+ device=self._device_id,
162
+ channels=1,
163
+ callback=callback,
164
+ finished_callback=event.set, # release the device when done
165
+ )
166
+ if self._output_stream is None:
167
+ raise RuntimeError("Failed to open SoundDevice audio output stream.")
168
+ self._output_stream.start()
169
+
170
+ def _clean_up_thread() -> None:
171
+ """Thread to clean up the output stream after playback.
172
+
173
+ The daemon may play sound but should release the audio device.
174
+ """
175
+ event.wait()
176
+ timeout = 5 # seconds
177
+ waited = 0
178
+ while (
179
+ self._output_stream is not None
180
+ and self._output_stream.active
181
+ and waited < timeout
182
+ ):
183
+ time.sleep(0.1)
184
+ waited += 0.1
185
+ self.stop_playing()
186
+
187
+ if autoclean:
188
+ threading.Thread(
189
+ target=_clean_up_thread,
190
+ daemon=True,
191
+ ).start()
192
+
193
+ def get_output_device_id(self, name_contains: str) -> int:
194
+ """Return the output device id whose name contains the given string (case-insensitive).
195
+
196
+ If not found, return the default output device id.
197
+ """
198
+ devices = sd.query_devices()
199
+
200
+ for idx, dev in enumerate(devices):
201
+ if name_contains.lower() in dev["name"].lower():
202
+ return idx
203
+ # Return default output device if not found
204
+ self.logger.warning(
205
+ f"No output device found containing '{name_contains}', using default."
206
+ )
207
+ return int(sd.default.device[1])
@@ -0,0 +1,27 @@
1
+ """Utility functions for audio handling, specifically for detecting the ReSpeaker sound card."""
2
+
3
+ import logging
4
+ import subprocess
5
+
6
+
7
+ def get_respeaker_card_number() -> int:
8
+ """Return the card number of the ReSpeaker sound card, or 0 if not found."""
9
+ try:
10
+ result = subprocess.run(
11
+ ["arecord", "-l"], capture_output=True, text=True, check=True
12
+ )
13
+ output = result.stdout
14
+
15
+ lines = output.split("\n")
16
+ for line in lines:
17
+ if "ReSpeaker" in line and "card" in line:
18
+ card_number = line.split(":")[0].split("card ")[1].strip()
19
+ logging.debug(f"Found ReSpeaker sound card: {card_number}")
20
+ return int(card_number)
21
+
22
+ logging.warning("ReSpeaker sound card not found. Returning default card")
23
+ return 0 # default sound card
24
+
25
+ except subprocess.CalledProcessError as e:
26
+ logging.error(f"Cannot find sound card: {e}")
27
+ return 0
@@ -0,0 +1,58 @@
1
+ """Base classes for camera implementations.
2
+
3
+ The camera implementations support various backends and provide a unified
4
+ interface for capturing images.
5
+ """
6
+
7
+ import logging
8
+ from abc import ABC, abstractmethod
9
+ from enum import Enum
10
+ from typing import Optional
11
+
12
+ import numpy as np
13
+ import numpy.typing as npt
14
+
15
+ from reachy_mini.media.camera_constants import CameraResolution
16
+
17
+
18
+ class CameraBackend(Enum):
19
+ """Camera backends."""
20
+
21
+ OPENCV = "opencv"
22
+ GSTREAMER = "gstreamer"
23
+
24
+
25
+ class CameraBase(ABC):
26
+ """Abstract class for opening and managing a camera."""
27
+
28
+ def __init__(
29
+ self,
30
+ backend: CameraBackend,
31
+ log_level: str = "INFO",
32
+ resolution: CameraResolution = CameraResolution.R1280x720,
33
+ ) -> None:
34
+ """Initialize the camera."""
35
+ self.logger = logging.getLogger(__name__)
36
+ self.logger.setLevel(log_level)
37
+ self.backend = backend
38
+ self._resolution = resolution
39
+
40
+ @property
41
+ def resolution(self) -> tuple[int, int]:
42
+ """Get the current camera resolution as a tuple (width, height)."""
43
+ return (self._resolution.value[0], self._resolution.value[1])
44
+
45
+ @abstractmethod
46
+ def open(self) -> None:
47
+ """Open the camera."""
48
+ pass
49
+
50
+ @abstractmethod
51
+ def read(self) -> Optional[bytes | npt.NDArray[np.uint8]]:
52
+ """Read an image from the camera. Returns the image or None if error."""
53
+ pass
54
+
55
+ @abstractmethod
56
+ def close(self) -> None:
57
+ """Close the camera and release resources."""
58
+ pass
@@ -0,0 +1,13 @@
1
+ """Camera constants for Reachy Mini."""
2
+
3
+ from enum import Enum
4
+
5
+
6
+ class CameraResolution(Enum):
7
+ """Camera resolutions. Arducam_12MP."""
8
+
9
+ R2304x1296 = (2304, 1296)
10
+ R4608x2592 = (4608, 2592)
11
+ R1920x1080 = (1920, 1080)
12
+ R1600x1200 = (1600, 1200)
13
+ R1280x720 = (1280, 720)