reachy-mini 1.0.0rc1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (359) hide show
  1. reachy_mini/__init__.py +4 -0
  2. reachy_mini/apps/__init__.py +23 -0
  3. reachy_mini/apps/app.py +119 -0
  4. reachy_mini/apps/manager.py +178 -0
  5. reachy_mini/apps/sources/__init__.py +4 -0
  6. reachy_mini/apps/sources/hf_space.py +25 -0
  7. reachy_mini/apps/sources/local_common_venv.py +38 -0
  8. reachy_mini/apps/templates/README.md.j2 +1 -0
  9. reachy_mini/apps/templates/main.py.j2 +46 -0
  10. reachy_mini/apps/templates/pyproject.toml.j2 +18 -0
  11. reachy_mini/apps/utils.py +30 -0
  12. reachy_mini/assets/config/hardware_config.yaml +119 -0
  13. reachy_mini/assets/confused1.wav +0 -0
  14. reachy_mini/assets/count.wav +0 -0
  15. reachy_mini/assets/dance1.wav +0 -0
  16. reachy_mini/assets/go_sleep.wav +0 -0
  17. reachy_mini/assets/impatient1.wav +0 -0
  18. reachy_mini/assets/kinematics_data.json +253 -0
  19. reachy_mini/assets/models/fknetwork.dynamic.onnx +3 -0
  20. reachy_mini/assets/models/fknetwork.onnx +3 -0
  21. reachy_mini/assets/models/fknetwork_int8.onnx +3 -0
  22. reachy_mini/assets/models/iknetwork.onnx +3 -0
  23. reachy_mini/assets/wake_up.wav +0 -0
  24. reachy_mini/daemon/__init__.py +1 -0
  25. reachy_mini/daemon/app/__init__.py +1 -0
  26. reachy_mini/daemon/app/dashboard/apps_manager.html +202 -0
  27. reachy_mini/daemon/app/dashboard/js/3rdparty/gstwebrtc-api-2.0.0.min.js +5 -0
  28. reachy_mini/daemon/app/dashboard/js/dashboard.js +121 -0
  29. reachy_mini/daemon/app/dashboard/live_robot_state.html +242 -0
  30. reachy_mini/daemon/app/dashboard/style.css +37 -0
  31. reachy_mini/daemon/app/dependencies.py +36 -0
  32. reachy_mini/daemon/app/main.py +271 -0
  33. reachy_mini/daemon/app/models.py +146 -0
  34. reachy_mini/daemon/app/routers/apps.py +220 -0
  35. reachy_mini/daemon/app/routers/daemon.py +53 -0
  36. reachy_mini/daemon/app/routers/kinematics.py +36 -0
  37. reachy_mini/daemon/app/routers/motors.py +41 -0
  38. reachy_mini/daemon/app/routers/move.py +200 -0
  39. reachy_mini/daemon/app/routers/state.py +137 -0
  40. reachy_mini/daemon/app/templates/dashboard.html +40 -0
  41. reachy_mini/daemon/backend/__init__.py +1 -0
  42. reachy_mini/daemon/backend/abstract.py +717 -0
  43. reachy_mini/daemon/backend/mujoco/__init__.py +36 -0
  44. reachy_mini/daemon/backend/mujoco/backend.py +304 -0
  45. reachy_mini/daemon/backend/mujoco/utils.py +59 -0
  46. reachy_mini/daemon/backend/mujoco/video_udp.py +53 -0
  47. reachy_mini/daemon/backend/robot/__init__.py +8 -0
  48. reachy_mini/daemon/backend/robot/backend.py +490 -0
  49. reachy_mini/daemon/daemon.py +442 -0
  50. reachy_mini/daemon/utils.py +114 -0
  51. reachy_mini/descriptions/reachy_mini/mjcf/additional.xml +6 -0
  52. reachy_mini/descriptions/reachy_mini/mjcf/assets/5w_speaker.part +13 -0
  53. reachy_mini/descriptions/reachy_mini/mjcf/assets/5w_speaker.stl +3 -0
  54. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna.part +13 -0
  55. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna.stl +3 -0
  56. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_body_3dprint.part +13 -0
  57. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_body_3dprint.stl +3 -0
  58. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_holder_l_3dprint.part +13 -0
  59. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_holder_l_3dprint.stl +3 -0
  60. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_holder_r_3dprint.part +13 -0
  61. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_holder_r_3dprint.stl +3 -0
  62. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_interface_3dprint.part +13 -0
  63. reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_interface_3dprint.stl +3 -0
  64. reachy_mini/descriptions/reachy_mini/mjcf/assets/arducam.part +13 -0
  65. reachy_mini/descriptions/reachy_mini/mjcf/assets/arducam.stl +3 -0
  66. reachy_mini/descriptions/reachy_mini/mjcf/assets/b3b_eh.part +13 -0
  67. reachy_mini/descriptions/reachy_mini/mjcf/assets/b3b_eh.stl +3 -0
  68. reachy_mini/descriptions/reachy_mini/mjcf/assets/b3b_eh_1.part +13 -0
  69. reachy_mini/descriptions/reachy_mini/mjcf/assets/b3b_eh_1.stl +3 -0
  70. reachy_mini/descriptions/reachy_mini/mjcf/assets/bearing_85x110x13.part +13 -0
  71. reachy_mini/descriptions/reachy_mini/mjcf/assets/bearing_85x110x13.stl +3 -0
  72. reachy_mini/descriptions/reachy_mini/mjcf/assets/big_lens_d40.part +13 -0
  73. reachy_mini/descriptions/reachy_mini/mjcf/assets/big_lens_d40.stl +3 -0
  74. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_down_3dprint.part +13 -0
  75. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_down_3dprint.stl +3 -0
  76. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_foot_3dprint.part +13 -0
  77. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_foot_3dprint.stl +3 -0
  78. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_top_3dprint.part +13 -0
  79. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_top_3dprint.stl +3 -0
  80. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_turning_3dprint.part +13 -0
  81. reachy_mini/descriptions/reachy_mini/mjcf/assets/body_turning_3dprint.stl +3 -0
  82. reachy_mini/descriptions/reachy_mini/mjcf/assets/bts2_m2_6x8.part +13 -0
  83. reachy_mini/descriptions/reachy_mini/mjcf/assets/bts2_m2_6x8.stl +3 -0
  84. reachy_mini/descriptions/reachy_mini/mjcf/assets/croissant_1k.blend/croissant_1k.obj +3 -0
  85. reachy_mini/descriptions/reachy_mini/mjcf/assets/croissant_1k.blend/textures/croissant_diff_1k.png +3 -0
  86. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_b_dummy.part +13 -0
  87. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_b_dummy.stl +3 -0
  88. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_f_dummy.part +13 -0
  89. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_f_dummy.stl +3 -0
  90. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_m_dummy.part +13 -0
  91. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_m_dummy.stl +3 -0
  92. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_horn_dummy.part +13 -0
  93. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_horn_dummy.stl +3 -0
  94. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_led_cap2_dummy.part +13 -0
  95. reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_led_cap2_dummy.stl +3 -0
  96. reachy_mini/descriptions/reachy_mini/mjcf/assets/food_apple_01_1k.blend/food_apple_01_1k.obj +3 -0
  97. reachy_mini/descriptions/reachy_mini/mjcf/assets/food_apple_01_1k.blend/textures/food_apple_01_diff_1k.png +3 -0
  98. reachy_mini/descriptions/reachy_mini/mjcf/assets/glasses_dolder_3dprint.part +13 -0
  99. reachy_mini/descriptions/reachy_mini/mjcf/assets/glasses_dolder_3dprint.stl +3 -0
  100. reachy_mini/descriptions/reachy_mini/mjcf/assets/head_back_3dprint.part +13 -0
  101. reachy_mini/descriptions/reachy_mini/mjcf/assets/head_back_3dprint.stl +3 -0
  102. reachy_mini/descriptions/reachy_mini/mjcf/assets/head_front_3dprint.part +13 -0
  103. reachy_mini/descriptions/reachy_mini/mjcf/assets/head_front_3dprint.stl +3 -0
  104. reachy_mini/descriptions/reachy_mini/mjcf/assets/head_mic_3dprint.part +13 -0
  105. reachy_mini/descriptions/reachy_mini/mjcf/assets/head_mic_3dprint.stl +3 -0
  106. reachy_mini/descriptions/reachy_mini/mjcf/assets/lens_cap_d30_3dprint.part +13 -0
  107. reachy_mini/descriptions/reachy_mini/mjcf/assets/lens_cap_d30_3dprint.stl +3 -0
  108. reachy_mini/descriptions/reachy_mini/mjcf/assets/lens_cap_d40_3dprint.part +13 -0
  109. reachy_mini/descriptions/reachy_mini/mjcf/assets/lens_cap_d40_3dprint.stl +3 -0
  110. reachy_mini/descriptions/reachy_mini/mjcf/assets/m12_fisheye_lens_1_8mm.part +13 -0
  111. reachy_mini/descriptions/reachy_mini/mjcf/assets/m12_fisheye_lens_1_8mm.stl +3 -0
  112. reachy_mini/descriptions/reachy_mini/mjcf/assets/mp01062_stewart_arm_3.part +13 -0
  113. reachy_mini/descriptions/reachy_mini/mjcf/assets/mp01062_stewart_arm_3.stl +3 -0
  114. reachy_mini/descriptions/reachy_mini/mjcf/assets/neck_reference_3dprint.part +13 -0
  115. reachy_mini/descriptions/reachy_mini/mjcf/assets/neck_reference_3dprint.stl +3 -0
  116. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10.part +13 -0
  117. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10.stl +3 -0
  118. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_1.part +13 -0
  119. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_1.stl +3 -0
  120. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_2.part +13 -0
  121. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_2.stl +3 -0
  122. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_3.part +13 -0
  123. reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_3.stl +3 -0
  124. reachy_mini/descriptions/reachy_mini/mjcf/assets/pp01102_arducam_carter.part +13 -0
  125. reachy_mini/descriptions/reachy_mini/mjcf/assets/pp01102_arducam_carter.stl +3 -0
  126. reachy_mini/descriptions/reachy_mini/mjcf/assets/rubber_duck_toy_1k.blend/rubber_duck_toy_1k.obj +3 -0
  127. reachy_mini/descriptions/reachy_mini/mjcf/assets/rubber_duck_toy_1k.blend/textures/rubber_duck_toy_diff_1k.png +3 -0
  128. reachy_mini/descriptions/reachy_mini/mjcf/assets/small_lens_d30.part +13 -0
  129. reachy_mini/descriptions/reachy_mini/mjcf/assets/small_lens_d30.stl +3 -0
  130. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_ball.part +13 -0
  131. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_ball.stl +3 -0
  132. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_ball__2.part +13 -0
  133. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_ball__2.stl +3 -0
  134. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_rod.part +13 -0
  135. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_rod.stl +3 -0
  136. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_main_plate_3dprint.part +13 -0
  137. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_main_plate_3dprint.stl +3 -0
  138. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_tricap_3dprint.part +13 -0
  139. reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_tricap_3dprint.stl +3 -0
  140. reachy_mini/descriptions/reachy_mini/mjcf/assets/wooden_table_02_1k.blend/textures/wooden_table_02_diff_1k.png +3 -0
  141. reachy_mini/descriptions/reachy_mini/mjcf/assets/wooden_table_02_1k.blend/wooden_table_02_1k.obj +3 -0
  142. reachy_mini/descriptions/reachy_mini/mjcf/config.json +21 -0
  143. reachy_mini/descriptions/reachy_mini/mjcf/joints_properties.xml +29 -0
  144. reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml +613 -0
  145. reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml.bak +442 -0
  146. reachy_mini/descriptions/reachy_mini/mjcf/scene.xml +24 -0
  147. reachy_mini/descriptions/reachy_mini/mjcf/scenes/empty.xml +27 -0
  148. reachy_mini/descriptions/reachy_mini/mjcf/scenes/minimal.xml +131 -0
  149. reachy_mini/descriptions/reachy_mini/urdf/assets/5w_speaker.part +13 -0
  150. reachy_mini/descriptions/reachy_mini/urdf/assets/5w_speaker.stl +3 -0
  151. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna.part +13 -0
  152. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna.stl +3 -0
  153. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_body_3dprint.part +13 -0
  154. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_body_3dprint.stl +3 -0
  155. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_holder_l_3dprint.part +13 -0
  156. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_holder_l_3dprint.stl +3 -0
  157. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_holder_r_3dprint.part +13 -0
  158. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_holder_r_3dprint.stl +3 -0
  159. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_interface_3dprint.part +13 -0
  160. reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_interface_3dprint.stl +3 -0
  161. reachy_mini/descriptions/reachy_mini/urdf/assets/arducam.part +13 -0
  162. reachy_mini/descriptions/reachy_mini/urdf/assets/arducam.stl +3 -0
  163. reachy_mini/descriptions/reachy_mini/urdf/assets/arm.part +13 -0
  164. reachy_mini/descriptions/reachy_mini/urdf/assets/arm.stl +3 -0
  165. reachy_mini/descriptions/reachy_mini/urdf/assets/b3b_eh.part +13 -0
  166. reachy_mini/descriptions/reachy_mini/urdf/assets/b3b_eh.stl +3 -0
  167. reachy_mini/descriptions/reachy_mini/urdf/assets/b3b_eh_1.part +13 -0
  168. reachy_mini/descriptions/reachy_mini/urdf/assets/b3b_eh_1.stl +3 -0
  169. reachy_mini/descriptions/reachy_mini/urdf/assets/ball.part +13 -0
  170. reachy_mini/descriptions/reachy_mini/urdf/assets/ball.stl +3 -0
  171. reachy_mini/descriptions/reachy_mini/urdf/assets/bearing_85x110x13.part +13 -0
  172. reachy_mini/descriptions/reachy_mini/urdf/assets/bearing_85x110x13.stl +3 -0
  173. reachy_mini/descriptions/reachy_mini/urdf/assets/big_lens.part +13 -0
  174. reachy_mini/descriptions/reachy_mini/urdf/assets/big_lens.stl +3 -0
  175. reachy_mini/descriptions/reachy_mini/urdf/assets/big_lens_d40.part +13 -0
  176. reachy_mini/descriptions/reachy_mini/urdf/assets/big_lens_d40.stl +3 -0
  177. reachy_mini/descriptions/reachy_mini/urdf/assets/body_down_3dprint.part +13 -0
  178. reachy_mini/descriptions/reachy_mini/urdf/assets/body_down_3dprint.stl +3 -0
  179. reachy_mini/descriptions/reachy_mini/urdf/assets/body_foot_3dprint.part +13 -0
  180. reachy_mini/descriptions/reachy_mini/urdf/assets/body_foot_3dprint.stl +3 -0
  181. reachy_mini/descriptions/reachy_mini/urdf/assets/body_top_3dprint.part +13 -0
  182. reachy_mini/descriptions/reachy_mini/urdf/assets/body_top_3dprint.stl +3 -0
  183. reachy_mini/descriptions/reachy_mini/urdf/assets/body_turning_3dprint.part +13 -0
  184. reachy_mini/descriptions/reachy_mini/urdf/assets/body_turning_3dprint.stl +3 -0
  185. reachy_mini/descriptions/reachy_mini/urdf/assets/bottom_body.part +13 -0
  186. reachy_mini/descriptions/reachy_mini/urdf/assets/bottom_body.stl +3 -0
  187. reachy_mini/descriptions/reachy_mini/urdf/assets/bts2_m2_6x8.part +13 -0
  188. reachy_mini/descriptions/reachy_mini/urdf/assets/bts2_m2_6x8.stl +3 -0
  189. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_b_dummy.part +13 -0
  190. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_b_dummy.stl +3 -0
  191. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_f_dummy.part +13 -0
  192. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_f_dummy.stl +3 -0
  193. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_m_dummy.part +13 -0
  194. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_m_dummy.stl +3 -0
  195. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_horn_dummy.part +13 -0
  196. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_horn_dummy.stl +3 -0
  197. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_led_cap2_dummy.part +13 -0
  198. reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_led_cap2_dummy.stl +3 -0
  199. reachy_mini/descriptions/reachy_mini/urdf/assets/drive_palonier__configuration_default.part +14 -0
  200. reachy_mini/descriptions/reachy_mini/urdf/assets/drive_palonier__configuration_default.stl +3 -0
  201. reachy_mini/descriptions/reachy_mini/urdf/assets/drive_palonier__configuration_simple_axe.part +14 -0
  202. reachy_mini/descriptions/reachy_mini/urdf/assets/drive_palonier__configuration_simple_axe.stl +3 -0
  203. reachy_mini/descriptions/reachy_mini/urdf/assets/eye_support.part +13 -0
  204. reachy_mini/descriptions/reachy_mini/urdf/assets/eye_support.stl +3 -0
  205. reachy_mini/descriptions/reachy_mini/urdf/assets/foot.part +13 -0
  206. reachy_mini/descriptions/reachy_mini/urdf/assets/foot.stl +3 -0
  207. reachy_mini/descriptions/reachy_mini/urdf/assets/glasses_dolder_3dprint.part +13 -0
  208. reachy_mini/descriptions/reachy_mini/urdf/assets/glasses_dolder_3dprint.stl +3 -0
  209. reachy_mini/descriptions/reachy_mini/urdf/assets/head_back_3dprint.part +13 -0
  210. reachy_mini/descriptions/reachy_mini/urdf/assets/head_back_3dprint.stl +3 -0
  211. reachy_mini/descriptions/reachy_mini/urdf/assets/head_front_3dprint.part +13 -0
  212. reachy_mini/descriptions/reachy_mini/urdf/assets/head_front_3dprint.stl +3 -0
  213. reachy_mini/descriptions/reachy_mini/urdf/assets/head_head_back.part +13 -0
  214. reachy_mini/descriptions/reachy_mini/urdf/assets/head_head_back.stl +3 -0
  215. reachy_mini/descriptions/reachy_mini/urdf/assets/head_interface.part +13 -0
  216. reachy_mini/descriptions/reachy_mini/urdf/assets/head_interface.stl +3 -0
  217. reachy_mini/descriptions/reachy_mini/urdf/assets/head_mic_3dprint.part +13 -0
  218. reachy_mini/descriptions/reachy_mini/urdf/assets/head_mic_3dprint.stl +3 -0
  219. reachy_mini/descriptions/reachy_mini/urdf/assets/head_shell_front.part +13 -0
  220. reachy_mini/descriptions/reachy_mini/urdf/assets/head_shell_front.stl +3 -0
  221. reachy_mini/descriptions/reachy_mini/urdf/assets/lens_cap_d30_3dprint.part +13 -0
  222. reachy_mini/descriptions/reachy_mini/urdf/assets/lens_cap_d30_3dprint.stl +3 -0
  223. reachy_mini/descriptions/reachy_mini/urdf/assets/lens_cap_d40_3dprint.part +13 -0
  224. reachy_mini/descriptions/reachy_mini/urdf/assets/lens_cap_d40_3dprint.stl +3 -0
  225. reachy_mini/descriptions/reachy_mini/urdf/assets/m12_fisheye_lens_1_8mm.part +13 -0
  226. reachy_mini/descriptions/reachy_mini/urdf/assets/m12_fisheye_lens_1_8mm.stl +3 -0
  227. reachy_mini/descriptions/reachy_mini/urdf/assets/m12_lens.part +13 -0
  228. reachy_mini/descriptions/reachy_mini/urdf/assets/m12_lens.stl +3 -0
  229. reachy_mini/descriptions/reachy_mini/urdf/assets/main_plate.part +13 -0
  230. reachy_mini/descriptions/reachy_mini/urdf/assets/main_plate.stl +3 -0
  231. reachy_mini/descriptions/reachy_mini/urdf/assets/mid_plate.part +13 -0
  232. reachy_mini/descriptions/reachy_mini/urdf/assets/mid_plate.stl +3 -0
  233. reachy_mini/descriptions/reachy_mini/urdf/assets/mp01062_stewart_arm_3.part +13 -0
  234. reachy_mini/descriptions/reachy_mini/urdf/assets/mp01062_stewart_arm_3.stl +3 -0
  235. reachy_mini/descriptions/reachy_mini/urdf/assets/neck_reference_3dprint.part +13 -0
  236. reachy_mini/descriptions/reachy_mini/urdf/assets/neck_reference_3dprint.stl +3 -0
  237. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10.part +13 -0
  238. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10.stl +3 -0
  239. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_1.part +13 -0
  240. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_1.stl +3 -0
  241. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_2.part +13 -0
  242. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_2.stl +3 -0
  243. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_3.part +13 -0
  244. reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_3.stl +3 -0
  245. reachy_mini/descriptions/reachy_mini/urdf/assets/plateform.part +13 -0
  246. reachy_mini/descriptions/reachy_mini/urdf/assets/plateform.stl +3 -0
  247. reachy_mini/descriptions/reachy_mini/urdf/assets/pp00xxx_stewart_rod.part +13 -0
  248. reachy_mini/descriptions/reachy_mini/urdf/assets/pp00xxx_stewart_rod.stl +3 -0
  249. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01062_stewart_arm.part +13 -0
  250. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01062_stewart_arm.stl +3 -0
  251. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01063_stewart_plateform.part +13 -0
  252. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01063_stewart_plateform.stl +3 -0
  253. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01064_stewart_main_plate.part +13 -0
  254. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01064_stewart_main_plate.stl +3 -0
  255. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01065_stewart_side_plate.part +13 -0
  256. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01065_stewart_side_plate.stl +3 -0
  257. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01066_stewart_mid_plate.part +13 -0
  258. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01066_stewart_mid_plate.stl +3 -0
  259. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01067_bottom_body.part +13 -0
  260. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01067_bottom_body.stl +3 -0
  261. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01068_top_body.part +13 -0
  262. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01068_top_body.stl +3 -0
  263. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01069_head_shell_front.part +13 -0
  264. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01069_head_shell_front.stl +3 -0
  265. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01070_head_head_back.part +13 -0
  266. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01070_head_head_back.stl +3 -0
  267. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01071_turning_bowl.part +13 -0
  268. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01071_turning_bowl.stl +3 -0
  269. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01072_turning_end.part +13 -0
  270. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01072_turning_end.stl +3 -0
  271. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01078_glasses.part +13 -0
  272. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01078_glasses.stl +3 -0
  273. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01079_back_big_eye.part +13 -0
  274. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01079_back_big_eye.stl +3 -0
  275. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01080_back_small_eye.part +13 -0
  276. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01080_back_small_eye.stl +3 -0
  277. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01102_arducam_carter.part +13 -0
  278. reachy_mini/descriptions/reachy_mini/urdf/assets/pp01102_arducam_carter.stl +3 -0
  279. reachy_mini/descriptions/reachy_mini/urdf/assets/rod.part +13 -0
  280. reachy_mini/descriptions/reachy_mini/urdf/assets/rod.stl +3 -0
  281. reachy_mini/descriptions/reachy_mini/urdf/assets/shape.part +13 -0
  282. reachy_mini/descriptions/reachy_mini/urdf/assets/shape.stl +3 -0
  283. reachy_mini/descriptions/reachy_mini/urdf/assets/side_plate.part +13 -0
  284. reachy_mini/descriptions/reachy_mini/urdf/assets/side_plate.stl +3 -0
  285. reachy_mini/descriptions/reachy_mini/urdf/assets/small_lens.part +13 -0
  286. reachy_mini/descriptions/reachy_mini/urdf/assets/small_lens.stl +3 -0
  287. reachy_mini/descriptions/reachy_mini/urdf/assets/small_lens_d30.part +13 -0
  288. reachy_mini/descriptions/reachy_mini/urdf/assets/small_lens_d30.stl +3 -0
  289. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_ball.part +13 -0
  290. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_ball.stl +3 -0
  291. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_ball__2.part +13 -0
  292. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_ball__2.stl +3 -0
  293. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_rod.part +13 -0
  294. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_rod.stl +3 -0
  295. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_main_plate_3dprint.part +13 -0
  296. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_main_plate_3dprint.stl +3 -0
  297. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_tricap_3dprint.part +13 -0
  298. reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_tricap_3dprint.stl +3 -0
  299. reachy_mini/descriptions/reachy_mini/urdf/assets/test_antenna.part +13 -0
  300. reachy_mini/descriptions/reachy_mini/urdf/assets/test_antenna.stl +3 -0
  301. reachy_mini/descriptions/reachy_mini/urdf/assets/test_antenna_body.part +13 -0
  302. reachy_mini/descriptions/reachy_mini/urdf/assets/test_antenna_body.stl +3 -0
  303. reachy_mini/descriptions/reachy_mini/urdf/assets/top_body.part +13 -0
  304. reachy_mini/descriptions/reachy_mini/urdf/assets/top_body.stl +3 -0
  305. reachy_mini/descriptions/reachy_mini/urdf/assets/turning_bowl.part +13 -0
  306. reachy_mini/descriptions/reachy_mini/urdf/assets/turning_bowl.stl +3 -0
  307. reachy_mini/descriptions/reachy_mini/urdf/assets/uc_a37_rev_a_step.part +13 -0
  308. reachy_mini/descriptions/reachy_mini/urdf/assets/uc_a37_rev_a_step.stl +3 -0
  309. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0122topcabinetcase_95__configuration_default.part +14 -0
  310. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0122topcabinetcase_95__configuration_default.stl +3 -0
  311. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0122topcabinetcase_95__configuration_simple_axe.part +14 -0
  312. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0122topcabinetcase_95__configuration_simple_axe.stl +3 -0
  313. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0123middlecase_56__configuration_default.part +14 -0
  314. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0123middlecase_56__configuration_default.stl +3 -0
  315. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0123middlecase_56__configuration_simple_axe.part +14 -0
  316. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0123middlecase_56__configuration_simple_axe.stl +3 -0
  317. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0124bottomcase_45__configuration_default.part +14 -0
  318. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0124bottomcase_45__configuration_default.stl +3 -0
  319. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0124bottomcase_45__configuration_simple_axe.part +14 -0
  320. reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0124bottomcase_45__configuration_simple_axe.stl +3 -0
  321. reachy_mini/descriptions/reachy_mini/urdf/config.json +18 -0
  322. reachy_mini/descriptions/reachy_mini/urdf/robot.urdf +3282 -0
  323. reachy_mini/descriptions/reachy_mini/urdf/robot.urdf.bak +3282 -0
  324. reachy_mini/descriptions/reachy_mini/urdf/robot_no_collision.urdf +2316 -0
  325. reachy_mini/io/__init__.py +1 -0
  326. reachy_mini/io/abstract.py +70 -0
  327. reachy_mini/io/protocol.py +44 -0
  328. reachy_mini/io/zenoh_client.py +258 -0
  329. reachy_mini/io/zenoh_server.py +183 -0
  330. reachy_mini/kinematics/__init__.py +68 -0
  331. reachy_mini/kinematics/analytical_kinematics.py +102 -0
  332. reachy_mini/kinematics/nn_kinematics.py +100 -0
  333. reachy_mini/kinematics/placo_kinematics.py +662 -0
  334. reachy_mini/media/__init__.py +1 -0
  335. reachy_mini/media/audio_base.py +75 -0
  336. reachy_mini/media/audio_gstreamer.py +194 -0
  337. reachy_mini/media/audio_sounddevice.py +207 -0
  338. reachy_mini/media/audio_utils.py +27 -0
  339. reachy_mini/media/camera_base.py +58 -0
  340. reachy_mini/media/camera_constants.py +13 -0
  341. reachy_mini/media/camera_gstreamer.py +144 -0
  342. reachy_mini/media/camera_opencv.py +61 -0
  343. reachy_mini/media/camera_utils.py +60 -0
  344. reachy_mini/media/media_manager.py +186 -0
  345. reachy_mini/motion/__init__.py +4 -0
  346. reachy_mini/motion/goto.py +71 -0
  347. reachy_mini/motion/move.py +36 -0
  348. reachy_mini/motion/recorded_move.py +132 -0
  349. reachy_mini/reachy_mini.py +705 -0
  350. reachy_mini/utils/__init__.py +46 -0
  351. reachy_mini/utils/constants.py +9 -0
  352. reachy_mini/utils/interpolation.py +227 -0
  353. reachy_mini/utils/parse_urdf_for_kinematics.py +85 -0
  354. reachy_mini-1.0.0rc1.dist-info/METADATA +261 -0
  355. reachy_mini-1.0.0rc1.dist-info/RECORD +359 -0
  356. reachy_mini-1.0.0rc1.dist-info/WHEEL +5 -0
  357. reachy_mini-1.0.0rc1.dist-info/entry_points.txt +3 -0
  358. reachy_mini-1.0.0rc1.dist-info/licenses/LICENSE +201 -0
  359. reachy_mini-1.0.0rc1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,146 @@
1
+ """Common pydantic models definitions."""
2
+
3
+ from datetime import datetime
4
+
5
+ import numpy as np
6
+ from numpy.typing import NDArray
7
+ from pydantic import BaseModel
8
+ from scipy.spatial.transform import Rotation as R
9
+
10
+ from reachy_mini.daemon.backend.abstract import MotorControlMode
11
+
12
+
13
+ class Matrix4x4Pose(BaseModel):
14
+ """Represent a 3D pose by its 4x4 transformation matrix (translation is expressed in meters)."""
15
+
16
+ m: tuple[
17
+ float,
18
+ float,
19
+ float,
20
+ float,
21
+ float,
22
+ float,
23
+ float,
24
+ float,
25
+ float,
26
+ float,
27
+ float,
28
+ float,
29
+ float,
30
+ float,
31
+ float,
32
+ float,
33
+ ]
34
+
35
+ @classmethod
36
+ def from_pose_array(cls, arr: NDArray[np.float64]) -> "Matrix4x4Pose":
37
+ """Create a Matrix4x4 pose representation from a 4x4 pose array."""
38
+ assert arr.shape == (4, 4), "Array must be of shape (4, 4)"
39
+ m: tuple[
40
+ float,
41
+ float,
42
+ float,
43
+ float,
44
+ float,
45
+ float,
46
+ float,
47
+ float,
48
+ float,
49
+ float,
50
+ float,
51
+ float,
52
+ float,
53
+ float,
54
+ float,
55
+ float,
56
+ ] = tuple(arr.flatten().tolist()) # type: ignore [assignment]
57
+ return cls(m=m)
58
+
59
+ def to_pose_array(self) -> NDArray[np.float64]:
60
+ """Convert the Matrix4x4Pose to a 4x4 numpy array."""
61
+ return np.array(self.m).reshape((4, 4))
62
+
63
+
64
+ class XYZRPYPose(BaseModel):
65
+ """Represent a 3D pose using position (x, y, z) in meters and orientation (roll, pitch, yaw) angles in radians."""
66
+
67
+ x: float = 0.0
68
+ y: float = 0.0
69
+ z: float = 0.0
70
+ roll: float = 0.0
71
+ pitch: float = 0.0
72
+ yaw: float = 0.0
73
+
74
+ @classmethod
75
+ def from_pose_array(cls, arr: NDArray[np.float64]) -> "XYZRPYPose":
76
+ """Create an XYZRPYPose representation from a 4x4 pose array."""
77
+ assert arr.shape == (4, 4), "Array must be of shape (4, 4)"
78
+
79
+ x, y, z = arr[0, 3], arr[1, 3], arr[2, 3]
80
+ roll, pitch, yaw = R.from_matrix(arr[:3, :3]).as_euler("xyz")
81
+
82
+ return cls(
83
+ x=x,
84
+ y=y,
85
+ z=z,
86
+ roll=roll,
87
+ pitch=pitch,
88
+ yaw=yaw,
89
+ )
90
+
91
+ def to_pose_array(self) -> NDArray[np.float64]:
92
+ """Convert the XYZRPYPose to a 4x4 numpy array."""
93
+ rotation = R.from_euler("xyz", [self.roll, self.pitch, self.yaw])
94
+ pose_matrix = np.eye(4)
95
+ pose_matrix[:3, 3] = [self.x, self.y, self.z]
96
+ pose_matrix[:3, :3] = rotation.as_matrix()
97
+ return pose_matrix
98
+
99
+
100
+ AnyPose = XYZRPYPose | Matrix4x4Pose
101
+
102
+
103
+ def as_any_pose(pose: NDArray[np.float64], use_matrix: bool) -> AnyPose:
104
+ """Convert a numpy array to an AnyPose representation."""
105
+ return (
106
+ Matrix4x4Pose.from_pose_array(pose)
107
+ if use_matrix
108
+ else XYZRPYPose.from_pose_array(pose)
109
+ )
110
+
111
+
112
+ class FullBodyTarget(BaseModel):
113
+ """Represent the full body including the head pose and the joints for antennas."""
114
+
115
+ target_head_pose: AnyPose | None = None
116
+ target_antennas: tuple[float, float] | None = None
117
+ timestamp: datetime | None = None
118
+
119
+ model_config = {
120
+ "json_schema_extra": {
121
+ "examples": [
122
+ {
123
+ "target_head_pose": {
124
+ "x": 0.0,
125
+ "y": 0.0,
126
+ "z": 0.0,
127
+ "roll": 0.0,
128
+ "pitch": 0.0,
129
+ "yaw": 0.0,
130
+ },
131
+ "target_antennas": [0.0, 0.0],
132
+ }
133
+ ]
134
+ }
135
+ }
136
+
137
+
138
+ class FullState(BaseModel):
139
+ """Represent the full state of the robot including all joint positions and poses."""
140
+
141
+ control_mode: MotorControlMode | None = None
142
+ head_pose: AnyPose | None = None
143
+ head_joints: list[float] | None = None
144
+ body_yaw: float | None = None
145
+ antennas_position: list[float] | None = None
146
+ timestamp: datetime | None = None
@@ -0,0 +1,220 @@
1
+ """Apps router for apps management."""
2
+
3
+ import asyncio
4
+ import logging
5
+ import uuid
6
+ from dataclasses import dataclass
7
+ from typing import Any, Awaitable, Callable
8
+
9
+ from fastapi import (
10
+ APIRouter,
11
+ BackgroundTasks,
12
+ Depends,
13
+ HTTPException,
14
+ WebSocket,
15
+ WebSocketDisconnect,
16
+ )
17
+ from pydantic import BaseModel
18
+
19
+ from reachy_mini.apps import AppInfo, SourceKind
20
+ from reachy_mini.apps.manager import AppManager, AppStatus
21
+ from reachy_mini.daemon.app.dependencies import get_app_manager
22
+
23
+ router = APIRouter(prefix="/apps")
24
+
25
+
26
+ class JobStatus(BaseModel):
27
+ """Pydantic model for install job status."""
28
+
29
+ command: str
30
+ status: str
31
+ logs: list[str]
32
+
33
+
34
+ @dataclass
35
+ class JobHandler:
36
+ """Handler for background jobs."""
37
+
38
+ status: JobStatus
39
+ new_log_evt: dict[str, asyncio.Event]
40
+
41
+
42
+ jobs: dict[str, JobHandler] = {}
43
+
44
+
45
+ @router.get("/list-available/{source_kind}")
46
+ async def list_available_apps(
47
+ source_kind: SourceKind,
48
+ app_manager: "AppManager" = Depends(get_app_manager),
49
+ ) -> list[AppInfo]:
50
+ """List available apps (including not installed)."""
51
+ return await app_manager.list_available_apps(source_kind)
52
+
53
+
54
+ @router.get("/list-available")
55
+ async def list_all_available_apps(
56
+ app_manager: "AppManager" = Depends(get_app_manager),
57
+ ) -> list[AppInfo]:
58
+ """List all available apps (including not installed)."""
59
+ return await app_manager.list_all_available_apps()
60
+
61
+
62
+ @router.post("/install")
63
+ async def install_app(
64
+ app_info: AppInfo,
65
+ background_tasks: BackgroundTasks,
66
+ app_manager: "AppManager" = Depends(get_app_manager),
67
+ ) -> dict[str, str]:
68
+ """Install a new app by its info (background, returns job_id)."""
69
+ job_id = start_bg_job(
70
+ "install", background_tasks, app_manager.install_new_app, app_info
71
+ )
72
+ return {"job_id": job_id}
73
+
74
+
75
+ @router.post("/remove/{app_name}")
76
+ async def remove_app(
77
+ app_name: str,
78
+ background_tasks: BackgroundTasks,
79
+ app_manager: "AppManager" = Depends(get_app_manager),
80
+ ) -> dict[str, str]:
81
+ """Remove an installed app by its name (background, returns job_id)."""
82
+ job_id = start_bg_job("remove", background_tasks, app_manager.remove_app, app_name)
83
+ return {"job_id": job_id}
84
+
85
+
86
+ @router.get("/job-status/{job_id}")
87
+ async def job_status(job_id: str) -> JobStatus:
88
+ """Get status/logs for a job."""
89
+ job = jobs.get(job_id)
90
+ if not job:
91
+ raise HTTPException(status_code=404, detail="Job not found")
92
+ return job.status
93
+
94
+
95
+ # WebSocket route for live job status/logs
96
+ @router.websocket("/ws/apps-manager/{job_id}")
97
+ async def ws_apps_manager(websocket: WebSocket, job_id: str) -> None:
98
+ """WebSocket route to stream live job status/logs for a job, sending updates as soon as new logs are available."""
99
+ await websocket.accept()
100
+ last_log_len = 0
101
+
102
+ job = jobs.get(job_id)
103
+ if not job:
104
+ await websocket.send_json({"error": "Job not found"})
105
+ await websocket.close()
106
+ return
107
+
108
+ assert job is not None # for mypy
109
+
110
+ ws_uuid = str(uuid.uuid4())
111
+
112
+ try:
113
+ job.new_log_evt[ws_uuid] = asyncio.Event()
114
+ while True:
115
+ await job.new_log_evt[ws_uuid].wait()
116
+ job.new_log_evt[ws_uuid].clear()
117
+ new_logs = job.status.logs[last_log_len:]
118
+ last_log_len = len(job.status.logs)
119
+ await websocket.send_json(
120
+ {
121
+ "command": job.status.command,
122
+ "status": job.status.model_dump_json(),
123
+ "logs": new_logs,
124
+ }
125
+ )
126
+ if job.status.status.startswith("done") or job.status.status.startswith(
127
+ "error"
128
+ ):
129
+ await websocket.close()
130
+ break
131
+ except WebSocketDisconnect:
132
+ pass
133
+
134
+ finally:
135
+ if ws_uuid in job.new_log_evt:
136
+ del job.new_log_evt[ws_uuid]
137
+
138
+
139
+ @router.post("/start-app/{app_name}")
140
+ async def start_app(
141
+ app_name: str,
142
+ app_manager: "AppManager" = Depends(get_app_manager),
143
+ ) -> AppStatus:
144
+ """Start an app by its name."""
145
+ try:
146
+ return await app_manager.start_app(app_name)
147
+ except RuntimeError as e:
148
+ raise HTTPException(status_code=400, detail=str(e))
149
+
150
+
151
+ @router.post("/restart-current-app")
152
+ async def restart_app(
153
+ app_manager: "AppManager" = Depends(get_app_manager),
154
+ ) -> AppStatus:
155
+ """Restart the currently running app."""
156
+ try:
157
+ return await app_manager.restart_current_app()
158
+ except RuntimeError as e:
159
+ raise HTTPException(status_code=400, detail=str(e))
160
+
161
+
162
+ @router.post("/stop-current-app")
163
+ async def stop_app(
164
+ app_manager: "AppManager" = Depends(get_app_manager),
165
+ ) -> None:
166
+ """Stop the currently running app."""
167
+ try:
168
+ return await app_manager.stop_current_app()
169
+ except RuntimeError as e:
170
+ raise HTTPException(status_code=400, detail=str(e))
171
+
172
+
173
+ @router.get("/current-app-status")
174
+ async def current_app_status(
175
+ app_manager: "AppManager" = Depends(get_app_manager),
176
+ ) -> AppStatus | None:
177
+ """Get the status of the currently running app, if any."""
178
+ return await app_manager.current_app_status()
179
+
180
+
181
+ def start_bg_job(
182
+ command: str,
183
+ background_tasks: BackgroundTasks,
184
+ coro_func: Callable[..., Awaitable[None]],
185
+ *args: Any,
186
+ ) -> str:
187
+ """Start a background job, with a custom logger and return its job_id."""
188
+ job_id = str(uuid.uuid4())
189
+ jobs[job_id] = JobHandler(
190
+ status=JobStatus(
191
+ command=command,
192
+ status="pending",
193
+ logs=[],
194
+ ),
195
+ new_log_evt={},
196
+ )
197
+
198
+ async def run_command() -> None:
199
+ jobs[job_id].status.status = "running"
200
+
201
+ class JobLogger(logging.Handler):
202
+ def emit(self, record: logging.LogRecord) -> None:
203
+ jobs[job_id].status.logs.append(self.format(record))
204
+ for ws in jobs[job_id].new_log_evt.values():
205
+ ws.set()
206
+
207
+ logger = logging.getLogger(f"logs_job_{job_id}")
208
+ logger.setLevel(logging.INFO)
209
+ logger.handlers.clear()
210
+ logger.addHandler(JobLogger())
211
+ try:
212
+ await coro_func(*args, logger=logger)
213
+ jobs[job_id].status.status = "done"
214
+ logger.info(f"Job '{command}' completed successfully")
215
+ except Exception as e:
216
+ jobs[job_id].status.status = f"error: {e}"
217
+ logger.error(f"Job '{command}' failed with error: {e}")
218
+
219
+ background_tasks.add_task(run_command)
220
+ return job_id
@@ -0,0 +1,53 @@
1
+ """Daemon-related API routes."""
2
+
3
+ from fastapi import APIRouter, Depends, Request
4
+
5
+ from ...daemon import Daemon, DaemonStatus
6
+ from ..dependencies import get_daemon
7
+
8
+ router = APIRouter(
9
+ prefix="/daemon",
10
+ )
11
+
12
+
13
+ @router.post("/start")
14
+ async def start_daemon(
15
+ request: Request,
16
+ wake_up: bool,
17
+ daemon: Daemon = Depends(get_daemon),
18
+ ) -> DaemonStatus:
19
+ """Start the daemon."""
20
+ await daemon.start(
21
+ sim=request.app.state.args.sim,
22
+ scene=request.app.state.args.scene,
23
+ headless=request.app.state.args.headless,
24
+ wake_up_on_start=wake_up,
25
+ )
26
+ return daemon.status()
27
+
28
+
29
+ @router.post("/stop")
30
+ async def stop_daemon(
31
+ goto_sleep: bool, daemon: Daemon = Depends(get_daemon)
32
+ ) -> DaemonStatus:
33
+ """Stop the daemon, optionally putting the robot to sleep."""
34
+ await daemon.stop(goto_sleep_on_stop=goto_sleep)
35
+ return daemon.status()
36
+
37
+
38
+ @router.post("/restart")
39
+ async def restart_daemon(
40
+ request: Request, daemon: Daemon = Depends(get_daemon)
41
+ ) -> DaemonStatus:
42
+ """Restart the daemon."""
43
+ await daemon.restart(
44
+ sim=request.app.state.args.sim,
45
+ scene=request.app.state.args.scene,
46
+ )
47
+ return daemon.status()
48
+
49
+
50
+ @router.get("/status")
51
+ async def get_daemon_status(daemon: Daemon = Depends(get_daemon)) -> DaemonStatus:
52
+ """Get the current status of the daemon."""
53
+ return daemon.status()
@@ -0,0 +1,36 @@
1
+ """Kinematics router for handling kinematics-related requests.
2
+
3
+ This module defines the API endpoints for interacting with the kinematics
4
+ subsystem of the robot. It provides endpoints for retrieving URDF representation,
5
+ and other kinematics-related information.
6
+ """
7
+
8
+ from typing import Any
9
+
10
+ from fastapi import APIRouter, Depends
11
+
12
+ from ....daemon.backend.abstract import Backend
13
+ from ..dependencies import get_backend
14
+
15
+ router = APIRouter(
16
+ prefix="/kinematics",
17
+ )
18
+
19
+
20
+ @router.get("/info")
21
+ async def get_kinematics_info(
22
+ backend: Backend = Depends(get_backend),
23
+ ) -> dict[str, Any]:
24
+ """Get the current information of the kinematics."""
25
+ return {
26
+ "info": {
27
+ "engine": backend.kinematics_engine,
28
+ "collision check": backend.check_collision,
29
+ }
30
+ }
31
+
32
+
33
+ @router.get("/urdf")
34
+ async def get_urdf(backend: Backend = Depends(get_backend)) -> dict[str, str]:
35
+ """Get the URDF representation of the robot."""
36
+ return {"urdf": backend.get_urdf()}
@@ -0,0 +1,41 @@
1
+ """Motors router.
2
+
3
+ Provides endpoints to get and set the motor control mode.
4
+ """
5
+
6
+ from fastapi import APIRouter, Depends
7
+ from pydantic import BaseModel
8
+
9
+ from ....daemon.backend.abstract import Backend, MotorControlMode
10
+ from ..dependencies import get_backend
11
+
12
+ router = APIRouter(
13
+ prefix="/motors",
14
+ )
15
+
16
+
17
+ class MotorStatus(BaseModel):
18
+ """Represents the status of the motors.
19
+
20
+ Exposes
21
+ - mode: The current motor control mode (enabled, disabled, gravity_compensation).
22
+ """
23
+
24
+ mode: MotorControlMode
25
+
26
+
27
+ @router.get("/status")
28
+ async def get_motor_status(backend: Backend = Depends(get_backend)) -> MotorStatus:
29
+ """Get the current status of the motors."""
30
+ return MotorStatus(mode=backend.get_motor_control_mode())
31
+
32
+
33
+ @router.post("/set_mode/{mode}")
34
+ async def set_motor_mode(
35
+ mode: MotorControlMode,
36
+ backend: Backend = Depends(get_backend),
37
+ ) -> dict[str, str]:
38
+ """Set the motor control mode."""
39
+ backend.set_motor_control_mode(mode)
40
+
41
+ return {"status": f"motors changed to {mode} mode"}
@@ -0,0 +1,200 @@
1
+ """Movement-related API routes.
2
+
3
+ This exposes:
4
+ - goto
5
+ - play (wake_up, goto_sleep)
6
+ - stop running moves
7
+ - set_target and streaming set_target
8
+ """
9
+
10
+ import asyncio
11
+ import json
12
+ from enum import Enum
13
+ from typing import Any, Coroutine
14
+ from uuid import UUID, uuid4
15
+
16
+ import numpy as np
17
+ from fastapi import APIRouter, Depends, WebSocket, WebSocketDisconnect
18
+ from pydantic import BaseModel
19
+
20
+ from reachy_mini.motion.recorded_move import RecordedMoves
21
+
22
+ from ....daemon.backend.abstract import Backend
23
+ from ..dependencies import get_backend, ws_get_backend
24
+ from ..models import AnyPose, FullBodyTarget
25
+
26
+ router = APIRouter(
27
+ prefix="/move",
28
+ )
29
+
30
+
31
+ class InterpolationMode(str, Enum):
32
+ """Interpolation modes for movement."""
33
+
34
+ # TODO: This should be the same as for the backend
35
+
36
+ LINEAR = "linear"
37
+ MINJERK = "minjerk"
38
+ EASE = "ease"
39
+ CARTOON = "cartoon"
40
+
41
+
42
+ class GotoModelRequest(BaseModel):
43
+ """Request model for the goto endpoint."""
44
+
45
+ head_pose: AnyPose | None = None
46
+ antennas: tuple[float, float] | None = None
47
+ duration: float
48
+ interpolation: InterpolationMode = InterpolationMode.MINJERK
49
+
50
+ model_config = {
51
+ "json_schema_extra": {
52
+ "examples": [
53
+ {
54
+ "head_pose": {
55
+ "x": 0.0,
56
+ "y": 0.0,
57
+ "z": 0.0,
58
+ "roll": 0.0,
59
+ "pitch": 0.0,
60
+ "yaw": 0.0,
61
+ },
62
+ "antennas": [0.0, 0.0],
63
+ "duration": 2.0,
64
+ "interpolation": "minjerk",
65
+ },
66
+ {
67
+ "antennas": [0.0, 0.0],
68
+ "duration": 1.0,
69
+ "interpolation": "linear",
70
+ },
71
+ ],
72
+ }
73
+ }
74
+
75
+
76
+ class MoveUUID(BaseModel):
77
+ """Model representing a unique identifier for a move task."""
78
+
79
+ uuid: UUID
80
+
81
+
82
+ move_tasks: dict[UUID, asyncio.Task[None]] = {}
83
+
84
+
85
+ def create_move_task(coro: Coroutine[Any, Any, None]) -> MoveUUID:
86
+ """Create a new move task using async task coroutine."""
87
+ uuid = uuid4()
88
+
89
+ task = asyncio.create_task(coro)
90
+
91
+ task.add_done_callback(lambda t: move_tasks.pop(uuid, None))
92
+ move_tasks[uuid] = task
93
+
94
+ return MoveUUID(uuid=uuid)
95
+
96
+
97
+ async def stop_move_task(uuid: UUID) -> dict[str, str]:
98
+ """Stop a running move task by cancelling it."""
99
+ if uuid not in move_tasks:
100
+ raise KeyError(f"Running move with UUID {uuid} not found")
101
+
102
+ task = move_tasks.pop(uuid, None)
103
+ assert task is not None
104
+
105
+ if task:
106
+ if task.cancel():
107
+ try:
108
+ await task
109
+ except asyncio.CancelledError:
110
+ pass
111
+
112
+ return {
113
+ "message": f"Stopped move with UUID: {uuid}",
114
+ }
115
+
116
+
117
+ @router.get("/running")
118
+ async def get_running_moves() -> list[MoveUUID]:
119
+ """Get a list of currently running move tasks."""
120
+ return [MoveUUID(uuid=uuid) for uuid in move_tasks.keys()]
121
+
122
+
123
+ @router.post("/goto")
124
+ async def goto(
125
+ goto_req: GotoModelRequest, backend: Backend = Depends(get_backend)
126
+ ) -> MoveUUID:
127
+ """Request a movement to a specific target."""
128
+ return create_move_task(
129
+ backend.goto_target(
130
+ head=goto_req.head_pose.to_pose_array() if goto_req.head_pose else None,
131
+ antennas=np.array(goto_req.antennas) if goto_req.antennas else None,
132
+ duration=goto_req.duration,
133
+ )
134
+ )
135
+
136
+
137
+ @router.post("/play/wake_up")
138
+ async def play_wake_up(backend: Backend = Depends(get_backend)) -> MoveUUID:
139
+ """Request the robot to wake up."""
140
+ return create_move_task(backend.wake_up())
141
+
142
+
143
+ @router.post("/play/goto_sleep")
144
+ async def play_goto_sleep(backend: Backend = Depends(get_backend)) -> MoveUUID:
145
+ """Request the robot to go to sleep."""
146
+ return create_move_task(backend.goto_sleep())
147
+
148
+
149
+ @router.post("/play/recorded-move-dataset/{dataset_name:path}/{move_name}")
150
+ async def play_recorded_move_dataset(
151
+ dataset_name: str,
152
+ move_name: str,
153
+ backend: Backend = Depends(get_backend),
154
+ ) -> MoveUUID:
155
+ """Request the robot to play a predefined recorded move from a dataset."""
156
+ move = RecordedMoves(dataset_name).get(move_name)
157
+ return create_move_task(backend.play_move(move))
158
+
159
+
160
+ @router.post("/stop")
161
+ async def stop_move(uuid: MoveUUID) -> dict[str, str]:
162
+ """Stop a running move task."""
163
+ return await stop_move_task(uuid.uuid)
164
+
165
+
166
+ # --- FullBodyTarget streaming and single set_target ---
167
+ @router.post("/set_target")
168
+ async def set_target(
169
+ target: FullBodyTarget,
170
+ backend: Backend = Depends(get_backend),
171
+ ) -> dict[str, str]:
172
+ """POST route to set a single FullBodyTarget."""
173
+ backend.set_target(
174
+ head=target.target_head_pose.to_pose_array()
175
+ if target.target_head_pose
176
+ else None,
177
+ antennas=np.array(target.target_antennas) if target.target_antennas else None,
178
+ )
179
+ return {"status": "ok"}
180
+
181
+
182
+ @router.websocket("/ws/set_target")
183
+ async def ws_set_target(
184
+ websocket: WebSocket, backend: Backend = Depends(ws_get_backend)
185
+ ) -> None:
186
+ """WebSocket route to stream FullBodyTarget set_target calls."""
187
+ await websocket.accept()
188
+ try:
189
+ while True:
190
+ data = await websocket.receive_text()
191
+ try:
192
+ target = FullBodyTarget.model_validate_json(data)
193
+ await set_target(target, backend)
194
+
195
+ except Exception as e:
196
+ await websocket.send_text(
197
+ json.dumps({"status": "error", "detail": str(e)})
198
+ )
199
+ except WebSocketDisconnect:
200
+ pass