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,111 @@
1
+ """Camera utility for Reachy Mini."""
2
+
3
+ import platform
4
+ from typing import Optional, Tuple, cast
5
+
6
+ import cv2
7
+ from cv2_enumerate_cameras import enumerate_cameras
8
+
9
+ from reachy_mini.media.camera_constants import (
10
+ ArducamSpecs,
11
+ CameraSpecs,
12
+ OlderRPiCamSpecs,
13
+ ReachyMiniLiteCamSpecs,
14
+ )
15
+
16
+
17
+ def find_camera(
18
+ apiPreference: int = cv2.CAP_ANY, no_cap: bool = False
19
+ ) -> Tuple[Optional[cv2.VideoCapture], Optional[CameraSpecs]]:
20
+ """Find and return the Reachy Mini camera.
21
+
22
+ Looks for the Reachy Mini camera first, then Arducam, then older Raspberry Pi Camera. Returns None if no camera is found.
23
+
24
+ Args:
25
+ apiPreference (int): Preferred API backend for the camera. Default is cv2.CAP_ANY.
26
+ no_cap (bool): If True, close the camera after finding it. Default is False.
27
+
28
+ Returns:
29
+ cv2.VideoCapture | None: A VideoCapture object if the camera is found and opened successfully, otherwise None.
30
+
31
+ """
32
+ cap = find_camera_by_vid_pid(
33
+ ReachyMiniLiteCamSpecs.vid, ReachyMiniLiteCamSpecs.pid, apiPreference
34
+ )
35
+ if cap is not None:
36
+ fourcc = cv2.VideoWriter_fourcc("M", "J", "P", "G") # type: ignore
37
+ cap.set(cv2.CAP_PROP_FOURCC, fourcc)
38
+ if no_cap:
39
+ cap.release()
40
+ return cap, cast(CameraSpecs, ReachyMiniLiteCamSpecs)
41
+
42
+ cap = find_camera_by_vid_pid(
43
+ OlderRPiCamSpecs.vid, OlderRPiCamSpecs.pid, apiPreference
44
+ )
45
+ if cap is not None:
46
+ fourcc = cv2.VideoWriter_fourcc("M", "J", "P", "G") # type: ignore
47
+ cap.set(cv2.CAP_PROP_FOURCC, fourcc)
48
+ if no_cap:
49
+ cap.release()
50
+ return cap, cast(CameraSpecs, OlderRPiCamSpecs)
51
+
52
+ cap = find_camera_by_vid_pid(ArducamSpecs.vid, ArducamSpecs.pid, apiPreference)
53
+ if cap is not None:
54
+ if no_cap:
55
+ cap.release()
56
+ return cap, cast(CameraSpecs, ArducamSpecs)
57
+
58
+ return None, None
59
+
60
+
61
+ def find_camera_by_vid_pid(
62
+ vid: int = ReachyMiniLiteCamSpecs.vid,
63
+ pid: int = ReachyMiniLiteCamSpecs.pid,
64
+ apiPreference: int = cv2.CAP_ANY,
65
+ ) -> cv2.VideoCapture | None:
66
+ """Find and return a camera with the specified VID and PID.
67
+
68
+ Args:
69
+ vid (int): Vendor ID of the camera. Default is ReachyMiniCamera
70
+ pid (int): Product ID of the camera. Default is ReachyMiniCamera
71
+ apiPreference (int): Preferred API backend for the camera. Default is cv2.CAP_ANY.
72
+
73
+ Returns:
74
+ cv2.VideoCapture | None: A VideoCapture object if the camera is found and opened successfully, otherwise None.
75
+
76
+ """
77
+ if platform.system() == "Linux":
78
+ apiPreference = cv2.CAP_V4L2
79
+
80
+ selected_cap = None
81
+ for c in enumerate_cameras(apiPreference):
82
+ if c.vid == vid and c.pid == pid:
83
+ # the Arducam camera creates two /dev/videoX devices
84
+ # that enumerate_cameras cannot differentiate
85
+ try:
86
+ cap = cv2.VideoCapture(c.index, c.backend)
87
+ if cap.isOpened():
88
+ selected_cap = cap
89
+ except Exception as e:
90
+ print(f"Error opening camera {c.index}: {e}")
91
+ return selected_cap
92
+
93
+
94
+ if __name__ == "__main__":
95
+ from reachy_mini.media.camera_constants import CameraResolution
96
+
97
+ cam, _ = find_camera()
98
+ if cam is None:
99
+ exit("Camera not found")
100
+
101
+ cam.set(cv2.CAP_PROP_FRAME_WIDTH, CameraResolution.R1280x720at30fps.value[0])
102
+ cam.set(cv2.CAP_PROP_FRAME_HEIGHT, CameraResolution.R1280x720at30fps.value[1])
103
+
104
+ while True:
105
+ ret, frame = cam.read()
106
+ if not ret:
107
+ print("Failed to grab frame")
108
+ break
109
+ cv2.imshow("Camera Feed", frame)
110
+ if cv2.waitKey(1) & 0xFF == ord("q"):
111
+ break
@@ -0,0 +1,281 @@
1
+ """Media Manager.
2
+
3
+ Provides camera and audio access based on the selected backedn
4
+ """
5
+
6
+ import logging
7
+ from enum import Enum
8
+ from typing import Optional
9
+
10
+ import numpy as np
11
+ import numpy.typing as npt
12
+
13
+ from reachy_mini.media.audio_base import AudioBase
14
+ from reachy_mini.media.camera_base import CameraBase
15
+
16
+ # actual backends are dynamically imported
17
+
18
+
19
+ class MediaBackend(Enum):
20
+ """Media backends."""
21
+
22
+ NO_MEDIA = "no_media"
23
+ DEFAULT = "default"
24
+ DEFAULT_NO_VIDEO = "default_no_video"
25
+ GSTREAMER = "gstreamer"
26
+ GSTREAMER_NO_VIDEO = "gstreamer_no_video"
27
+ WEBRTC = "webrtc"
28
+
29
+
30
+ class MediaManager:
31
+ """Abstract class for opening and managing audio devices."""
32
+
33
+ def __init__(
34
+ self,
35
+ backend: MediaBackend = MediaBackend.DEFAULT,
36
+ log_level: str = "INFO",
37
+ use_sim: bool = False,
38
+ signalling_host: str = "localhost",
39
+ ) -> None:
40
+ """Initialize the audio device."""
41
+ self.logger = logging.getLogger(__name__)
42
+ self.logger.setLevel(log_level)
43
+ self.backend = backend
44
+ self.camera: Optional[CameraBase] = None
45
+ self.audio: Optional[AudioBase] = None
46
+
47
+ match backend:
48
+ case MediaBackend.NO_MEDIA:
49
+ self.logger.info("No media backend selected.")
50
+ case MediaBackend.DEFAULT:
51
+ self.logger.info("Using default media backend (OpenCV + SoundDevice).")
52
+ self._init_camera(use_sim, log_level)
53
+ self._init_audio(log_level)
54
+ case MediaBackend.DEFAULT_NO_VIDEO:
55
+ self.logger.info("Using default media backend (SoundDevice only).")
56
+ self._init_audio(log_level)
57
+ case MediaBackend.GSTREAMER:
58
+ self.logger.info("Using GStreamer media backend.")
59
+ self._init_camera(use_sim, log_level)
60
+ self._init_audio(log_level)
61
+ case MediaBackend.GSTREAMER_NO_VIDEO:
62
+ self.logger.info("Using GStreamer audio backend.")
63
+ self._init_audio(log_level)
64
+ case MediaBackend.WEBRTC:
65
+ self.logger.info("Using WebRTC GStreamer backend.")
66
+ self._init_webrtc(log_level, signalling_host, 8443)
67
+ # self._init_audio(log_level)
68
+ case _:
69
+ raise NotImplementedError(f"Media backend {backend} not implemented.")
70
+
71
+ def close(self) -> None:
72
+ """Close the media manager and release resources."""
73
+ if self.camera is not None:
74
+ self.camera.close()
75
+ if self.audio is not None:
76
+ self.audio.stop_recording()
77
+ self.audio.stop_playing()
78
+
79
+ def __del__(self) -> None:
80
+ """Destructor to ensure resources are released."""
81
+ self.close()
82
+
83
+ def _init_camera(
84
+ self,
85
+ use_sim: bool,
86
+ log_level: str,
87
+ ) -> None:
88
+ """Initialize the camera."""
89
+ self.logger.debug("Initializing camera...")
90
+ if self.backend == MediaBackend.DEFAULT:
91
+ self.logger.info("Using OpenCV camera backend.")
92
+ from reachy_mini.media.camera_opencv import OpenCVCamera
93
+
94
+ self.camera = OpenCVCamera(log_level=log_level)
95
+ if use_sim:
96
+ self.camera.open(udp_camera="udp://@127.0.0.1:5005")
97
+ else:
98
+ self.camera.open()
99
+ elif self.backend == MediaBackend.GSTREAMER:
100
+ self.logger.info("Using GStreamer camera backend.")
101
+ from reachy_mini.media.camera_gstreamer import GStreamerCamera
102
+
103
+ self.camera = GStreamerCamera(log_level=log_level)
104
+ self.camera.open()
105
+ # Todo: use simulation with gstreamer?
106
+
107
+ else:
108
+ raise NotImplementedError(f"Camera backend {self.backend} not implemented.")
109
+
110
+ def get_frame(self) -> Optional[npt.NDArray[np.uint8]]:
111
+ """Get a frame from the camera.
112
+
113
+ Returns:
114
+ Optional[npt.NDArray[np.uint8]]: The captured BGR frame, or None if the camera is not available.
115
+
116
+ """
117
+ if self.camera is None:
118
+ self.logger.warning("Camera is not initialized.")
119
+ return None
120
+ return self.camera.read()
121
+
122
+ def _init_audio(self, log_level: str) -> None:
123
+ """Initialize the audio system."""
124
+ self.logger.debug("Initializing audio...")
125
+ if (
126
+ self.backend == MediaBackend.DEFAULT
127
+ or self.backend == MediaBackend.DEFAULT_NO_VIDEO
128
+ ):
129
+ self.logger.info("Using SoundDevice audio backend.")
130
+ from reachy_mini.media.audio_sounddevice import SoundDeviceAudio
131
+
132
+ self.audio = SoundDeviceAudio(log_level=log_level)
133
+ elif (
134
+ self.backend == MediaBackend.GSTREAMER
135
+ or self.backend == MediaBackend.GSTREAMER_NO_VIDEO
136
+ ):
137
+ self.logger.info("Using GStreamer audio backend.")
138
+ from reachy_mini.media.audio_gstreamer import GStreamerAudio
139
+
140
+ self.audio = GStreamerAudio(log_level=log_level)
141
+ else:
142
+ raise NotImplementedError(f"Audio backend {self.backend} not implemented.")
143
+
144
+ def _init_webrtc(
145
+ self, log_level: str, signalling_host: str, signalling_port: int
146
+ ) -> None:
147
+ """Initialize the WebRTC system (not implemented yet)."""
148
+ from gst_signalling.utils import find_producer_peer_id_by_name
149
+
150
+ from reachy_mini.media.webrtc_client_gstreamer import GstWebRTCClient
151
+
152
+ peer_id = find_producer_peer_id_by_name(
153
+ signalling_host, signalling_port, "reachymini"
154
+ )
155
+
156
+ webrtc_media: GstWebRTCClient = GstWebRTCClient(
157
+ log_level=log_level,
158
+ peer_id=peer_id,
159
+ signaling_host=signalling_host,
160
+ signaling_port=signalling_port,
161
+ )
162
+
163
+ self.camera = webrtc_media
164
+ self.audio = webrtc_media # GstWebRTCClient handles both audio and video
165
+ self.camera.open()
166
+
167
+ def play_sound(self, sound_file: str) -> None:
168
+ """Play a sound file.
169
+
170
+ Args:
171
+ sound_file (str): Path to the sound file to play.
172
+
173
+ """
174
+ if self.audio is None:
175
+ self.logger.warning("Audio system is not initialized.")
176
+ return
177
+ self.audio.play_sound(sound_file)
178
+
179
+ def start_recording(self) -> None:
180
+ """Start recording audio."""
181
+ if self.audio is None:
182
+ self.logger.warning("Audio system is not initialized.")
183
+ return
184
+ self.audio.start_recording()
185
+
186
+ def get_audio_sample(self) -> Optional[bytes | npt.NDArray[np.float32]]:
187
+ """Get an audio sample from the audio device.
188
+
189
+ Returns:
190
+ Optional[np.ndarray]: The recorded audio sample, or None if no data is available.
191
+
192
+ """
193
+ if self.audio is None:
194
+ self.logger.warning("Audio system is not initialized.")
195
+ return None
196
+ return self.audio.get_audio_sample()
197
+
198
+ def get_input_audio_samplerate(self) -> int:
199
+ """Get the input samplerate of the audio device."""
200
+ if self.audio is None:
201
+ self.logger.warning("Audio system is not initialized.")
202
+ return -1
203
+ return self.audio.get_input_audio_samplerate()
204
+
205
+ def get_output_audio_samplerate(self) -> int:
206
+ """Get the output samplerate of the audio device."""
207
+ if self.audio is None:
208
+ self.logger.warning("Audio system is not initialized.")
209
+ return -1
210
+ return self.audio.get_output_audio_samplerate()
211
+
212
+ def get_input_channels(self) -> int:
213
+ """Get the number of input channels of the audio device."""
214
+ if self.audio is None:
215
+ self.logger.warning("Audio system is not initialized.")
216
+ return -1
217
+ return self.audio.get_input_channels()
218
+
219
+ def get_output_channels(self) -> int:
220
+ """Get the number of output channels of the audio device."""
221
+ if self.audio is None:
222
+ self.logger.warning("Audio system is not initialized.")
223
+ return -1
224
+ return self.audio.get_output_channels()
225
+
226
+ def stop_recording(self) -> None:
227
+ """Stop recording audio."""
228
+ if self.audio is None:
229
+ self.logger.warning("Audio system is not initialized.")
230
+ return
231
+ self.audio.stop_recording()
232
+
233
+ def start_playing(self) -> None:
234
+ """Start playing audio."""
235
+ if self.audio is None:
236
+ self.logger.warning("Audio system is not initialized.")
237
+ return
238
+ self.audio.start_playing()
239
+
240
+ def push_audio_sample(self, data: npt.NDArray[np.float32]) -> None:
241
+ """Push audio data to the output device.
242
+
243
+ Args:
244
+ data (npt.NDArray[np.float32]): The audio data to push to the output device (mono format).
245
+
246
+ """
247
+ if self.audio is None:
248
+ self.logger.warning("Audio system is not initialized.")
249
+ return
250
+
251
+ if data.ndim > 2 or data.ndim == 0:
252
+ self.logger.warning(
253
+ f"Audio samples arrays must have at most 2 dimensions and at least 1 dimension, got {data.ndim}"
254
+ )
255
+ return
256
+
257
+ # Transpose data to match sounddevice channels last convention
258
+ if data.ndim == 2 and data.shape[1] > data.shape[0]:
259
+ data = data.T
260
+
261
+ # Fit data to match output stream channels
262
+ output_channels = self.get_output_channels()
263
+
264
+ # Mono input to multiple channels output : duplicate to fit
265
+ if data.ndim == 1 and output_channels > 1:
266
+ data = np.column_stack((data,) * output_channels)
267
+ # Lower channels input to higher channels output : reduce to mono and duplicate to fit
268
+ elif data.ndim == 2 and data.shape[1] < output_channels:
269
+ data = np.column_stack((data[:, 0],) * output_channels)
270
+ # Higher channels input to lower channels output : crop to fit
271
+ elif data.ndim == 2 and data.shape[1] > output_channels:
272
+ data = data[:, :output_channels]
273
+
274
+ self.audio.push_audio_sample(data)
275
+
276
+ def stop_playing(self) -> None:
277
+ """Stop playing audio."""
278
+ if self.audio is None:
279
+ self.logger.warning("Audio system is not initialized.")
280
+ return
281
+ self.audio.stop_playing()
@@ -0,0 +1,288 @@
1
+ """GStreamer WebRTC client implementation.
2
+
3
+ The class is a client for the webrtc server hosted on the Reachy Mini Wireless robot.
4
+ """
5
+
6
+ from threading import Thread
7
+ from typing import Optional, cast
8
+
9
+ import gi
10
+ import numpy as np
11
+ import numpy.typing as npt
12
+
13
+ from reachy_mini.media.audio_base import AudioBase
14
+ from reachy_mini.media.camera_base import CameraBase
15
+ from reachy_mini.media.camera_constants import (
16
+ CameraResolution,
17
+ CameraSpecs,
18
+ ReachyMiniWirelessCamSpecs,
19
+ )
20
+
21
+ gi.require_version("Gst", "1.0")
22
+ gi.require_version("GstApp", "1.0")
23
+ from gi.repository import GLib, Gst, GstApp # noqa: E402, F401
24
+
25
+
26
+ class GstWebRTCClient(CameraBase, AudioBase):
27
+ """GStreamer WebRTC client implementation."""
28
+
29
+ def __init__(
30
+ self,
31
+ log_level: str = "INFO",
32
+ peer_id: str = "",
33
+ signaling_host: str = "",
34
+ signaling_port: int = 8443,
35
+ ):
36
+ """Initialize the GStreamer WebRTC client."""
37
+ super().__init__(log_level=log_level)
38
+ Gst.init(None)
39
+ self._loop = GLib.MainLoop()
40
+ self._thread_bus_calls = Thread(target=lambda: self._loop.run(), daemon=True)
41
+ self._thread_bus_calls.start()
42
+
43
+ self._pipeline_record = Gst.Pipeline.new("audio_recorder")
44
+ self._bus_record = self._pipeline_record.get_bus()
45
+ self._bus_record.add_watch(
46
+ GLib.PRIORITY_DEFAULT, self._on_bus_message, self._loop
47
+ )
48
+
49
+ self._appsink_audio = Gst.ElementFactory.make("appsink")
50
+ caps = Gst.Caps.from_string(
51
+ f"audio/x-raw,rate={self.SAMPLE_RATE},channels={self.CHANNELS},format=F32LE,layout=interleaved"
52
+ )
53
+ self._appsink_audio.set_property("caps", caps)
54
+ self._appsink_audio.set_property("drop", True) # avoid overflow
55
+ self._appsink_audio.set_property("max-buffers", 500)
56
+ self._pipeline_record.add(self._appsink_audio)
57
+
58
+ self.camera_specs = cast(CameraSpecs, ReachyMiniWirelessCamSpecs)
59
+ self.set_resolution(CameraResolution.R1920x1080at30fps)
60
+
61
+ self._appsink_video = Gst.ElementFactory.make("appsink")
62
+ caps_video = Gst.Caps.from_string("video/x-raw,format=BGR")
63
+ self._appsink_video.set_property("caps", caps_video)
64
+ self._appsink_video.set_property("drop", True) # avoid overflow
65
+ self._appsink_video.set_property("max-buffers", 1) # keep last image only
66
+ self._pipeline_record.add(self._appsink_video)
67
+
68
+ webrtcsrc = self._configure_webrtcsrc(signaling_host, signaling_port, peer_id)
69
+ self._pipeline_record.add(webrtcsrc)
70
+
71
+ self._pipeline_playback = Gst.Pipeline.new("audio_player")
72
+ self._init_pipeline_playback(
73
+ self._pipeline_playback, signaling_host, signaling_port
74
+ )
75
+ self._bus_playback = self._pipeline_playback.get_bus()
76
+ self._bus_playback.add_watch(
77
+ GLib.PRIORITY_DEFAULT, self._on_bus_message, self._loop
78
+ )
79
+
80
+ def __del__(self) -> None:
81
+ """Destructor to ensure gstreamer resources are released."""
82
+ super().__del__()
83
+ self._loop.quit()
84
+ self._bus_record.remove_watch()
85
+ self._bus_playback.remove_watch()
86
+
87
+ def set_resolution(self, resolution: CameraResolution) -> None:
88
+ """Set the camera resolution."""
89
+ super().set_resolution(resolution)
90
+ self._resolution = resolution
91
+
92
+ def _configure_webrtcsrc(
93
+ self, signaling_host: str, signaling_port: int, peer_id: str
94
+ ) -> Gst.Element:
95
+ source = Gst.ElementFactory.make("webrtcsrc")
96
+ if not source:
97
+ raise RuntimeError(
98
+ "Failed to create webrtcsrc element. Is the GStreamer webrtc rust plugin installed?"
99
+ )
100
+
101
+ source.connect("pad-added", self._webrtcsrc_pad_added_cb)
102
+ signaller = source.get_property("signaller")
103
+ signaller.set_property("producer-peer-id", peer_id)
104
+ signaller.set_property("uri", f"ws://{signaling_host}:{signaling_port}")
105
+ return source
106
+
107
+ def _configure_webrtcbin(self, webrtcsrc: Gst.Element) -> None:
108
+ if isinstance(webrtcsrc, Gst.Bin):
109
+ webrtcbin_name = "webrtcbin0"
110
+ webrtcbin = webrtcsrc.get_by_name(webrtcbin_name)
111
+ assert webrtcbin is not None
112
+ # jitterbuffer has a default 200 ms buffer. Should be ok to lower this in localnetwork config
113
+ webrtcbin.set_property("latency", 100)
114
+
115
+ def _webrtcsrc_pad_added_cb(self, webrtcsrc: Gst.Element, pad: Gst.Pad) -> None:
116
+ self._configure_webrtcbin(webrtcsrc)
117
+ if pad.get_name().startswith("video"):
118
+ queue = Gst.ElementFactory.make("queue")
119
+
120
+ videoconvert = Gst.ElementFactory.make("videoconvert")
121
+ videoscale = Gst.ElementFactory.make("videoscale")
122
+ videorate = Gst.ElementFactory.make("videorate")
123
+
124
+ self._pipeline_record.add(queue)
125
+ self._pipeline_record.add(videoconvert)
126
+ self._pipeline_record.add(videoscale)
127
+ self._pipeline_record.add(videorate)
128
+ pad.link(queue.get_static_pad("sink"))
129
+
130
+ queue.link(videoconvert)
131
+ videoconvert.link(videoscale)
132
+ videoscale.link(videorate)
133
+ videorate.link(self._appsink_video)
134
+
135
+ queue.sync_state_with_parent()
136
+ videoconvert.sync_state_with_parent()
137
+ videoscale.sync_state_with_parent()
138
+ videorate.sync_state_with_parent()
139
+ self._appsink_video.sync_state_with_parent()
140
+
141
+ elif pad.get_name().startswith("audio"):
142
+ audioconvert = Gst.ElementFactory.make("audioconvert")
143
+ audioresample = Gst.ElementFactory.make("audioresample")
144
+ self._pipeline_record.add(audioconvert)
145
+ self._pipeline_record.add(audioresample)
146
+
147
+ pad.link(audioconvert.get_static_pad("sink"))
148
+ audioconvert.link(audioresample)
149
+ audioresample.link(self._appsink_audio)
150
+
151
+ self._appsink_audio.sync_state_with_parent()
152
+ audioconvert.sync_state_with_parent()
153
+ audioresample.sync_state_with_parent()
154
+
155
+ def _on_bus_message(self, bus: Gst.Bus, msg: Gst.Message, loop) -> bool: # type: ignore[no-untyped-def]
156
+ t = msg.type
157
+ if t == Gst.MessageType.EOS:
158
+ self.logger.warning("End-of-stream")
159
+ return False
160
+
161
+ elif t == Gst.MessageType.ERROR:
162
+ err, debug = msg.parse_error()
163
+ self.logger.error(f"Error: {err} {debug}")
164
+ return False
165
+
166
+ return True
167
+
168
+ def open(self) -> None:
169
+ """Open the video stream."""
170
+ self._pipeline_record.set_state(Gst.State.PLAYING)
171
+
172
+ def _get_sample(self, appsink: GstApp.AppSink) -> Optional[bytes]:
173
+ sample = appsink.try_pull_sample(20_000_000)
174
+ if sample is None:
175
+ return None
176
+ data = None
177
+ if isinstance(sample, Gst.Sample):
178
+ buf = sample.get_buffer()
179
+ if buf is None:
180
+ self.logger.warning("Buffer is None")
181
+
182
+ data = buf.extract_dup(0, buf.get_size())
183
+ return data
184
+
185
+ def get_audio_sample(self) -> Optional[npt.NDArray[np.float32]]:
186
+ """Read a sample from the audio card. Returns the sample or None if error.
187
+
188
+ Returns:
189
+ Optional[npt.NDArray[np.float32]]: The captured sample in raw format, or None if error.
190
+
191
+ """
192
+ sample = self._get_sample(self._appsink_audio)
193
+ if sample is None:
194
+ return None
195
+ return np.frombuffer(sample, dtype=np.float32).reshape(-1, 2)
196
+
197
+ def read(self) -> Optional[npt.NDArray[np.uint8]]:
198
+ """Read a frame from the camera. Returns the frame or None if error.
199
+
200
+ Returns:
201
+ Optional[npt.NDArray[np.uint8]]: The captured frame in BGR format, or None if error.
202
+
203
+ """
204
+ data = self._get_sample(self._appsink_video)
205
+ if data is None:
206
+ return None
207
+
208
+ arr = np.frombuffer(data, dtype=np.uint8).reshape(
209
+ (self.resolution[1], self.resolution[0], 3)
210
+ )
211
+ return arr
212
+
213
+ def close(self) -> None:
214
+ """Stop the pipeline."""
215
+ # self._loop.quit()
216
+ self._pipeline_record.set_state(Gst.State.NULL)
217
+
218
+ def start_recording(self) -> None:
219
+ """Open the audio card using GStreamer."""
220
+ pass # already started in open()
221
+
222
+ def stop_recording(self) -> None:
223
+ """Release the camera resource."""
224
+ pass # managed in close()
225
+
226
+ def _init_pipeline_playback(
227
+ self, pipeline: Gst.Pipeline, signaling_host: str, signaling_port: int
228
+ ) -> None:
229
+ """Initialize the audio playback pipeline."""
230
+ self._appsrc = Gst.ElementFactory.make("appsrc")
231
+ self._appsrc.set_property("format", Gst.Format.TIME)
232
+ self._appsrc.set_property("is-live", True)
233
+ caps = Gst.Caps.from_string(
234
+ f"audio/x-raw,format=F32LE,channels={self.CHANNELS},rate={self.SAMPLE_RATE},layout=interleaved"
235
+ )
236
+ self._appsrc.set_property("caps", caps)
237
+ audioconvert = Gst.ElementFactory.make("audioconvert")
238
+ audioresample = Gst.ElementFactory.make("audioresample")
239
+ opusenc = Gst.ElementFactory.make("opusenc")
240
+ queue = Gst.ElementFactory.make("queue")
241
+ rtpopuspay = Gst.ElementFactory.make("rtpopuspay")
242
+ udpsink = Gst.ElementFactory.make("udpsink")
243
+
244
+ udpsink.set_property("host", signaling_host)
245
+ udpsink.set_property("port", 5000)
246
+
247
+ pipeline.add(self._appsrc)
248
+ pipeline.add(audioconvert)
249
+ pipeline.add(audioresample)
250
+ pipeline.add(opusenc)
251
+ pipeline.add(queue)
252
+ pipeline.add(rtpopuspay)
253
+ pipeline.add(udpsink)
254
+
255
+ self._appsrc.link(audioconvert)
256
+ audioconvert.link(audioresample)
257
+ audioresample.link(opusenc)
258
+ opusenc.link(queue)
259
+ queue.link(rtpopuspay)
260
+ rtpopuspay.link(udpsink)
261
+
262
+ def start_playing(self) -> None:
263
+ """Open the audio output using GStreamer."""
264
+ self._pipeline_playback.set_state(Gst.State.PLAYING)
265
+
266
+ def stop_playing(self) -> None:
267
+ """Stop playing audio and release resources."""
268
+ self._pipeline_playback.set_state(Gst.State.NULL)
269
+
270
+ def push_audio_sample(self, data: npt.NDArray[np.float32]) -> None:
271
+ """Push audio data to the output device."""
272
+ if self._appsrc is not None:
273
+ buf = Gst.Buffer.new_wrapped(data.tobytes())
274
+ self._appsrc.push_buffer(buf)
275
+
276
+ else:
277
+ self.logger.warning(
278
+ "AppSrc is not initialized. Call start_playing() first."
279
+ )
280
+
281
+ def play_sound(self, sound_file: str) -> None:
282
+ """Play a sound file.
283
+
284
+ Args:
285
+ sound_file (str): Path to the sound file to play.
286
+
287
+ """
288
+ self.logger.warning("Audio playback not implemented in WebRTC client.")