reachy-mini 1.0.0__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 (385) hide show
  1. reachy_mini/__init__.py +4 -0
  2. reachy_mini/apps/__init__.py +24 -0
  3. reachy_mini/apps/app.py +121 -0
  4. reachy_mini/apps/manager.py +183 -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 +44 -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 +0 -0
  20. reachy_mini/assets/models/fknetwork.onnx +0 -0
  21. reachy_mini/assets/models/fknetwork_int8.onnx +0 -0
  22. reachy_mini/assets/models/iknetwork.onnx +0 -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/bg_job_register.py +142 -0
  27. reachy_mini/daemon/app/dashboard/static/assets/KO-cartoon-static.svg +40 -0
  28. reachy_mini/daemon/app/dashboard/static/assets/awake-cartoon-static.svg +42 -0
  29. reachy_mini/daemon/app/dashboard/static/assets/awake-cartoon.svg +6 -0
  30. reachy_mini/daemon/app/dashboard/static/assets/go-to-sleep-cartoon.svg +6 -0
  31. reachy_mini/daemon/app/dashboard/static/assets/no-wifi-cartoon-static.svg +50 -0
  32. reachy_mini/daemon/app/dashboard/static/assets/no-wifi-cartoon.svg +6 -0
  33. reachy_mini/daemon/app/dashboard/static/assets/reachy-mini-awake.svg +18 -0
  34. reachy_mini/daemon/app/dashboard/static/assets/reachy-mini-connection-lost-animation.svg +6 -0
  35. reachy_mini/daemon/app/dashboard/static/assets/reachy-mini-go-to-sleep-animation.svg +6 -0
  36. reachy_mini/daemon/app/dashboard/static/assets/reachy-mini-ko-animation.svg +6 -0
  37. reachy_mini/daemon/app/dashboard/static/assets/reachy-mini-ko.svg +22 -0
  38. reachy_mini/daemon/app/dashboard/static/assets/reachy-mini-sleeping-static.svg +41 -0
  39. reachy_mini/daemon/app/dashboard/static/assets/reachy-mini-sleeping.svg +18 -0
  40. reachy_mini/daemon/app/dashboard/static/assets/reachy-mini-wake-up-animation.svg +6 -0
  41. reachy_mini/daemon/app/dashboard/static/js/3rdparty/gstwebrtc-api-2.0.0.min.js +5 -0
  42. reachy_mini/daemon/app/dashboard/static/js/apps.js +304 -0
  43. reachy_mini/daemon/app/dashboard/static/js/appstore.js +150 -0
  44. reachy_mini/daemon/app/dashboard/static/js/daemon.js +163 -0
  45. reachy_mini/daemon/app/dashboard/static/js/move_player.js +132 -0
  46. reachy_mini/daemon/app/dashboard/static/js/setup_wifi.js +94 -0
  47. reachy_mini/daemon/app/dashboard/static/js/update.js +80 -0
  48. reachy_mini/daemon/app/dashboard/static/style.css +83 -0
  49. reachy_mini/daemon/app/dashboard/templates/base.html +23 -0
  50. reachy_mini/daemon/app/dashboard/templates/index.html +17 -0
  51. reachy_mini/daemon/app/dashboard/templates/sections/apps.html +8 -0
  52. reachy_mini/daemon/app/dashboard/templates/sections/appstore.html +29 -0
  53. reachy_mini/daemon/app/dashboard/templates/sections/daemon.html +36 -0
  54. reachy_mini/daemon/app/dashboard/templates/sections/move_player.html +27 -0
  55. reachy_mini/daemon/app/dashboard/update.html +22 -0
  56. reachy_mini/daemon/app/dashboard/wifi_config.html +41 -0
  57. reachy_mini/daemon/app/dependencies.py +41 -0
  58. reachy_mini/daemon/app/main.py +262 -0
  59. reachy_mini/daemon/app/models.py +147 -0
  60. reachy_mini/daemon/app/routers/apps.py +114 -0
  61. reachy_mini/daemon/app/routers/daemon.py +80 -0
  62. reachy_mini/daemon/app/routers/kinematics.py +57 -0
  63. reachy_mini/daemon/app/routers/motors.py +41 -0
  64. reachy_mini/daemon/app/routers/move.py +257 -0
  65. reachy_mini/daemon/app/routers/state.py +146 -0
  66. reachy_mini/daemon/backend/__init__.py +1 -0
  67. reachy_mini/daemon/backend/abstract.py +750 -0
  68. reachy_mini/daemon/backend/mujoco/__init__.py +36 -0
  69. reachy_mini/daemon/backend/mujoco/backend.py +304 -0
  70. reachy_mini/daemon/backend/mujoco/utils.py +59 -0
  71. reachy_mini/daemon/backend/mujoco/video_udp.py +53 -0
  72. reachy_mini/daemon/backend/robot/__init__.py +8 -0
  73. reachy_mini/daemon/backend/robot/backend.py +535 -0
  74. reachy_mini/daemon/daemon.py +444 -0
  75. reachy_mini/daemon/utils.py +114 -0
  76. reachy_mini/descriptions/reachy_mini/mjcf/additional.xml +6 -0
  77. reachy_mini/descriptions/reachy_mini/mjcf/assets/5w_speaker.part +13 -0
  78. reachy_mini/descriptions/reachy_mini/mjcf/assets/5w_speaker.stl +0 -0
  79. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna.part +13 -0
  80. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna.stl +0 -0
  81. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_body_3dprint.part +13 -0
  82. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_body_3dprint.stl +0 -0
  83. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_holder_l_3dprint.part +13 -0
  84. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_holder_l_3dprint.stl +0 -0
  85. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_holder_r_3dprint.part +13 -0
  86. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_holder_r_3dprint.stl +0 -0
  87. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_interface_3dprint.part +13 -0
  88. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_interface_3dprint.stl +0 -0
  89. reachy_mini/descriptions/reachy_mini/mjcf/assets/arducam.part +13 -0
  90. reachy_mini/descriptions/reachy_mini/mjcf/assets/arducam.stl +0 -0
  91. reachy_mini/descriptions/reachy_mini/mjcf/assets/b3b_eh.part +13 -0
  92. reachy_mini/descriptions/reachy_mini/mjcf/assets/b3b_eh.stl +0 -0
  93. reachy_mini/descriptions/reachy_mini/mjcf/assets/b3b_eh_1.part +13 -0
  94. reachy_mini/descriptions/reachy_mini/mjcf/assets/b3b_eh_1.stl +0 -0
  95. reachy_mini/descriptions/reachy_mini/mjcf/assets/bearing_85x110x13.part +13 -0
  96. reachy_mini/descriptions/reachy_mini/mjcf/assets/bearing_85x110x13.stl +0 -0
  97. reachy_mini/descriptions/reachy_mini/mjcf/assets/big_lens_d40.part +13 -0
  98. reachy_mini/descriptions/reachy_mini/mjcf/assets/big_lens_d40.stl +0 -0
  99. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_down_3dprint.part +13 -0
  100. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_down_3dprint.stl +0 -0
  101. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_foot_3dprint.part +13 -0
  102. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_foot_3dprint.stl +0 -0
  103. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_top_3dprint.part +13 -0
  104. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_top_3dprint.stl +0 -0
  105. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_turning_3dprint.part +13 -0
  106. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_turning_3dprint.stl +0 -0
  107. reachy_mini/descriptions/reachy_mini/mjcf/assets/bts2_m2_6x8.part +13 -0
  108. reachy_mini/descriptions/reachy_mini/mjcf/assets/bts2_m2_6x8.stl +0 -0
  109. reachy_mini/descriptions/reachy_mini/mjcf/assets/croissant_1k.blend/croissant_1k.obj +5021 -0
  110. reachy_mini/descriptions/reachy_mini/mjcf/assets/croissant_1k.blend/textures/croissant_diff_1k.png +0 -0
  111. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_b_dummy.part +13 -0
  112. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_b_dummy.stl +0 -0
  113. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_f_dummy.part +13 -0
  114. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_f_dummy.stl +0 -0
  115. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_m_dummy.part +13 -0
  116. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_m_dummy.stl +0 -0
  117. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_horn_dummy.part +13 -0
  118. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_horn_dummy.stl +0 -0
  119. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_led_cap2_dummy.part +13 -0
  120. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_led_cap2_dummy.stl +0 -0
  121. reachy_mini/descriptions/reachy_mini/mjcf/assets/food_apple_01_1k.blend/food_apple_01_1k.obj +18045 -0
  122. reachy_mini/descriptions/reachy_mini/mjcf/assets/food_apple_01_1k.blend/textures/food_apple_01_diff_1k.png +0 -0
  123. reachy_mini/descriptions/reachy_mini/mjcf/assets/glasses_dolder_3dprint.part +13 -0
  124. reachy_mini/descriptions/reachy_mini/mjcf/assets/glasses_dolder_3dprint.stl +0 -0
  125. reachy_mini/descriptions/reachy_mini/mjcf/assets/head_back_3dprint.part +13 -0
  126. reachy_mini/descriptions/reachy_mini/mjcf/assets/head_back_3dprint.stl +0 -0
  127. reachy_mini/descriptions/reachy_mini/mjcf/assets/head_front_3dprint.part +13 -0
  128. reachy_mini/descriptions/reachy_mini/mjcf/assets/head_front_3dprint.stl +0 -0
  129. reachy_mini/descriptions/reachy_mini/mjcf/assets/head_mic_3dprint.part +13 -0
  130. reachy_mini/descriptions/reachy_mini/mjcf/assets/head_mic_3dprint.stl +0 -0
  131. reachy_mini/descriptions/reachy_mini/mjcf/assets/lens_cap_d30_3dprint.part +13 -0
  132. reachy_mini/descriptions/reachy_mini/mjcf/assets/lens_cap_d30_3dprint.stl +0 -0
  133. reachy_mini/descriptions/reachy_mini/mjcf/assets/lens_cap_d40_3dprint.part +13 -0
  134. reachy_mini/descriptions/reachy_mini/mjcf/assets/lens_cap_d40_3dprint.stl +0 -0
  135. reachy_mini/descriptions/reachy_mini/mjcf/assets/m12_fisheye_lens_1_8mm.part +13 -0
  136. reachy_mini/descriptions/reachy_mini/mjcf/assets/m12_fisheye_lens_1_8mm.stl +0 -0
  137. reachy_mini/descriptions/reachy_mini/mjcf/assets/mp01062_stewart_arm_3.part +13 -0
  138. reachy_mini/descriptions/reachy_mini/mjcf/assets/mp01062_stewart_arm_3.stl +0 -0
  139. reachy_mini/descriptions/reachy_mini/mjcf/assets/neck_reference_3dprint.part +13 -0
  140. reachy_mini/descriptions/reachy_mini/mjcf/assets/neck_reference_3dprint.stl +0 -0
  141. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10.part +13 -0
  142. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10.stl +0 -0
  143. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_1.part +13 -0
  144. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_1.stl +0 -0
  145. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_2.part +13 -0
  146. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_2.stl +0 -0
  147. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_3.part +13 -0
  148. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_3.stl +0 -0
  149. reachy_mini/descriptions/reachy_mini/mjcf/assets/pp01102_arducam_carter.part +13 -0
  150. reachy_mini/descriptions/reachy_mini/mjcf/assets/pp01102_arducam_carter.stl +0 -0
  151. reachy_mini/descriptions/reachy_mini/mjcf/assets/rubber_duck_toy_1k.blend/rubber_duck_toy_1k.obj +8940 -0
  152. reachy_mini/descriptions/reachy_mini/mjcf/assets/rubber_duck_toy_1k.blend/textures/rubber_duck_toy_diff_1k.png +0 -0
  153. reachy_mini/descriptions/reachy_mini/mjcf/assets/small_lens_d30.part +13 -0
  154. reachy_mini/descriptions/reachy_mini/mjcf/assets/small_lens_d30.stl +0 -0
  155. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_ball.part +13 -0
  156. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_ball.stl +0 -0
  157. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_ball__2.part +13 -0
  158. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_ball__2.stl +0 -0
  159. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_rod.part +13 -0
  160. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_rod.stl +0 -0
  161. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_main_plate_3dprint.part +13 -0
  162. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_main_plate_3dprint.stl +0 -0
  163. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_tricap_3dprint.part +13 -0
  164. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_tricap_3dprint.stl +0 -0
  165. reachy_mini/descriptions/reachy_mini/mjcf/assets/wooden_table_02_1k.blend/textures/wooden_table_02_diff_1k.png +0 -0
  166. reachy_mini/descriptions/reachy_mini/mjcf/assets/wooden_table_02_1k.blend/wooden_table_02_1k.obj +485 -0
  167. reachy_mini/descriptions/reachy_mini/mjcf/config.json +21 -0
  168. reachy_mini/descriptions/reachy_mini/mjcf/joints_properties.xml +29 -0
  169. reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml +613 -0
  170. reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml.bak +442 -0
  171. reachy_mini/descriptions/reachy_mini/mjcf/scene.xml +24 -0
  172. reachy_mini/descriptions/reachy_mini/mjcf/scenes/empty.xml +27 -0
  173. reachy_mini/descriptions/reachy_mini/mjcf/scenes/minimal.xml +131 -0
  174. reachy_mini/descriptions/reachy_mini/urdf/assets/5w_speaker.part +13 -0
  175. reachy_mini/descriptions/reachy_mini/urdf/assets/5w_speaker.stl +0 -0
  176. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna.part +13 -0
  177. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna.stl +0 -0
  178. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_body_3dprint.part +13 -0
  179. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_body_3dprint.stl +0 -0
  180. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_holder_l_3dprint.part +13 -0
  181. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_holder_l_3dprint.stl +0 -0
  182. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_holder_r_3dprint.part +13 -0
  183. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_holder_r_3dprint.stl +0 -0
  184. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_interface_3dprint.part +13 -0
  185. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_interface_3dprint.stl +0 -0
  186. reachy_mini/descriptions/reachy_mini/urdf/assets/arducam.part +13 -0
  187. reachy_mini/descriptions/reachy_mini/urdf/assets/arducam.stl +0 -0
  188. reachy_mini/descriptions/reachy_mini/urdf/assets/arm.part +13 -0
  189. reachy_mini/descriptions/reachy_mini/urdf/assets/arm.stl +0 -0
  190. reachy_mini/descriptions/reachy_mini/urdf/assets/b3b_eh.part +13 -0
  191. reachy_mini/descriptions/reachy_mini/urdf/assets/b3b_eh.stl +0 -0
  192. reachy_mini/descriptions/reachy_mini/urdf/assets/b3b_eh_1.part +13 -0
  193. reachy_mini/descriptions/reachy_mini/urdf/assets/b3b_eh_1.stl +0 -0
  194. reachy_mini/descriptions/reachy_mini/urdf/assets/ball.part +13 -0
  195. reachy_mini/descriptions/reachy_mini/urdf/assets/ball.stl +0 -0
  196. reachy_mini/descriptions/reachy_mini/urdf/assets/bearing_85x110x13.part +13 -0
  197. reachy_mini/descriptions/reachy_mini/urdf/assets/bearing_85x110x13.stl +0 -0
  198. reachy_mini/descriptions/reachy_mini/urdf/assets/big_lens.part +13 -0
  199. reachy_mini/descriptions/reachy_mini/urdf/assets/big_lens.stl +0 -0
  200. reachy_mini/descriptions/reachy_mini/urdf/assets/big_lens_d40.part +13 -0
  201. reachy_mini/descriptions/reachy_mini/urdf/assets/big_lens_d40.stl +0 -0
  202. reachy_mini/descriptions/reachy_mini/urdf/assets/body_down_3dprint.part +13 -0
  203. reachy_mini/descriptions/reachy_mini/urdf/assets/body_down_3dprint.stl +0 -0
  204. reachy_mini/descriptions/reachy_mini/urdf/assets/body_foot_3dprint.part +13 -0
  205. reachy_mini/descriptions/reachy_mini/urdf/assets/body_foot_3dprint.stl +0 -0
  206. reachy_mini/descriptions/reachy_mini/urdf/assets/body_top_3dprint.part +13 -0
  207. reachy_mini/descriptions/reachy_mini/urdf/assets/body_top_3dprint.stl +0 -0
  208. reachy_mini/descriptions/reachy_mini/urdf/assets/body_turning_3dprint.part +13 -0
  209. reachy_mini/descriptions/reachy_mini/urdf/assets/body_turning_3dprint.stl +0 -0
  210. reachy_mini/descriptions/reachy_mini/urdf/assets/bottom_body.part +13 -0
  211. reachy_mini/descriptions/reachy_mini/urdf/assets/bottom_body.stl +0 -0
  212. reachy_mini/descriptions/reachy_mini/urdf/assets/bts2_m2_6x8.part +13 -0
  213. reachy_mini/descriptions/reachy_mini/urdf/assets/bts2_m2_6x8.stl +0 -0
  214. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_b_dummy.part +13 -0
  215. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_b_dummy.stl +0 -0
  216. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_f_dummy.part +13 -0
  217. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_f_dummy.stl +0 -0
  218. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_m_dummy.part +13 -0
  219. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_m_dummy.stl +0 -0
  220. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_horn_dummy.part +13 -0
  221. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_horn_dummy.stl +0 -0
  222. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_led_cap2_dummy.part +13 -0
  223. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_led_cap2_dummy.stl +0 -0
  224. reachy_mini/descriptions/reachy_mini/urdf/assets/drive_palonier__configuration_default.part +14 -0
  225. reachy_mini/descriptions/reachy_mini/urdf/assets/drive_palonier__configuration_default.stl +0 -0
  226. reachy_mini/descriptions/reachy_mini/urdf/assets/drive_palonier__configuration_simple_axe.part +14 -0
  227. reachy_mini/descriptions/reachy_mini/urdf/assets/drive_palonier__configuration_simple_axe.stl +0 -0
  228. reachy_mini/descriptions/reachy_mini/urdf/assets/eye_support.part +13 -0
  229. reachy_mini/descriptions/reachy_mini/urdf/assets/eye_support.stl +0 -0
  230. reachy_mini/descriptions/reachy_mini/urdf/assets/foot.part +13 -0
  231. reachy_mini/descriptions/reachy_mini/urdf/assets/foot.stl +0 -0
  232. reachy_mini/descriptions/reachy_mini/urdf/assets/glasses_dolder_3dprint.part +13 -0
  233. reachy_mini/descriptions/reachy_mini/urdf/assets/glasses_dolder_3dprint.stl +0 -0
  234. reachy_mini/descriptions/reachy_mini/urdf/assets/head_back_3dprint.part +13 -0
  235. reachy_mini/descriptions/reachy_mini/urdf/assets/head_back_3dprint.stl +0 -0
  236. reachy_mini/descriptions/reachy_mini/urdf/assets/head_front_3dprint.part +13 -0
  237. reachy_mini/descriptions/reachy_mini/urdf/assets/head_front_3dprint.stl +0 -0
  238. reachy_mini/descriptions/reachy_mini/urdf/assets/head_head_back.part +13 -0
  239. reachy_mini/descriptions/reachy_mini/urdf/assets/head_head_back.stl +0 -0
  240. reachy_mini/descriptions/reachy_mini/urdf/assets/head_interface.part +13 -0
  241. reachy_mini/descriptions/reachy_mini/urdf/assets/head_interface.stl +0 -0
  242. reachy_mini/descriptions/reachy_mini/urdf/assets/head_mic_3dprint.part +13 -0
  243. reachy_mini/descriptions/reachy_mini/urdf/assets/head_mic_3dprint.stl +0 -0
  244. reachy_mini/descriptions/reachy_mini/urdf/assets/head_shell_front.part +13 -0
  245. reachy_mini/descriptions/reachy_mini/urdf/assets/head_shell_front.stl +0 -0
  246. reachy_mini/descriptions/reachy_mini/urdf/assets/lens_cap_d30_3dprint.part +13 -0
  247. reachy_mini/descriptions/reachy_mini/urdf/assets/lens_cap_d30_3dprint.stl +0 -0
  248. reachy_mini/descriptions/reachy_mini/urdf/assets/lens_cap_d40_3dprint.part +13 -0
  249. reachy_mini/descriptions/reachy_mini/urdf/assets/lens_cap_d40_3dprint.stl +0 -0
  250. reachy_mini/descriptions/reachy_mini/urdf/assets/m12_fisheye_lens_1_8mm.part +13 -0
  251. reachy_mini/descriptions/reachy_mini/urdf/assets/m12_fisheye_lens_1_8mm.stl +0 -0
  252. reachy_mini/descriptions/reachy_mini/urdf/assets/m12_lens.part +13 -0
  253. reachy_mini/descriptions/reachy_mini/urdf/assets/m12_lens.stl +0 -0
  254. reachy_mini/descriptions/reachy_mini/urdf/assets/main_plate.part +13 -0
  255. reachy_mini/descriptions/reachy_mini/urdf/assets/main_plate.stl +0 -0
  256. reachy_mini/descriptions/reachy_mini/urdf/assets/mid_plate.part +13 -0
  257. reachy_mini/descriptions/reachy_mini/urdf/assets/mid_plate.stl +0 -0
  258. reachy_mini/descriptions/reachy_mini/urdf/assets/mp01062_stewart_arm_3.part +13 -0
  259. reachy_mini/descriptions/reachy_mini/urdf/assets/mp01062_stewart_arm_3.stl +0 -0
  260. reachy_mini/descriptions/reachy_mini/urdf/assets/neck_reference_3dprint.part +13 -0
  261. reachy_mini/descriptions/reachy_mini/urdf/assets/neck_reference_3dprint.stl +0 -0
  262. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10.part +13 -0
  263. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10.stl +0 -0
  264. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_1.part +13 -0
  265. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_1.stl +0 -0
  266. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_2.part +13 -0
  267. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_2.stl +0 -0
  268. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_3.part +13 -0
  269. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_3.stl +0 -0
  270. reachy_mini/descriptions/reachy_mini/urdf/assets/plateform.part +13 -0
  271. reachy_mini/descriptions/reachy_mini/urdf/assets/plateform.stl +0 -0
  272. reachy_mini/descriptions/reachy_mini/urdf/assets/pp00xxx_stewart_rod.part +13 -0
  273. reachy_mini/descriptions/reachy_mini/urdf/assets/pp00xxx_stewart_rod.stl +0 -0
  274. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01062_stewart_arm.part +13 -0
  275. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01062_stewart_arm.stl +0 -0
  276. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01063_stewart_plateform.part +13 -0
  277. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01063_stewart_plateform.stl +0 -0
  278. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01064_stewart_main_plate.part +13 -0
  279. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01064_stewart_main_plate.stl +0 -0
  280. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01065_stewart_side_plate.part +13 -0
  281. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01065_stewart_side_plate.stl +0 -0
  282. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01066_stewart_mid_plate.part +13 -0
  283. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01066_stewart_mid_plate.stl +0 -0
  284. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01067_bottom_body.part +13 -0
  285. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01067_bottom_body.stl +0 -0
  286. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01068_top_body.part +13 -0
  287. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01068_top_body.stl +0 -0
  288. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01069_head_shell_front.part +13 -0
  289. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01069_head_shell_front.stl +0 -0
  290. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01070_head_head_back.part +13 -0
  291. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01070_head_head_back.stl +0 -0
  292. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01071_turning_bowl.part +13 -0
  293. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01071_turning_bowl.stl +0 -0
  294. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01072_turning_end.part +13 -0
  295. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01072_turning_end.stl +0 -0
  296. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01078_glasses.part +13 -0
  297. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01078_glasses.stl +0 -0
  298. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01079_back_big_eye.part +13 -0
  299. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01079_back_big_eye.stl +0 -0
  300. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01080_back_small_eye.part +13 -0
  301. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01080_back_small_eye.stl +0 -0
  302. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01102_arducam_carter.part +13 -0
  303. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01102_arducam_carter.stl +0 -0
  304. reachy_mini/descriptions/reachy_mini/urdf/assets/rod.part +13 -0
  305. reachy_mini/descriptions/reachy_mini/urdf/assets/rod.stl +0 -0
  306. reachy_mini/descriptions/reachy_mini/urdf/assets/shape.part +13 -0
  307. reachy_mini/descriptions/reachy_mini/urdf/assets/shape.stl +0 -0
  308. reachy_mini/descriptions/reachy_mini/urdf/assets/side_plate.part +13 -0
  309. reachy_mini/descriptions/reachy_mini/urdf/assets/side_plate.stl +0 -0
  310. reachy_mini/descriptions/reachy_mini/urdf/assets/small_lens.part +13 -0
  311. reachy_mini/descriptions/reachy_mini/urdf/assets/small_lens.stl +0 -0
  312. reachy_mini/descriptions/reachy_mini/urdf/assets/small_lens_d30.part +13 -0
  313. reachy_mini/descriptions/reachy_mini/urdf/assets/small_lens_d30.stl +0 -0
  314. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_ball.part +13 -0
  315. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_ball.stl +0 -0
  316. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_ball__2.part +13 -0
  317. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_ball__2.stl +0 -0
  318. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_rod.part +13 -0
  319. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_rod.stl +0 -0
  320. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_main_plate_3dprint.part +13 -0
  321. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_main_plate_3dprint.stl +0 -0
  322. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_tricap_3dprint.part +13 -0
  323. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_tricap_3dprint.stl +0 -0
  324. reachy_mini/descriptions/reachy_mini/urdf/assets/test_antenna.part +13 -0
  325. reachy_mini/descriptions/reachy_mini/urdf/assets/test_antenna.stl +0 -0
  326. reachy_mini/descriptions/reachy_mini/urdf/assets/test_antenna_body.part +13 -0
  327. reachy_mini/descriptions/reachy_mini/urdf/assets/test_antenna_body.stl +0 -0
  328. reachy_mini/descriptions/reachy_mini/urdf/assets/top_body.part +13 -0
  329. reachy_mini/descriptions/reachy_mini/urdf/assets/top_body.stl +0 -0
  330. reachy_mini/descriptions/reachy_mini/urdf/assets/turning_bowl.part +13 -0
  331. reachy_mini/descriptions/reachy_mini/urdf/assets/turning_bowl.stl +0 -0
  332. reachy_mini/descriptions/reachy_mini/urdf/assets/uc_a37_rev_a_step.part +13 -0
  333. reachy_mini/descriptions/reachy_mini/urdf/assets/uc_a37_rev_a_step.stl +0 -0
  334. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0122topcabinetcase_95__configuration_default.part +14 -0
  335. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0122topcabinetcase_95__configuration_default.stl +0 -0
  336. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0122topcabinetcase_95__configuration_simple_axe.part +14 -0
  337. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0122topcabinetcase_95__configuration_simple_axe.stl +0 -0
  338. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0123middlecase_56__configuration_default.part +14 -0
  339. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0123middlecase_56__configuration_default.stl +0 -0
  340. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0123middlecase_56__configuration_simple_axe.part +14 -0
  341. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0123middlecase_56__configuration_simple_axe.stl +0 -0
  342. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0124bottomcase_45__configuration_default.part +14 -0
  343. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0124bottomcase_45__configuration_default.stl +0 -0
  344. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0124bottomcase_45__configuration_simple_axe.part +14 -0
  345. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0124bottomcase_45__configuration_simple_axe.stl +0 -0
  346. reachy_mini/descriptions/reachy_mini/urdf/config.json +18 -0
  347. reachy_mini/descriptions/reachy_mini/urdf/robot.urdf +3281 -0
  348. reachy_mini/descriptions/reachy_mini/urdf/robot.urdf.bak +3282 -0
  349. reachy_mini/descriptions/reachy_mini/urdf/robot_no_collision.urdf +2316 -0
  350. reachy_mini/io/__init__.py +1 -0
  351. reachy_mini/io/abstract.py +70 -0
  352. reachy_mini/io/protocol.py +44 -0
  353. reachy_mini/io/zenoh_client.py +258 -0
  354. reachy_mini/io/zenoh_server.py +183 -0
  355. reachy_mini/kinematics/__init__.py +68 -0
  356. reachy_mini/kinematics/analytical_kinematics.py +102 -0
  357. reachy_mini/kinematics/nn_kinematics.py +100 -0
  358. reachy_mini/kinematics/placo_kinematics.py +666 -0
  359. reachy_mini/media/__init__.py +1 -0
  360. reachy_mini/media/audio_base.py +163 -0
  361. reachy_mini/media/audio_gstreamer.py +195 -0
  362. reachy_mini/media/audio_sounddevice.py +226 -0
  363. reachy_mini/media/audio_utils.py +27 -0
  364. reachy_mini/media/camera_base.py +63 -0
  365. reachy_mini/media/camera_constants.py +13 -0
  366. reachy_mini/media/camera_gstreamer.py +162 -0
  367. reachy_mini/media/camera_opencv.py +61 -0
  368. reachy_mini/media/camera_utils.py +60 -0
  369. reachy_mini/media/media_manager.py +194 -0
  370. reachy_mini/motion/__init__.py +4 -0
  371. reachy_mini/motion/goto.py +71 -0
  372. reachy_mini/motion/move.py +36 -0
  373. reachy_mini/motion/recorded_move.py +132 -0
  374. reachy_mini/reachy_mini.py +705 -0
  375. reachy_mini/utils/__init__.py +46 -0
  376. reachy_mini/utils/constants.py +9 -0
  377. reachy_mini/utils/interpolation.py +227 -0
  378. reachy_mini/utils/parse_urdf_for_kinematics.py +110 -0
  379. reachy_mini/utils/rerun.py +546 -0
  380. reachy_mini-1.0.0.dist-info/METADATA +286 -0
  381. reachy_mini-1.0.0.dist-info/RECORD +385 -0
  382. reachy_mini-1.0.0.dist-info/WHEEL +5 -0
  383. reachy_mini-1.0.0.dist-info/entry_points.txt +3 -0
  384. reachy_mini-1.0.0.dist-info/licenses/LICENSE +201 -0
  385. reachy_mini-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,705 @@
1
+ """Reachy Mini class for controlling a simulated or real Reachy Mini robot.
2
+
3
+ This class provides methods to control the head and antennas of the Reachy Mini robot,
4
+ set their target positions, and perform various behaviors such as waking up and going to sleep.
5
+
6
+ It also includes methods for multimedia interactions like playing sounds and looking at specific points in the image frame or world coordinates.
7
+ """
8
+
9
+ import asyncio
10
+ import json
11
+ import logging
12
+ import time
13
+ from typing import Dict, List, Optional, Union
14
+
15
+ import cv2
16
+ import numpy as np
17
+ import numpy.typing as npt
18
+ from asgiref.sync import async_to_sync
19
+ from scipy.spatial.transform import Rotation as R
20
+
21
+ from reachy_mini.daemon.utils import daemon_check
22
+ from reachy_mini.io.protocol import GotoTaskRequest
23
+ from reachy_mini.io.zenoh_client import ZenohClient
24
+ from reachy_mini.media.media_manager import MediaBackend, MediaManager
25
+ from reachy_mini.motion.move import Move
26
+ from reachy_mini.utils.interpolation import InterpolationTechnique, minimum_jerk
27
+
28
+ # Behavior definitions
29
+ INIT_HEAD_POSE = np.eye(4)
30
+
31
+ SLEEP_HEAD_JOINT_POSITIONS = [
32
+ 0,
33
+ -0.9848156658225817,
34
+ 1.2624661884298831,
35
+ -0.24390294527381684,
36
+ 0.20555342557667577,
37
+ -1.2363885150358267,
38
+ 1.0032234352772091,
39
+ ]
40
+
41
+
42
+ SLEEP_ANTENNAS_JOINT_POSITIONS = [-3.05, 3.05]
43
+ SLEEP_HEAD_POSE = np.array(
44
+ [
45
+ [0.911, 0.004, 0.413, -0.021],
46
+ [-0.004, 1.0, -0.001, 0.001],
47
+ [-0.413, -0.001, 0.911, -0.044],
48
+ [0.0, 0.0, 0.0, 1.0],
49
+ ]
50
+ )
51
+
52
+
53
+ class ReachyMini:
54
+ """Reachy Mini class for controlling a simulated or real Reachy Mini robot.
55
+
56
+ Args:
57
+ localhost_only (bool): If True, will only connect to localhost daemons, defaults to True.
58
+ spawn_daemon (bool): If True, will spawn a daemon to control the robot, defaults to False.
59
+ use_sim (bool): If True and spawn_daemon is True, will spawn a simulated robot, defaults to True.
60
+
61
+ """
62
+
63
+ def __init__(
64
+ self,
65
+ localhost_only: bool = True,
66
+ spawn_daemon: bool = False,
67
+ use_sim: bool = False,
68
+ timeout: float = 5.0,
69
+ automatic_body_yaw: bool = False,
70
+ log_level: str = "INFO",
71
+ media_backend: str = "default",
72
+ ) -> None:
73
+ """Initialize the Reachy Mini robot.
74
+
75
+ Args:
76
+ localhost_only (bool): If True, will only connect to localhost daemons, defaults to True.
77
+ spawn_daemon (bool): If True, will spawn a daemon to control the robot, defaults to False.
78
+ use_sim (bool): If True and spawn_daemon is True, will spawn a simulated robot, defaults to True.
79
+ timeout (float): Timeout for the client connection, defaults to 5.0 seconds.
80
+ automatic_body_yaw (bool): If True, the body yaw will be used to compute the IK and FK. Default is False.
81
+ log_level (str): Logging level, defaults to "INFO".
82
+ media_backend (str): Media backend to use, either "default" (OpenCV) or "gstreamer", defaults to "default".
83
+
84
+ It will try to connect to the daemon, and if it fails, it will raise an exception.
85
+
86
+ """
87
+ self.logger = logging.getLogger(__name__)
88
+ self.logger.setLevel(log_level)
89
+ daemon_check(spawn_daemon, use_sim)
90
+ self.client = ZenohClient(localhost_only)
91
+ self.client.wait_for_connection(timeout=timeout)
92
+ self.set_automatic_body_yaw(automatic_body_yaw)
93
+ self._last_head_pose: Optional[npt.NDArray[np.float64]] = None
94
+ self.is_recording = False
95
+
96
+ self.K = np.array(
97
+ [[550.3564, 0.0, 638.0112], [0.0, 549.1653, 364.589], [0.0, 0.0, 1.0]]
98
+ )
99
+ self.D = np.array([-0.0694, 0.1565, -0.0004, 0.0003, -0.0983])
100
+
101
+ self.T_head_cam = np.eye(4)
102
+ self.T_head_cam[:3, 3][:] = [0.0437, 0, 0.0512]
103
+ self.T_head_cam[:3, :3] = np.array(
104
+ [
105
+ [0, 0, 1],
106
+ [-1, 0, 0],
107
+ [0, -1, 0],
108
+ ]
109
+ )
110
+
111
+ mbackend = MediaBackend.DEFAULT
112
+ if media_backend.lower() == "gstreamer":
113
+ mbackend = MediaBackend.GSTREAMER
114
+ elif media_backend.lower() == "default":
115
+ mbackend = MediaBackend.DEFAULT
116
+ elif media_backend.lower() == "no_media":
117
+ mbackend = MediaBackend.NO_MEDIA
118
+ elif media_backend.lower() == "default_no_video":
119
+ mbackend = MediaBackend.DEFAULT_NO_VIDEO
120
+ else:
121
+ raise ValueError(
122
+ f"Invalid media_backend '{media_backend}'. Supported values are 'default', 'gstreamer', 'no_media', and 'default_no_video'."
123
+ )
124
+
125
+ self.media_manager = MediaManager(
126
+ use_sim=self.client.get_status()["simulation_enabled"],
127
+ backend=mbackend,
128
+ log_level=log_level,
129
+ )
130
+
131
+ def __del__(self) -> None:
132
+ """Destroy the Reachy Mini instance.
133
+
134
+ The client is disconnected explicitly to avoid a thread pending issue.
135
+
136
+ """
137
+ self.client.disconnect()
138
+
139
+ def __enter__(self) -> "ReachyMini":
140
+ """Context manager entry point for Reachy Mini."""
141
+ return self
142
+
143
+ def __exit__(self, exc_type, exc_value, traceback) -> None: # type: ignore [no-untyped-def]
144
+ """Context manager exit point for Reachy Mini."""
145
+ self.client.disconnect()
146
+
147
+ @property
148
+ def media(self) -> MediaManager:
149
+ """Expose the MediaManager instance used by ReachyMini."""
150
+ return self.media_manager
151
+
152
+ def set_target(
153
+ self,
154
+ head: Optional[npt.NDArray[np.float64]] = None, # 4x4 pose matrix
155
+ antennas: Optional[
156
+ Union[npt.NDArray[np.float64], List[float]]
157
+ ] = None, # [right_angle, left_angle] (in rads)
158
+ body_yaw: Optional[float] = None, # Body yaw angle in radians
159
+ ) -> None:
160
+ """Set the target pose of the head and/or the target position of the antennas.
161
+
162
+ Args:
163
+ head (Optional[np.ndarray]): 4x4 pose matrix representing the head pose.
164
+ antennas (Optional[Union[np.ndarray, List[float]]]): 1D array with two elements representing the angles of the antennas in radians.
165
+ body_yaw (Optional[float]): Body yaw angle in radians.
166
+
167
+ Raises:
168
+ ValueError: If neither head nor antennas are provided, or if the shape of head is not (4, 4), or if antennas is not a 1D array with two elements.
169
+
170
+ """
171
+ if head is None and antennas is None and body_yaw is None:
172
+ raise ValueError(
173
+ "At least one of head, antennas or body_yaw must be provided."
174
+ )
175
+
176
+ if head is not None and not head.shape == (4, 4):
177
+ raise ValueError(f"Head pose must be a 4x4 matrix, got shape {head.shape}.")
178
+
179
+ if antennas is not None and not len(antennas) == 2:
180
+ raise ValueError(
181
+ "Antennas must be a list or 1D np array with two elements."
182
+ )
183
+
184
+ if body_yaw is not None and not isinstance(body_yaw, (int, float)):
185
+ raise ValueError("body_yaw must be a float.")
186
+
187
+ if head is not None:
188
+ self.set_target_head_pose(head)
189
+
190
+ if antennas is not None:
191
+ self.set_target_antenna_joint_positions(list(antennas))
192
+ # self._set_joint_positions(
193
+ # antennas_joint_positions=list(antennas),
194
+ # )
195
+
196
+ if body_yaw is not None:
197
+ self.set_target_body_yaw(body_yaw)
198
+
199
+ self._last_head_pose = head
200
+
201
+ record: Dict[str, float | List[float] | List[List[float]]] = {
202
+ "time": time.time(),
203
+ "body_yaw": body_yaw if body_yaw is not None else 0.0,
204
+ }
205
+ if head is not None:
206
+ record["head"] = head.tolist()
207
+ if antennas is not None:
208
+ record["antennas"] = list(antennas)
209
+ if body_yaw is not None:
210
+ record["body_yaw"] = body_yaw
211
+ self._set_record_data(record)
212
+
213
+ def goto_target(
214
+ self,
215
+ head: Optional[npt.NDArray[np.float64]] = None, # 4x4 pose matrix
216
+ antennas: Optional[
217
+ Union[npt.NDArray[np.float64], List[float]]
218
+ ] = None, # [right_angle, left_angle] (in rads)
219
+ duration: float = 0.5, # Duration in seconds for the movement, default is 0.5 seconds.
220
+ method: InterpolationTechnique = InterpolationTechnique.MIN_JERK, # can be "linear", "minjerk", "ease" or "cartoon", default is "minjerk")
221
+ body_yaw: float | None = 0.0, # Body yaw angle in radians
222
+ ) -> None:
223
+ """Go to a target head pose and/or antennas position using task space interpolation, in "duration" seconds.
224
+
225
+ Args:
226
+ head (Optional[np.ndarray]): 4x4 pose matrix representing the target head pose.
227
+ antennas (Optional[Union[np.ndarray, List[float]]]): 1D array with two elements representing the angles of the antennas in radians.
228
+ duration (float): Duration of the movement in seconds.
229
+ method (InterpolationTechnique): Interpolation method to use ("linear", "minjerk", "ease", "cartoon"). Default is "minjerk".
230
+ body_yaw (float | None): Body yaw angle in radians. Use None to keep the current yaw.
231
+
232
+ Raises:
233
+ ValueError: If neither head nor antennas are provided, or if duration is not positive.
234
+
235
+ """
236
+ if head is None and antennas is None and body_yaw is None:
237
+ raise ValueError(
238
+ "At least one of head, antennas or body_yaw must be provided."
239
+ )
240
+
241
+ if duration <= 0.0:
242
+ raise ValueError(
243
+ "Duration must be positive and non-zero. Use set_target() for immediate position setting."
244
+ )
245
+
246
+ req = GotoTaskRequest(
247
+ head=np.array(head, dtype=np.float64).flatten().tolist()
248
+ if head is not None
249
+ else None,
250
+ antennas=np.array(antennas, dtype=np.float64).flatten().tolist()
251
+ if antennas is not None
252
+ else None,
253
+ duration=duration,
254
+ method=method,
255
+ body_yaw=body_yaw,
256
+ )
257
+
258
+ task_uid = self.client.send_task_request(req)
259
+ self.client.wait_for_task_completion(task_uid, timeout=duration + 1.0)
260
+
261
+ def wake_up(self) -> None:
262
+ """Wake up the robot - go to the initial head position and play the wake up emote and sound."""
263
+ self.goto_target(INIT_HEAD_POSE, antennas=[0.0, 0.0], duration=2)
264
+ time.sleep(0.1)
265
+
266
+ # Toudoum
267
+ self.media.play_sound("wake_up.wav")
268
+
269
+ # Roll 20° to the left
270
+ pose = INIT_HEAD_POSE.copy()
271
+ pose[:3, :3] = R.from_euler("xyz", [20, 0, 0], degrees=True).as_matrix()
272
+ self.goto_target(pose, duration=0.2)
273
+
274
+ # Go back to the initial position
275
+ self.goto_target(INIT_HEAD_POSE, duration=0.2)
276
+
277
+ def goto_sleep(self) -> None:
278
+ """Put the robot to sleep by moving the head and antennas to a predefined sleep position."""
279
+ # Check if we are too far from the initial position
280
+ # Move to the initial position if necessary
281
+ current_positions, _ = self.get_current_joint_positions()
282
+ # init_positions = self.head_kinematics.ik(INIT_HEAD_POSE)
283
+ # Todo : get init position from the daemon?
284
+ init_positions = [
285
+ 6.959852054044218e-07,
286
+ 0.5251518455536499,
287
+ -0.668710345667336,
288
+ 0.6067086443974802,
289
+ -0.606711497194891,
290
+ 0.6687148024583701,
291
+ -0.5251586523105128,
292
+ ]
293
+ dist = np.linalg.norm(np.array(current_positions) - np.array(init_positions))
294
+ if dist > 0.2:
295
+ self.goto_target(INIT_HEAD_POSE, antennas=[0.0, 0.0], duration=1)
296
+ time.sleep(0.2)
297
+
298
+ # Pfiou
299
+ self.media.play_sound("go_sleep.wav")
300
+
301
+ # # Move to the sleep position
302
+ self.goto_target(
303
+ SLEEP_HEAD_POSE, antennas=SLEEP_ANTENNAS_JOINT_POSITIONS, duration=2
304
+ )
305
+
306
+ self._last_head_pose = SLEEP_HEAD_POSE
307
+ time.sleep(2)
308
+
309
+ def look_at_image(
310
+ self, u: int, v: int, duration: float = 1.0, perform_movement: bool = True
311
+ ) -> npt.NDArray[np.float64]:
312
+ """Make the robot head look at a point defined by a pixel position (u,v).
313
+
314
+ # TODO image of reachy mini coordinate system
315
+
316
+ Args:
317
+ u (int): Horizontal coordinate in image frame.
318
+ v (int): Vertical coordinate in image frame.
319
+ duration (float): Duration of the movement in seconds. If 0, the head will snap to the position immediately.
320
+ perform_movement (bool): If True, perform the movement. If False, only calculate and return the pose.
321
+
322
+ Returns:
323
+ np.ndarray: The calculated head pose as a 4x4 matrix.
324
+
325
+ Raises:
326
+ ValueError: If duration is negative.
327
+
328
+ """
329
+ if self.media_manager.camera is None:
330
+ raise RuntimeError("Camera is not initialized.")
331
+
332
+ assert 0 < u < self.media_manager.camera.resolution[0], (
333
+ f"u must be in [0, {self.media_manager.camera.resolution[0]}], got {u}."
334
+ )
335
+ assert 0 < v < self.media_manager.camera.resolution[1], (
336
+ f"v must be in [0, {self.media_manager.camera.resolution[1]}], got {v}."
337
+ )
338
+
339
+ if duration < 0:
340
+ raise ValueError("Duration can't be negative.")
341
+
342
+ x_n, y_n = cv2.undistortPoints(np.float32([[[u, v]]]), self.K, self.D)[0, 0] # type: ignore
343
+
344
+ ray_cam = np.array([x_n, y_n, 1.0])
345
+ ray_cam /= np.linalg.norm(ray_cam)
346
+
347
+ T_world_head = self.get_current_head_pose()
348
+ T_world_cam = T_world_head @ self.T_head_cam
349
+
350
+ R_wc = T_world_cam[:3, :3]
351
+ t_wc = T_world_cam[:3, 3]
352
+
353
+ ray_world = R_wc @ ray_cam
354
+
355
+ P_world = t_wc + ray_world
356
+
357
+ return self.look_at_world(
358
+ x=P_world[0],
359
+ y=P_world[1],
360
+ z=P_world[2],
361
+ duration=duration,
362
+ perform_movement=perform_movement,
363
+ )
364
+
365
+ def look_at_world(
366
+ self,
367
+ x: float,
368
+ y: float,
369
+ z: float,
370
+ duration: float = 1.0,
371
+ perform_movement: bool = True,
372
+ ) -> npt.NDArray[np.float64]:
373
+ """Look at a specific point in 3D space in Reachy Mini's reference frame.
374
+
375
+ TODO include image of reachy mini coordinate system
376
+
377
+ Args:
378
+ x (float): X coordinate in meters.
379
+ y (float): Y coordinate in meters.
380
+ z (float): Z coordinate in meters.
381
+ duration (float): Duration of the movement in seconds. If 0, the head will snap to the position immediately.
382
+ perform_movement (bool): If True, perform the movement. If False, only calculate and return the pose.
383
+
384
+ Returns:
385
+ np.ndarray: The calculated head pose as a 4x4 matrix.
386
+
387
+ Raises:
388
+ ValueError: If duration is negative.
389
+
390
+ """
391
+ if duration < 0:
392
+ raise ValueError("Duration can't be negative.")
393
+
394
+ # Head is at the origin, so vector from head to target position is directly the target position
395
+ # TODO FIX : Actually, the head frame is not the origin frame wrt the kinematics. Close enough for now.
396
+ target_position = np.array([x, y, z])
397
+ target_vector = target_position / np.linalg.norm(
398
+ target_position
399
+ ) # normalize the vector
400
+
401
+ # head_pointing straight vector
402
+ straight_head_vector = np.array([1, 0, 0])
403
+
404
+ # Calculate the rotation needed to align the head with the target vector
405
+ v1 = straight_head_vector
406
+ v2 = target_vector
407
+ axis = np.cross(v1, v2)
408
+ axis_norm = np.linalg.norm(axis)
409
+ if axis_norm < 1e-8:
410
+ # Vectors are (almost) parallel
411
+ if np.dot(v1, v2) > 0:
412
+ rot_mat = np.eye(3)
413
+ else:
414
+ # Opposite direction: rotate 180° around any perpendicular axis
415
+ perp = np.array([0, 1, 0]) if abs(v1[0]) < 0.9 else np.array([0, 0, 1])
416
+ axis = np.cross(v1, perp)
417
+ axis /= np.linalg.norm(axis)
418
+ rot_mat = R.from_rotvec(np.pi * axis).as_matrix()
419
+ else:
420
+ axis = axis / axis_norm
421
+ angle = np.arccos(np.clip(np.dot(v1, v2), -1.0, 1.0))
422
+ rotation_vector = angle * axis
423
+ rot_mat = R.from_rotvec(rotation_vector).as_matrix()
424
+
425
+ target_head_pose = np.eye(4)
426
+ target_head_pose[:3, :3] = rot_mat
427
+
428
+ # If perform_movement is True, execute the movement
429
+ if perform_movement:
430
+ # If duration is specified, use the goto_target method to move smoothly
431
+ # Otherwise, set the position immediately
432
+ if duration > 0:
433
+ self.goto_target(target_head_pose, duration=duration)
434
+ else:
435
+ self.set_target(target_head_pose)
436
+
437
+ return target_head_pose
438
+
439
+ def _goto_joint_positions(
440
+ self,
441
+ head_joint_positions: Optional[
442
+ List[float]
443
+ ] = None, # [yaw, stewart_platform x 6] length 7
444
+ antennas_joint_positions: Optional[
445
+ List[float]
446
+ ] = None, # [right_angle, left_angle] length 2
447
+ duration: float = 0.5, # Duration in seconds for the movement
448
+ ) -> None:
449
+ """Go to a target head joint positions and/or antennas joint positions using joint space interpolation, in "duration" seconds.
450
+
451
+ [Internal] Go to a target head joint positions and/or antennas joint positions using joint space interpolation, in "duration" seconds.
452
+
453
+ Args:
454
+ head_joint_positions (Optional[List[float]]): List of head joint positions in radians (length 7).
455
+ antennas_joint_positions (Optional[List[float]]): List of antennas joint positions in radians (length 2).
456
+ duration (float): Duration of the movement in seconds. Default is 0.5 seconds.
457
+
458
+ Raises:
459
+ ValueError: If neither head_joint_positions nor antennas_joint_positions are provided, or if duration is not positive.
460
+
461
+ """
462
+ if duration <= 0.0:
463
+ raise ValueError(
464
+ "Duration must be positive and non-zero. Use set_target() for immediate position setting."
465
+ )
466
+
467
+ cur_head, cur_antennas = self.get_current_joint_positions()
468
+ current = cur_head + cur_antennas
469
+
470
+ target = []
471
+ if head_joint_positions is not None:
472
+ target.extend(head_joint_positions)
473
+ else:
474
+ target.extend(cur_head)
475
+ if antennas_joint_positions is not None:
476
+ target.extend(antennas_joint_positions)
477
+ else:
478
+ target.extend(cur_antennas)
479
+
480
+ traj = minimum_jerk(np.array(current), np.array(target), duration)
481
+
482
+ t0 = time.time()
483
+ while time.time() - t0 < duration:
484
+ t = time.time() - t0
485
+ angles = traj(t)
486
+
487
+ head_joint = angles[:7] # First 7 angles for the head
488
+ antennas_joint = angles[7:]
489
+
490
+ self._set_joint_positions(list(head_joint), list(antennas_joint))
491
+ time.sleep(0.01)
492
+
493
+ def get_current_joint_positions(self) -> tuple[list[float], list[float]]:
494
+ """Get the current joint positions of the head and antennas.
495
+
496
+ Get the current joint positions of the head and antennas (in rad)
497
+
498
+ Returns:
499
+ tuple: A tuple containing two lists:
500
+ - List of head joint positions (rad) (length 7).
501
+ - List of antennas joint positions (rad) (length 2).
502
+
503
+ """
504
+ return self.client.get_current_joints()
505
+
506
+ def get_present_antenna_joint_positions(self) -> list[float]:
507
+ """Get the present joint positions of the antennas.
508
+
509
+ Get the present joint positions of the antennas (in rad)
510
+
511
+ Returns:
512
+ list: A list of antennas joint positions (rad) (length 2).
513
+
514
+ """
515
+ return self.get_current_joint_positions()[1]
516
+
517
+ def get_current_head_pose(self) -> npt.NDArray[np.float64]:
518
+ """Get the current head pose as a 4x4 matrix.
519
+
520
+ Get the current head pose as a 4x4 matrix.
521
+
522
+ Returns:
523
+ np.ndarray: A 4x4 matrix representing the current head pose.
524
+
525
+ """
526
+ return self.client.get_current_head_pose()
527
+
528
+ def _set_joint_positions(
529
+ self,
530
+ head_joint_positions: list[float] | None = None,
531
+ antennas_joint_positions: list[float] | None = None,
532
+ ) -> None:
533
+ """Set the joint positions of the head and/or antennas.
534
+
535
+ [Internal] Set the joint positions of the head and/or antennas.
536
+
537
+ Args:
538
+ head_joint_positions (Optional[List[float]]): List of head joint positions in radians (length 7).
539
+ antennas_joint_positions (Optional[List[float]]): List of antennas joint positions in radians (length 2).
540
+ record (Optional[Dict]): If provided, the command will be logged with the given record data.
541
+
542
+ """
543
+ cmd = {}
544
+
545
+ if head_joint_positions is not None:
546
+ assert len(head_joint_positions) == 7, (
547
+ f"Head joint positions must have length 7, got {head_joint_positions}."
548
+ )
549
+ cmd["head_joint_positions"] = list(head_joint_positions)
550
+
551
+ if antennas_joint_positions is not None:
552
+ assert len(antennas_joint_positions) == 2, "Antennas must have length 2."
553
+ cmd["antennas_joint_positions"] = list(antennas_joint_positions)
554
+
555
+ if not cmd:
556
+ raise ValueError(
557
+ "At least one of head_joint_positions or antennas must be provided."
558
+ )
559
+
560
+ self.client.send_command(json.dumps(cmd))
561
+
562
+ def set_target_head_pose(self, pose: npt.NDArray[np.float64]) -> None:
563
+ """Set the head pose to a specific 4x4 matrix.
564
+
565
+ Args:
566
+ pose (np.ndarray): A 4x4 matrix representing the desired head pose.
567
+ body_yaw (float): The yaw angle of the body, used to adjust the head pose.
568
+
569
+ Raises:
570
+ ValueError: If the shape of the pose is not (4, 4).
571
+
572
+ """
573
+ cmd = {}
574
+
575
+ if pose is not None:
576
+ assert pose.shape == (4, 4), (
577
+ f"Head pose should be a 4x4 matrix, got {pose.shape}."
578
+ )
579
+ cmd["head_pose"] = pose.tolist()
580
+ else:
581
+ raise ValueError("Pose must be provided as a 4x4 matrix.")
582
+
583
+ self.client.send_command(json.dumps(cmd))
584
+
585
+ def set_target_antenna_joint_positions(self, antennas: List[float]) -> None:
586
+ """Set the target joint positions of the antennas."""
587
+ cmd = {"antennas_joint_positions": antennas}
588
+ self.client.send_command(json.dumps(cmd))
589
+
590
+ def set_target_body_yaw(self, body_yaw: float) -> None:
591
+ """Set the target body yaw.
592
+
593
+ Args:
594
+ body_yaw (float): The yaw angle of the body in radians.
595
+
596
+ """
597
+ cmd = {"body_yaw": body_yaw}
598
+ self.client.send_command(json.dumps(cmd))
599
+
600
+ def start_recording(self) -> None:
601
+ """Start recording data."""
602
+ self.client.send_command(json.dumps({"start_recording": True}))
603
+ self.is_recording = True
604
+
605
+ def stop_recording(
606
+ self,
607
+ ) -> Optional[List[Dict[str, float | List[float] | List[List[float]]]]]:
608
+ """Stop recording data and return the recorded data."""
609
+ self.client.send_command(json.dumps({"stop_recording": True}))
610
+ self.is_recording = False
611
+ if not self.client.wait_for_recorded_data(timeout=5):
612
+ raise RuntimeError("Daemon did not provide recorded data in time!")
613
+ recorded_data = self.client.get_recorded_data(wait=False)
614
+
615
+ return recorded_data
616
+
617
+ def _set_record_data(
618
+ self, record: Dict[str, float | List[float] | List[List[float]]]
619
+ ) -> None:
620
+ """Set the record data to be logged by the backend.
621
+
622
+ Args:
623
+ record (Dict): The record data to be logged.
624
+
625
+ """
626
+ if not isinstance(record, dict):
627
+ raise ValueError("Record must be a dictionary.")
628
+
629
+ # Send the record data to the backend
630
+ self.client.send_command(json.dumps({"set_target_record": record}))
631
+
632
+ def enable_motors(self) -> None:
633
+ """Enable the motors."""
634
+ self._set_torque(True)
635
+
636
+ def disable_motors(self) -> None:
637
+ """Disable the motors."""
638
+ self._set_torque(False)
639
+
640
+ def _set_torque(self, on: bool) -> None:
641
+ self.client.send_command(json.dumps({"torque": on}))
642
+
643
+ def enable_gravity_compensation(self) -> None:
644
+ """Enable gravity compensation for the head motors."""
645
+ self.client.send_command(json.dumps({"gravity_compensation": True}))
646
+
647
+ def disable_gravity_compensation(self) -> None:
648
+ """Disable gravity compensation for the head motors."""
649
+ self.client.send_command(json.dumps({"gravity_compensation": False}))
650
+
651
+ def set_automatic_body_yaw(self, body_yaw: float) -> None:
652
+ """Set the automatic body yaw.
653
+
654
+ Args:
655
+ body_yaw (float): The yaw angle of the body in radians.
656
+
657
+ """
658
+ self.client.send_command(json.dumps({"automatic_body_yaw": body_yaw}))
659
+
660
+ async def async_play_move(
661
+ self,
662
+ move: Move,
663
+ play_frequency: float = 100.0,
664
+ initial_goto_duration: float = 0.0,
665
+ ) -> None:
666
+ """Asynchronously play a Move.
667
+
668
+ Args:
669
+ move (Move): The Move object to be played.
670
+ play_frequency (float): The frequency at which to evaluate the move (in Hz).
671
+ initial_goto_duration (float): Duration for the initial goto to the starting position of the move (in seconds). If 0, no initial goto is performed.
672
+
673
+ """
674
+ if initial_goto_duration > 0.0:
675
+ start_head_pose, start_antennas_positions, start_body_yaw = move.evaluate(
676
+ 0.0
677
+ )
678
+ self.goto_target(
679
+ head=start_head_pose,
680
+ antennas=start_antennas_positions,
681
+ duration=initial_goto_duration,
682
+ body_yaw=start_body_yaw,
683
+ )
684
+
685
+ sleep_period = 1.0 / play_frequency
686
+
687
+ t0 = time.time()
688
+ while time.time() - t0 < move.duration:
689
+ t = min(time.time() - t0, move.duration - 1e-2)
690
+
691
+ head, antennas, body_yaw = move.evaluate(t)
692
+ if head is not None:
693
+ self.set_target_head_pose(head)
694
+ if body_yaw is not None:
695
+ self.set_target_body_yaw(body_yaw)
696
+ if antennas is not None:
697
+ self.set_target_antenna_joint_positions(list(antennas))
698
+
699
+ elapsed = time.time() - t0 - t
700
+ if elapsed < sleep_period:
701
+ await asyncio.sleep(sleep_period - elapsed)
702
+ else:
703
+ await asyncio.sleep(0.001)
704
+
705
+ play_move = async_to_sync(async_play_move)