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.
- reachy_mini/__init__.py +4 -0
- reachy_mini/apps/__init__.py +24 -0
- reachy_mini/apps/app.py +121 -0
- reachy_mini/apps/manager.py +183 -0
- reachy_mini/apps/sources/__init__.py +4 -0
- reachy_mini/apps/sources/hf_space.py +25 -0
- reachy_mini/apps/sources/local_common_venv.py +44 -0
- reachy_mini/apps/templates/README.md.j2 +1 -0
- reachy_mini/apps/templates/main.py.j2 +46 -0
- reachy_mini/apps/templates/pyproject.toml.j2 +18 -0
- reachy_mini/apps/utils.py +30 -0
- reachy_mini/assets/config/hardware_config.yaml +119 -0
- reachy_mini/assets/confused1.wav +0 -0
- reachy_mini/assets/count.wav +0 -0
- reachy_mini/assets/dance1.wav +0 -0
- reachy_mini/assets/go_sleep.wav +0 -0
- reachy_mini/assets/impatient1.wav +0 -0
- reachy_mini/assets/kinematics_data.json +253 -0
- reachy_mini/assets/models/fknetwork.dynamic.onnx +0 -0
- reachy_mini/assets/models/fknetwork.onnx +0 -0
- reachy_mini/assets/models/fknetwork_int8.onnx +0 -0
- reachy_mini/assets/models/iknetwork.onnx +0 -0
- reachy_mini/assets/wake_up.wav +0 -0
- reachy_mini/daemon/__init__.py +1 -0
- reachy_mini/daemon/app/__init__.py +1 -0
- reachy_mini/daemon/app/bg_job_register.py +142 -0
- reachy_mini/daemon/app/dashboard/static/assets/KO-cartoon-static.svg +40 -0
- reachy_mini/daemon/app/dashboard/static/assets/awake-cartoon-static.svg +42 -0
- reachy_mini/daemon/app/dashboard/static/assets/awake-cartoon.svg +6 -0
- reachy_mini/daemon/app/dashboard/static/assets/go-to-sleep-cartoon.svg +6 -0
- reachy_mini/daemon/app/dashboard/static/assets/no-wifi-cartoon-static.svg +50 -0
- reachy_mini/daemon/app/dashboard/static/assets/no-wifi-cartoon.svg +6 -0
- reachy_mini/daemon/app/dashboard/static/assets/reachy-mini-awake.svg +18 -0
- reachy_mini/daemon/app/dashboard/static/assets/reachy-mini-connection-lost-animation.svg +6 -0
- reachy_mini/daemon/app/dashboard/static/assets/reachy-mini-go-to-sleep-animation.svg +6 -0
- reachy_mini/daemon/app/dashboard/static/assets/reachy-mini-ko-animation.svg +6 -0
- reachy_mini/daemon/app/dashboard/static/assets/reachy-mini-ko.svg +22 -0
- reachy_mini/daemon/app/dashboard/static/assets/reachy-mini-sleeping-static.svg +41 -0
- reachy_mini/daemon/app/dashboard/static/assets/reachy-mini-sleeping.svg +18 -0
- reachy_mini/daemon/app/dashboard/static/assets/reachy-mini-wake-up-animation.svg +6 -0
- reachy_mini/daemon/app/dashboard/static/js/3rdparty/gstwebrtc-api-2.0.0.min.js +5 -0
- reachy_mini/daemon/app/dashboard/static/js/apps.js +304 -0
- reachy_mini/daemon/app/dashboard/static/js/appstore.js +150 -0
- reachy_mini/daemon/app/dashboard/static/js/daemon.js +163 -0
- reachy_mini/daemon/app/dashboard/static/js/move_player.js +132 -0
- reachy_mini/daemon/app/dashboard/static/js/setup_wifi.js +94 -0
- reachy_mini/daemon/app/dashboard/static/js/update.js +80 -0
- reachy_mini/daemon/app/dashboard/static/style.css +83 -0
- reachy_mini/daemon/app/dashboard/templates/base.html +23 -0
- reachy_mini/daemon/app/dashboard/templates/index.html +17 -0
- reachy_mini/daemon/app/dashboard/templates/sections/apps.html +8 -0
- reachy_mini/daemon/app/dashboard/templates/sections/appstore.html +29 -0
- reachy_mini/daemon/app/dashboard/templates/sections/daemon.html +36 -0
- reachy_mini/daemon/app/dashboard/templates/sections/move_player.html +27 -0
- reachy_mini/daemon/app/dashboard/update.html +22 -0
- reachy_mini/daemon/app/dashboard/wifi_config.html +41 -0
- reachy_mini/daemon/app/dependencies.py +41 -0
- reachy_mini/daemon/app/main.py +262 -0
- reachy_mini/daemon/app/models.py +147 -0
- reachy_mini/daemon/app/routers/apps.py +114 -0
- reachy_mini/daemon/app/routers/daemon.py +80 -0
- reachy_mini/daemon/app/routers/kinematics.py +57 -0
- reachy_mini/daemon/app/routers/motors.py +41 -0
- reachy_mini/daemon/app/routers/move.py +257 -0
- reachy_mini/daemon/app/routers/state.py +146 -0
- reachy_mini/daemon/backend/__init__.py +1 -0
- reachy_mini/daemon/backend/abstract.py +750 -0
- reachy_mini/daemon/backend/mujoco/__init__.py +36 -0
- reachy_mini/daemon/backend/mujoco/backend.py +304 -0
- reachy_mini/daemon/backend/mujoco/utils.py +59 -0
- reachy_mini/daemon/backend/mujoco/video_udp.py +53 -0
- reachy_mini/daemon/backend/robot/__init__.py +8 -0
- reachy_mini/daemon/backend/robot/backend.py +535 -0
- reachy_mini/daemon/daemon.py +444 -0
- reachy_mini/daemon/utils.py +114 -0
- reachy_mini/descriptions/reachy_mini/mjcf/additional.xml +6 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/5w_speaker.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/5w_speaker.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_body_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_body_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_holder_l_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_holder_l_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_holder_r_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_holder_r_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_interface_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/antenna_interface_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/arducam.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/arducam.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/b3b_eh.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/b3b_eh.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/b3b_eh_1.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/b3b_eh_1.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/bearing_85x110x13.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/bearing_85x110x13.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/big_lens_d40.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/big_lens_d40.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/body_down_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/body_down_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/body_foot_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/body_foot_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/body_top_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/body_top_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/body_turning_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/body_turning_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/bts2_m2_6x8.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/bts2_m2_6x8.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/croissant_1k.blend/croissant_1k.obj +5021 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/croissant_1k.blend/textures/croissant_diff_1k.png +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_b_dummy.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_b_dummy.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_f_dummy.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_f_dummy.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_m_dummy.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_case_m_dummy.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_horn_dummy.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_horn_dummy.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_led_cap2_dummy.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/dc15_a01_led_cap2_dummy.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/food_apple_01_1k.blend/food_apple_01_1k.obj +18045 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/food_apple_01_1k.blend/textures/food_apple_01_diff_1k.png +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/glasses_dolder_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/glasses_dolder_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/head_back_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/head_back_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/head_front_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/head_front_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/head_mic_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/head_mic_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/lens_cap_d30_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/lens_cap_d30_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/lens_cap_d40_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/lens_cap_d40_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/m12_fisheye_lens_1_8mm.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/m12_fisheye_lens_1_8mm.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/mp01062_stewart_arm_3.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/mp01062_stewart_arm_3.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/neck_reference_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/neck_reference_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_1.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_1.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_2.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_2.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_3.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/phs_1_7x20_5_dc10_3.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/pp01102_arducam_carter.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/pp01102_arducam_carter.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/rubber_duck_toy_1k.blend/rubber_duck_toy_1k.obj +8940 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/rubber_duck_toy_1k.blend/textures/rubber_duck_toy_diff_1k.png +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/small_lens_d30.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/small_lens_d30.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_ball.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_ball.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_ball__2.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_ball__2.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_rod.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_link_rod.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_main_plate_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_main_plate_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_tricap_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/stewart_tricap_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/wooden_table_02_1k.blend/textures/wooden_table_02_diff_1k.png +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/wooden_table_02_1k.blend/wooden_table_02_1k.obj +485 -0
- reachy_mini/descriptions/reachy_mini/mjcf/config.json +21 -0
- reachy_mini/descriptions/reachy_mini/mjcf/joints_properties.xml +29 -0
- reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml +613 -0
- reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml.bak +442 -0
- reachy_mini/descriptions/reachy_mini/mjcf/scene.xml +24 -0
- reachy_mini/descriptions/reachy_mini/mjcf/scenes/empty.xml +27 -0
- reachy_mini/descriptions/reachy_mini/mjcf/scenes/minimal.xml +131 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/5w_speaker.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/5w_speaker.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/antenna.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/antenna.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_body_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_body_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_holder_l_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_holder_l_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_holder_r_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_holder_r_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_interface_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/antenna_interface_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/arducam.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/arducam.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/arm.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/arm.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/b3b_eh.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/b3b_eh.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/b3b_eh_1.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/b3b_eh_1.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/ball.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/ball.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/bearing_85x110x13.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/bearing_85x110x13.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/big_lens.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/big_lens.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/big_lens_d40.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/big_lens_d40.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/body_down_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/body_down_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/body_foot_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/body_foot_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/body_top_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/body_top_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/body_turning_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/body_turning_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/bottom_body.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/bottom_body.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/bts2_m2_6x8.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/bts2_m2_6x8.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_b_dummy.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_b_dummy.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_f_dummy.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_f_dummy.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_m_dummy.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_case_m_dummy.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_horn_dummy.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_horn_dummy.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_led_cap2_dummy.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/dc15_a01_led_cap2_dummy.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/drive_palonier__configuration_default.part +14 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/drive_palonier__configuration_default.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/drive_palonier__configuration_simple_axe.part +14 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/drive_palonier__configuration_simple_axe.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/eye_support.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/eye_support.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/foot.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/foot.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/glasses_dolder_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/glasses_dolder_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/head_back_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/head_back_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/head_front_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/head_front_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/head_head_back.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/head_head_back.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/head_interface.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/head_interface.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/head_mic_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/head_mic_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/head_shell_front.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/head_shell_front.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/lens_cap_d30_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/lens_cap_d30_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/lens_cap_d40_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/lens_cap_d40_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/m12_fisheye_lens_1_8mm.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/m12_fisheye_lens_1_8mm.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/m12_lens.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/m12_lens.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/main_plate.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/main_plate.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/mid_plate.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/mid_plate.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/mp01062_stewart_arm_3.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/mp01062_stewart_arm_3.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/neck_reference_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/neck_reference_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_1.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_1.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_2.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_2.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_3.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/phs_1_7x20_5_dc10_3.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/plateform.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/plateform.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp00xxx_stewart_rod.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp00xxx_stewart_rod.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01062_stewart_arm.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01062_stewart_arm.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01063_stewart_plateform.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01063_stewart_plateform.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01064_stewart_main_plate.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01064_stewart_main_plate.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01065_stewart_side_plate.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01065_stewart_side_plate.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01066_stewart_mid_plate.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01066_stewart_mid_plate.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01067_bottom_body.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01067_bottom_body.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01068_top_body.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01068_top_body.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01069_head_shell_front.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01069_head_shell_front.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01070_head_head_back.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01070_head_head_back.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01071_turning_bowl.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01071_turning_bowl.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01072_turning_end.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01072_turning_end.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01078_glasses.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01078_glasses.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01079_back_big_eye.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01079_back_big_eye.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01080_back_small_eye.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01080_back_small_eye.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01102_arducam_carter.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/pp01102_arducam_carter.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/rod.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/rod.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/shape.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/shape.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/side_plate.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/side_plate.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/small_lens.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/small_lens.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/small_lens_d30.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/small_lens_d30.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_ball.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_ball.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_ball__2.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_ball__2.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_rod.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_link_rod.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_main_plate_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_main_plate_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_tricap_3dprint.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/stewart_tricap_3dprint.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/test_antenna.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/test_antenna.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/test_antenna_body.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/test_antenna_body.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/top_body.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/top_body.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/turning_bowl.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/turning_bowl.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/uc_a37_rev_a_step.part +13 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/uc_a37_rev_a_step.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0122topcabinetcase_95__configuration_default.part +14 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0122topcabinetcase_95__configuration_default.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0122topcabinetcase_95__configuration_simple_axe.part +14 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0122topcabinetcase_95__configuration_simple_axe.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0123middlecase_56__configuration_default.part +14 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0123middlecase_56__configuration_default.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0123middlecase_56__configuration_simple_axe.part +14 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0123middlecase_56__configuration_simple_axe.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0124bottomcase_45__configuration_default.part +14 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0124bottomcase_45__configuration_default.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0124bottomcase_45__configuration_simple_axe.part +14 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/wj_wk00_0124bottomcase_45__configuration_simple_axe.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/config.json +18 -0
- reachy_mini/descriptions/reachy_mini/urdf/robot.urdf +3281 -0
- reachy_mini/descriptions/reachy_mini/urdf/robot.urdf.bak +3282 -0
- reachy_mini/descriptions/reachy_mini/urdf/robot_no_collision.urdf +2316 -0
- reachy_mini/io/__init__.py +1 -0
- reachy_mini/io/abstract.py +70 -0
- reachy_mini/io/protocol.py +44 -0
- reachy_mini/io/zenoh_client.py +258 -0
- reachy_mini/io/zenoh_server.py +183 -0
- reachy_mini/kinematics/__init__.py +68 -0
- reachy_mini/kinematics/analytical_kinematics.py +102 -0
- reachy_mini/kinematics/nn_kinematics.py +100 -0
- reachy_mini/kinematics/placo_kinematics.py +666 -0
- reachy_mini/media/__init__.py +1 -0
- reachy_mini/media/audio_base.py +163 -0
- reachy_mini/media/audio_gstreamer.py +195 -0
- reachy_mini/media/audio_sounddevice.py +226 -0
- reachy_mini/media/audio_utils.py +27 -0
- reachy_mini/media/camera_base.py +63 -0
- reachy_mini/media/camera_constants.py +13 -0
- reachy_mini/media/camera_gstreamer.py +162 -0
- reachy_mini/media/camera_opencv.py +61 -0
- reachy_mini/media/camera_utils.py +60 -0
- reachy_mini/media/media_manager.py +194 -0
- reachy_mini/motion/__init__.py +4 -0
- reachy_mini/motion/goto.py +71 -0
- reachy_mini/motion/move.py +36 -0
- reachy_mini/motion/recorded_move.py +132 -0
- reachy_mini/reachy_mini.py +705 -0
- reachy_mini/utils/__init__.py +46 -0
- reachy_mini/utils/constants.py +9 -0
- reachy_mini/utils/interpolation.py +227 -0
- reachy_mini/utils/parse_urdf_for_kinematics.py +110 -0
- reachy_mini/utils/rerun.py +546 -0
- reachy_mini-1.0.0.dist-info/METADATA +286 -0
- reachy_mini-1.0.0.dist-info/RECORD +385 -0
- reachy_mini-1.0.0.dist-info/WHEEL +5 -0
- reachy_mini-1.0.0.dist-info/entry_points.txt +3 -0
- reachy_mini-1.0.0.dist-info/licenses/LICENSE +201 -0
- reachy_mini-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""IO module."""
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""Base classes for server and client implementations.
|
|
2
|
+
|
|
3
|
+
These abstract classes define the interface for server and client components
|
|
4
|
+
in the Reachy Mini project. They provide methods for starting and stopping
|
|
5
|
+
the server, handling commands, and managing client connections.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from abc import ABC, abstractmethod
|
|
9
|
+
from threading import Event
|
|
10
|
+
from uuid import UUID
|
|
11
|
+
|
|
12
|
+
from reachy_mini.io.protocol import AnyTaskRequest
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class AbstractServer(ABC):
|
|
16
|
+
"""Base class for server implementations."""
|
|
17
|
+
|
|
18
|
+
@abstractmethod
|
|
19
|
+
def start(self) -> None:
|
|
20
|
+
"""Start the server."""
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
@abstractmethod
|
|
24
|
+
def stop(self) -> None:
|
|
25
|
+
"""Stop the server."""
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
@abstractmethod
|
|
29
|
+
def command_received_event(self) -> Event:
|
|
30
|
+
"""Wait for a new command and return it."""
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class AbstractClient(ABC):
|
|
35
|
+
"""Base class for client implementations."""
|
|
36
|
+
|
|
37
|
+
@abstractmethod
|
|
38
|
+
def wait_for_connection(self) -> None:
|
|
39
|
+
"""Wait for the client to connect to the server."""
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
@abstractmethod
|
|
43
|
+
def is_connected(self) -> bool:
|
|
44
|
+
"""Check if the client is connected to the server."""
|
|
45
|
+
pass
|
|
46
|
+
|
|
47
|
+
@abstractmethod
|
|
48
|
+
def disconnect(self) -> None:
|
|
49
|
+
"""Disconnect the client from the server."""
|
|
50
|
+
pass
|
|
51
|
+
|
|
52
|
+
@abstractmethod
|
|
53
|
+
def send_command(self, command: str) -> None:
|
|
54
|
+
"""Send a command to the server."""
|
|
55
|
+
pass
|
|
56
|
+
|
|
57
|
+
@abstractmethod
|
|
58
|
+
def get_current_joints(self) -> tuple[list[float], list[float]]:
|
|
59
|
+
"""Get the current joint positions."""
|
|
60
|
+
pass
|
|
61
|
+
|
|
62
|
+
@abstractmethod
|
|
63
|
+
def send_task_request(self, task_req: AnyTaskRequest) -> UUID:
|
|
64
|
+
"""Send a task request to the server and return a unique task identifier."""
|
|
65
|
+
pass
|
|
66
|
+
|
|
67
|
+
@abstractmethod
|
|
68
|
+
def wait_for_task_completion(self, task_uid: UUID, timeout: float = 5.0) -> None:
|
|
69
|
+
"""Wait for the specified task to complete."""
|
|
70
|
+
pass
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""Protocol definitions for Reachy Mini client/server communication."""
|
|
2
|
+
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from uuid import UUID
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel
|
|
7
|
+
|
|
8
|
+
from reachy_mini.utils.interpolation import InterpolationTechnique
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class GotoTaskRequest(BaseModel):
|
|
12
|
+
"""Class to represent a goto target task."""
|
|
13
|
+
|
|
14
|
+
head: list[float] | None # 4x4 flatten pose matrix
|
|
15
|
+
antennas: list[float] | None # [right_angle, left_angle] (in rads)
|
|
16
|
+
duration: float
|
|
17
|
+
method: InterpolationTechnique
|
|
18
|
+
body_yaw: float | None
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class PlayMoveTaskRequest(BaseModel):
|
|
22
|
+
"""Class to represent a play move task."""
|
|
23
|
+
|
|
24
|
+
move_name: str
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
AnyTaskRequest = GotoTaskRequest | PlayMoveTaskRequest
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class TaskRequest(BaseModel):
|
|
31
|
+
"""Class to represent any task request."""
|
|
32
|
+
|
|
33
|
+
uuid: UUID
|
|
34
|
+
req: AnyTaskRequest
|
|
35
|
+
timestamp: datetime
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class TaskProgress(BaseModel):
|
|
39
|
+
"""Class to represent task progress."""
|
|
40
|
+
|
|
41
|
+
uuid: UUID
|
|
42
|
+
finished: bool = False
|
|
43
|
+
error: str | None = None
|
|
44
|
+
timestamp: datetime
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
"""Zenoh client for Reachy Mini.
|
|
2
|
+
|
|
3
|
+
This module implements a Zenoh client that allows communication with the Reachy Mini
|
|
4
|
+
robot. It subscribes to joint positions updates and allows sending commands to the robot.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
import threading
|
|
9
|
+
import time
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from datetime import datetime
|
|
12
|
+
from typing import Any, Dict, List, Optional
|
|
13
|
+
from uuid import UUID, uuid4
|
|
14
|
+
|
|
15
|
+
import numpy as np
|
|
16
|
+
import numpy.typing as npt
|
|
17
|
+
import zenoh
|
|
18
|
+
|
|
19
|
+
from reachy_mini.io.abstract import AbstractClient
|
|
20
|
+
from reachy_mini.io.protocol import AnyTaskRequest, TaskProgress, TaskRequest
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ZenohClient(AbstractClient):
|
|
24
|
+
"""Zenoh client for Reachy Mini."""
|
|
25
|
+
|
|
26
|
+
def __init__(self, localhost_only: bool = True):
|
|
27
|
+
"""Initialize the Zenoh client."""
|
|
28
|
+
if localhost_only:
|
|
29
|
+
c = zenoh.Config.from_json5(
|
|
30
|
+
json.dumps(
|
|
31
|
+
{
|
|
32
|
+
"connect": {
|
|
33
|
+
"endpoints": {
|
|
34
|
+
"peer": ["tcp/localhost:7447"],
|
|
35
|
+
"router": [],
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
)
|
|
41
|
+
else:
|
|
42
|
+
c = zenoh.Config()
|
|
43
|
+
|
|
44
|
+
self.joint_position_received = threading.Event()
|
|
45
|
+
self.head_pose_received = threading.Event()
|
|
46
|
+
self.status_received = threading.Event()
|
|
47
|
+
|
|
48
|
+
self.session = zenoh.open(c)
|
|
49
|
+
self.cmd_pub = self.session.declare_publisher("reachy_mini/command")
|
|
50
|
+
|
|
51
|
+
self.joint_sub = self.session.declare_subscriber(
|
|
52
|
+
"reachy_mini/joint_positions",
|
|
53
|
+
self._handle_joint_positions,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
self.pose_sub = self.session.declare_subscriber(
|
|
57
|
+
"reachy_mini/head_pose",
|
|
58
|
+
self._handle_head_pose,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
self.recording_sub = self.session.declare_subscriber(
|
|
62
|
+
"reachy_mini/recorded_data",
|
|
63
|
+
self._handle_recorded_data,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
self.status_sub = self.session.declare_subscriber(
|
|
67
|
+
"reachy_mini/daemon_status",
|
|
68
|
+
self._handle_status,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
self._last_head_joint_positions = None
|
|
72
|
+
self._last_antennas_joint_positions = None
|
|
73
|
+
self._last_head_pose: Optional[npt.NDArray[np.float64]] = None
|
|
74
|
+
self._recorded_data: Optional[
|
|
75
|
+
List[Dict[str, float | List[float] | List[List[float]]]]
|
|
76
|
+
] = None
|
|
77
|
+
self._recorded_data_ready = threading.Event()
|
|
78
|
+
self._is_alive = False
|
|
79
|
+
self._last_status: Dict[str, Any] = {} # contains a DaemonStatus
|
|
80
|
+
|
|
81
|
+
self.tasks: dict[UUID, TaskState] = {}
|
|
82
|
+
self.task_request_pub = self.session.declare_publisher("reachy_mini/task")
|
|
83
|
+
self.task_progress_sub = self.session.declare_subscriber(
|
|
84
|
+
"reachy_mini/task_progress",
|
|
85
|
+
self._handle_task_progress,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
def wait_for_connection(self, timeout: float = 5.0) -> None:
|
|
89
|
+
"""Wait for the client to connect to the server.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
timeout (float): Maximum time to wait for the connection in seconds.
|
|
93
|
+
|
|
94
|
+
Raises:
|
|
95
|
+
TimeoutError: If the connection is not established within the timeout period.
|
|
96
|
+
|
|
97
|
+
"""
|
|
98
|
+
start = time.time()
|
|
99
|
+
while not self.joint_position_received.wait(
|
|
100
|
+
timeout=1.0
|
|
101
|
+
) or not self.head_pose_received.wait(timeout=1.0):
|
|
102
|
+
if time.time() - start > timeout:
|
|
103
|
+
self.disconnect()
|
|
104
|
+
raise TimeoutError(
|
|
105
|
+
"Timeout while waiting for connection with the server."
|
|
106
|
+
)
|
|
107
|
+
print("Waiting for connection with the server...")
|
|
108
|
+
|
|
109
|
+
self._is_alive = True
|
|
110
|
+
self._check_alive_evt = threading.Event()
|
|
111
|
+
threading.Thread(target=self.check_alive, daemon=True).start()
|
|
112
|
+
|
|
113
|
+
def check_alive(self) -> None:
|
|
114
|
+
"""Periodically check if the client is still connected to the server."""
|
|
115
|
+
while True:
|
|
116
|
+
self._is_alive = self.is_connected()
|
|
117
|
+
self._check_alive_evt.set()
|
|
118
|
+
time.sleep(1.0)
|
|
119
|
+
|
|
120
|
+
def is_connected(self) -> bool:
|
|
121
|
+
"""Check if the client is connected to the server."""
|
|
122
|
+
self.joint_position_received.clear()
|
|
123
|
+
self.head_pose_received.clear()
|
|
124
|
+
return self.joint_position_received.wait(
|
|
125
|
+
timeout=1.0
|
|
126
|
+
) and self.head_pose_received.wait(timeout=1.0)
|
|
127
|
+
|
|
128
|
+
def disconnect(self) -> None:
|
|
129
|
+
"""Disconnect the client from the server."""
|
|
130
|
+
self.session.close() # type: ignore[no-untyped-call]
|
|
131
|
+
|
|
132
|
+
def send_command(self, command: str) -> None:
|
|
133
|
+
"""Send a command to the server."""
|
|
134
|
+
if not self._is_alive:
|
|
135
|
+
raise ConnectionError("Lost connection with the server.")
|
|
136
|
+
|
|
137
|
+
self.cmd_pub.put(command.encode("utf-8"))
|
|
138
|
+
|
|
139
|
+
def _handle_joint_positions(self, sample: zenoh.Sample) -> None:
|
|
140
|
+
"""Handle incoming joint positions."""
|
|
141
|
+
if sample.payload:
|
|
142
|
+
positions = json.loads(sample.payload.to_string())
|
|
143
|
+
self._last_head_joint_positions = positions.get("head_joint_positions")
|
|
144
|
+
self._last_antennas_joint_positions = positions.get(
|
|
145
|
+
"antennas_joint_positions"
|
|
146
|
+
)
|
|
147
|
+
self.joint_position_received.set()
|
|
148
|
+
|
|
149
|
+
def _handle_recorded_data(self, sample: zenoh.Sample) -> None:
|
|
150
|
+
"""Handle incoming recorded data."""
|
|
151
|
+
print("Received recorded data.")
|
|
152
|
+
if sample.payload:
|
|
153
|
+
data = json.loads(sample.payload.to_string())
|
|
154
|
+
self._recorded_data = data
|
|
155
|
+
self._recorded_data_ready.set()
|
|
156
|
+
if self._recorded_data is not None:
|
|
157
|
+
print(f"Recorded data: {len(self._recorded_data)} frames received.")
|
|
158
|
+
|
|
159
|
+
def _handle_status(self, sample: zenoh.Sample) -> None:
|
|
160
|
+
"""Handle incoming status updates."""
|
|
161
|
+
if sample.payload:
|
|
162
|
+
status = json.loads(sample.payload.to_string())
|
|
163
|
+
self._last_status = status
|
|
164
|
+
self.status_received.set()
|
|
165
|
+
|
|
166
|
+
def get_current_joints(self) -> tuple[list[float], list[float]]:
|
|
167
|
+
"""Get the current joint positions."""
|
|
168
|
+
assert (
|
|
169
|
+
self._last_head_joint_positions is not None
|
|
170
|
+
and self._last_antennas_joint_positions is not None
|
|
171
|
+
), "No joint positions received yet. Wait for the client to connect."
|
|
172
|
+
return (
|
|
173
|
+
self._last_head_joint_positions.copy(),
|
|
174
|
+
self._last_antennas_joint_positions.copy(),
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
def wait_for_recorded_data(self, timeout: float = 5.0) -> bool:
|
|
178
|
+
"""Block until the daemon publishes the frames (or timeout)."""
|
|
179
|
+
return self._recorded_data_ready.wait(timeout)
|
|
180
|
+
|
|
181
|
+
def get_recorded_data(
|
|
182
|
+
self, wait: bool = True, timeout: float = 5.0
|
|
183
|
+
) -> Optional[List[Dict[str, float | List[float] | List[List[float]]]]]:
|
|
184
|
+
"""Return the cached recording, optionally blocking until it arrives.
|
|
185
|
+
|
|
186
|
+
Raises `TimeoutError` if nothing shows up in time.
|
|
187
|
+
"""
|
|
188
|
+
if wait and not self._recorded_data_ready.wait(timeout):
|
|
189
|
+
raise TimeoutError("Recording not received in time.")
|
|
190
|
+
self._recorded_data_ready.clear() # ready for next run
|
|
191
|
+
if self._recorded_data is not None:
|
|
192
|
+
return self._recorded_data.copy()
|
|
193
|
+
return None
|
|
194
|
+
|
|
195
|
+
def get_status(self, wait: bool = True, timeout: float = 5.0) -> Dict[str, Any]:
|
|
196
|
+
"""Get the last received status. Returns DaemonStatus as a dict."""
|
|
197
|
+
if wait and not self.status_received.wait(timeout):
|
|
198
|
+
raise TimeoutError("Status not received in time.")
|
|
199
|
+
self.status_received.clear() # ready for next run
|
|
200
|
+
return self._last_status
|
|
201
|
+
|
|
202
|
+
def _handle_head_pose(self, sample: zenoh.Sample) -> None:
|
|
203
|
+
"""Handle incoming head pose."""
|
|
204
|
+
if sample.payload:
|
|
205
|
+
pose = json.loads(sample.payload.to_string())
|
|
206
|
+
self._last_head_pose = np.array(pose.get("head_pose")).reshape(4, 4)
|
|
207
|
+
self.head_pose_received.set()
|
|
208
|
+
|
|
209
|
+
def get_current_head_pose(self) -> npt.NDArray[np.float64]:
|
|
210
|
+
"""Get the current head pose."""
|
|
211
|
+
assert self._last_head_pose is not None, "No head pose received yet."
|
|
212
|
+
return self._last_head_pose.copy()
|
|
213
|
+
|
|
214
|
+
def send_task_request(self, task_req: AnyTaskRequest) -> UUID:
|
|
215
|
+
"""Send a task request to the server."""
|
|
216
|
+
if not self._is_alive:
|
|
217
|
+
raise ConnectionError("Lost connection with the server.")
|
|
218
|
+
|
|
219
|
+
task = TaskRequest(uuid=uuid4(), req=task_req, timestamp=datetime.now())
|
|
220
|
+
|
|
221
|
+
self.tasks[task.uuid] = TaskState(event=threading.Event(), error=None)
|
|
222
|
+
|
|
223
|
+
self.task_request_pub.put(task.model_dump_json())
|
|
224
|
+
|
|
225
|
+
return task.uuid
|
|
226
|
+
|
|
227
|
+
def wait_for_task_completion(self, task_uid: UUID, timeout: float = 5.0) -> None:
|
|
228
|
+
"""Wait for the specified task to complete."""
|
|
229
|
+
if task_uid not in self.tasks:
|
|
230
|
+
raise ValueError("Task not found.")
|
|
231
|
+
|
|
232
|
+
self.tasks[task_uid].event.wait(timeout)
|
|
233
|
+
|
|
234
|
+
if not self.tasks[task_uid].event.is_set():
|
|
235
|
+
raise TimeoutError("Task did not complete in time.")
|
|
236
|
+
if self.tasks[task_uid].error is not None:
|
|
237
|
+
raise Exception(f"Task failed with error: {self.tasks[task_uid].error}")
|
|
238
|
+
|
|
239
|
+
del self.tasks[task_uid]
|
|
240
|
+
|
|
241
|
+
def _handle_task_progress(self, sample: zenoh.Sample) -> None:
|
|
242
|
+
if sample.payload:
|
|
243
|
+
progress = TaskProgress.model_validate_json(sample.payload.to_string())
|
|
244
|
+
assert progress.uuid in self.tasks, "Unknown task UUID."
|
|
245
|
+
|
|
246
|
+
if progress.error:
|
|
247
|
+
self.tasks[progress.uuid].error = progress.error
|
|
248
|
+
|
|
249
|
+
if progress.finished:
|
|
250
|
+
self.tasks[progress.uuid].event.set()
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
@dataclass
|
|
254
|
+
class TaskState:
|
|
255
|
+
"""Represents the state of a task."""
|
|
256
|
+
|
|
257
|
+
event: threading.Event
|
|
258
|
+
error: str | None
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"""Zenoh server for Reachy Mini.
|
|
2
|
+
|
|
3
|
+
This module implements a Zenoh server that allows communication with the Reachy Mini
|
|
4
|
+
robot. It handles commands for joint positions and torque settings, and publishes joint positions updates.
|
|
5
|
+
|
|
6
|
+
It uses the Zenoh protocol for efficient data exchange and can be configured to run
|
|
7
|
+
either on localhost only or to accept connections from other hosts.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import asyncio
|
|
11
|
+
import json
|
|
12
|
+
import threading
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
|
|
15
|
+
import numpy as np
|
|
16
|
+
import zenoh
|
|
17
|
+
|
|
18
|
+
from reachy_mini.daemon.backend.abstract import Backend, MotorControlMode
|
|
19
|
+
from reachy_mini.io.abstract import AbstractServer
|
|
20
|
+
from reachy_mini.io.protocol import (
|
|
21
|
+
GotoTaskRequest,
|
|
22
|
+
PlayMoveTaskRequest,
|
|
23
|
+
TaskProgress,
|
|
24
|
+
TaskRequest,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class ZenohServer(AbstractServer):
|
|
29
|
+
"""Zenoh server for Reachy Mini."""
|
|
30
|
+
|
|
31
|
+
def __init__(self, backend: Backend, localhost_only: bool = True):
|
|
32
|
+
"""Initialize the Zenoh server."""
|
|
33
|
+
self.localhost_only = localhost_only
|
|
34
|
+
self.backend = backend
|
|
35
|
+
|
|
36
|
+
self._lock = threading.Lock()
|
|
37
|
+
self._cmd_event = threading.Event()
|
|
38
|
+
|
|
39
|
+
def start(self) -> None:
|
|
40
|
+
"""Start the Zenoh server."""
|
|
41
|
+
if self.localhost_only:
|
|
42
|
+
c = zenoh.Config.from_json5(
|
|
43
|
+
json.dumps(
|
|
44
|
+
{
|
|
45
|
+
"listen": {
|
|
46
|
+
"endpoints": ["tcp/localhost:7447"],
|
|
47
|
+
},
|
|
48
|
+
"scouting": {
|
|
49
|
+
"multicast": {
|
|
50
|
+
"enabled": False,
|
|
51
|
+
},
|
|
52
|
+
"gossip": {
|
|
53
|
+
"enabled": False,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
"connect": {
|
|
57
|
+
"endpoints": [
|
|
58
|
+
"tcp/localhost:7447",
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
}
|
|
62
|
+
)
|
|
63
|
+
)
|
|
64
|
+
else:
|
|
65
|
+
c = zenoh.Config()
|
|
66
|
+
|
|
67
|
+
self.session = zenoh.open(c)
|
|
68
|
+
self.sub = self.session.declare_subscriber(
|
|
69
|
+
"reachy_mini/command",
|
|
70
|
+
self._handle_command,
|
|
71
|
+
)
|
|
72
|
+
self.pub = self.session.declare_publisher("reachy_mini/joint_positions")
|
|
73
|
+
self.pub_record = self.session.declare_publisher("reachy_mini/recorded_data")
|
|
74
|
+
self.backend.set_joint_positions_publisher(self.pub)
|
|
75
|
+
self.backend.set_recording_publisher(self.pub_record)
|
|
76
|
+
|
|
77
|
+
self.pub_pose = self.session.declare_publisher("reachy_mini/head_pose")
|
|
78
|
+
self.backend.set_pose_publisher(self.pub_pose)
|
|
79
|
+
|
|
80
|
+
self.task_req_sub = self.session.declare_subscriber(
|
|
81
|
+
"reachy_mini/task",
|
|
82
|
+
self._handle_task_request,
|
|
83
|
+
)
|
|
84
|
+
self.task_progress_pub = self.session.declare_publisher(
|
|
85
|
+
"reachy_mini/task_progress"
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
self.pub_status = self.session.declare_publisher("reachy_mini/daemon_status")
|
|
89
|
+
|
|
90
|
+
def stop(self) -> None:
|
|
91
|
+
"""Stop the Zenoh server."""
|
|
92
|
+
self.session.close() # type: ignore[no-untyped-call]
|
|
93
|
+
|
|
94
|
+
def command_received_event(self) -> threading.Event:
|
|
95
|
+
"""Wait for a new command and return it."""
|
|
96
|
+
return self._cmd_event
|
|
97
|
+
|
|
98
|
+
def _handle_command(self, sample: zenoh.Sample) -> None:
|
|
99
|
+
data = sample.payload.to_string()
|
|
100
|
+
command = json.loads(data)
|
|
101
|
+
with self._lock:
|
|
102
|
+
if "torque" in command:
|
|
103
|
+
if command["torque"]:
|
|
104
|
+
self.backend.set_motor_control_mode(MotorControlMode.Enabled)
|
|
105
|
+
else:
|
|
106
|
+
self.backend.set_motor_control_mode(MotorControlMode.Disabled)
|
|
107
|
+
if "head_joint_positions" in command:
|
|
108
|
+
self.backend.set_target_head_joint_positions(
|
|
109
|
+
np.array(command["head_joint_positions"])
|
|
110
|
+
)
|
|
111
|
+
if "head_pose" in command:
|
|
112
|
+
self.backend.set_target_head_pose(
|
|
113
|
+
np.array(command["head_pose"]).reshape(4, 4)
|
|
114
|
+
)
|
|
115
|
+
if "body_yaw" in command:
|
|
116
|
+
self.backend.set_target_body_yaw(command["body_yaw"])
|
|
117
|
+
if "antennas_joint_positions" in command:
|
|
118
|
+
self.backend.set_target_antenna_joint_positions(
|
|
119
|
+
np.array(command["antennas_joint_positions"]),
|
|
120
|
+
)
|
|
121
|
+
if "gravity_compensation" in command:
|
|
122
|
+
try:
|
|
123
|
+
if command["gravity_compensation"]:
|
|
124
|
+
self.backend.set_motor_control_mode(
|
|
125
|
+
MotorControlMode.GravityCompensation
|
|
126
|
+
)
|
|
127
|
+
else:
|
|
128
|
+
self.backend.set_motor_control_mode(MotorControlMode.Enabled)
|
|
129
|
+
|
|
130
|
+
except ValueError as e:
|
|
131
|
+
print(e)
|
|
132
|
+
if "automatic_body_yaw" in command:
|
|
133
|
+
self.backend.set_automatic_body_yaw(command["automatic_body_yaw"])
|
|
134
|
+
|
|
135
|
+
if "set_target_record" in command:
|
|
136
|
+
self.backend.append_record(command["set_target_record"])
|
|
137
|
+
|
|
138
|
+
if "start_recording" in command:
|
|
139
|
+
self.backend.start_recording()
|
|
140
|
+
if "stop_recording" in command:
|
|
141
|
+
self.backend.stop_recording()
|
|
142
|
+
self._cmd_event.set()
|
|
143
|
+
|
|
144
|
+
def _handle_task_request(self, sample: zenoh.Sample) -> None:
|
|
145
|
+
task_req = TaskRequest.model_validate_json(sample.payload.to_string())
|
|
146
|
+
|
|
147
|
+
if isinstance(task_req.req, GotoTaskRequest):
|
|
148
|
+
req = task_req.req
|
|
149
|
+
|
|
150
|
+
def task() -> None:
|
|
151
|
+
asyncio.run(
|
|
152
|
+
self.backend.goto_target(
|
|
153
|
+
head=np.array(req.head).reshape(4, 4) if req.head else None,
|
|
154
|
+
antennas=np.array(req.antennas) if req.antennas else None,
|
|
155
|
+
duration=req.duration,
|
|
156
|
+
method=req.method,
|
|
157
|
+
body_yaw=req.body_yaw,
|
|
158
|
+
)
|
|
159
|
+
)
|
|
160
|
+
elif isinstance(task_req.req, PlayMoveTaskRequest):
|
|
161
|
+
|
|
162
|
+
def task() -> None:
|
|
163
|
+
print("PLAY MOVE")
|
|
164
|
+
|
|
165
|
+
else:
|
|
166
|
+
assert False, f"Unknown task request type {task_req.req.__class__.__name__}"
|
|
167
|
+
|
|
168
|
+
def wrapped_task() -> None:
|
|
169
|
+
error = None
|
|
170
|
+
try:
|
|
171
|
+
task()
|
|
172
|
+
except Exception as e:
|
|
173
|
+
error = str(e)
|
|
174
|
+
|
|
175
|
+
progress = TaskProgress(
|
|
176
|
+
uuid=task_req.uuid,
|
|
177
|
+
finished=True,
|
|
178
|
+
error=error,
|
|
179
|
+
timestamp=datetime.now(),
|
|
180
|
+
)
|
|
181
|
+
self.task_progress_pub.put(progress.model_dump_json())
|
|
182
|
+
|
|
183
|
+
threading.Thread(target=wrapped_task).start()
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""Try to import kinematics engines, and provide mockup classes if they are not available."""
|
|
2
|
+
|
|
3
|
+
from typing import Annotated
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
import numpy.typing as npt
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
from reachy_mini.kinematics.nn_kinematics import NNKinematics # noqa: F401
|
|
10
|
+
except ImportError:
|
|
11
|
+
|
|
12
|
+
class MockupNNKinematics:
|
|
13
|
+
"""Mockup class for NNKinematics."""
|
|
14
|
+
|
|
15
|
+
def __init__(self, *args, **kwargs) -> None: # type: ignore[no-untyped-def]
|
|
16
|
+
"""Raise ImportError when trying to instantiate the class."""
|
|
17
|
+
raise ImportError(
|
|
18
|
+
"NNKinematics could not be imported. Make sure you run pip install reachy_mini[nn_kinematics]."
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
def ik(self, *args, **kwargs) -> Annotated[npt.NDArray[np.float64], (7,)]: # type: ignore[no-untyped-def]
|
|
22
|
+
"""Mockup method for ik."""
|
|
23
|
+
raise ImportError(
|
|
24
|
+
"NNKinematics could not be imported. Make sure you run pip install reachy_mini[nn_kinematics]."
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
def fk(self, *args, **kwargs) -> Annotated[npt.NDArray[np.float64], (4, 4)]: # type: ignore[no-untyped-def]
|
|
28
|
+
"""Mockup method for fk."""
|
|
29
|
+
raise ImportError(
|
|
30
|
+
"NNKinematics could not be imported. Make sure you run pip install reachy_mini[nn_kinematics]."
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
NNKinematics = MockupNNKinematics # type: ignore[assignment, misc]
|
|
34
|
+
|
|
35
|
+
try:
|
|
36
|
+
from reachy_mini.kinematics.placo_kinematics import PlacoKinematics # noqa: F401
|
|
37
|
+
except ImportError:
|
|
38
|
+
|
|
39
|
+
class MockupPlacoKinematics:
|
|
40
|
+
"""Mockup class for PlacoKinematics."""
|
|
41
|
+
|
|
42
|
+
def __init__(self, *args, **kwargs) -> None: # type: ignore[no-untyped-def]
|
|
43
|
+
"""Raise ImportError when trying to instantiate the class."""
|
|
44
|
+
raise ImportError(
|
|
45
|
+
"PlacoKinematics could not be imported. Make sure you run pip install reachy_mini[placo_kinematics]."
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
def ik(self, *args, **kwargs) -> Annotated[npt.NDArray[np.float64], (7,)]: # type: ignore[no-untyped-def]
|
|
49
|
+
"""Mockup method for ik."""
|
|
50
|
+
raise ImportError(
|
|
51
|
+
"PlacoKinematics could not be imported. Make sure you run pip install reachy_mini[placo_kinematics]."
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
def fk(self, *args, **kwargs) -> Annotated[npt.NDArray[np.float64], (4, 4)]: # type: ignore[no-untyped-def]
|
|
55
|
+
"""Mockup method for fk."""
|
|
56
|
+
raise ImportError(
|
|
57
|
+
"PlacoKinematics could not be imported. Make sure you run pip install reachy_mini[placo_kinematics]."
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
PlacoKinematics = MockupPlacoKinematics # type: ignore[assignment, misc]
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
from reachy_mini.kinematics.analytical_kinematics import ( # noqa: F401
|
|
64
|
+
AnalyticalKinematics,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
AnyKinematics = NNKinematics | PlacoKinematics | AnalyticalKinematics
|
|
68
|
+
__all__ = ["NNKinematics", "PlacoKinematics", "AnalyticalKinematics"]
|