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