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,750 @@
|
|
|
1
|
+
"""Base class for robot backends, simulated or real.
|
|
2
|
+
|
|
3
|
+
This module defines the `Backend` class, which serves as a base for implementing
|
|
4
|
+
different types of robot backends, whether they are simulated (like Mujoco) or real
|
|
5
|
+
(connected via serial port). The class provides methods for managing joint positions,
|
|
6
|
+
torque control, and other backend-specific functionalities.
|
|
7
|
+
It is designed to be extended by subclasses that implement the specific behavior for
|
|
8
|
+
each type of backend.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import asyncio
|
|
12
|
+
import json
|
|
13
|
+
import logging
|
|
14
|
+
import threading
|
|
15
|
+
import time
|
|
16
|
+
import typing
|
|
17
|
+
from abc import abstractmethod
|
|
18
|
+
from enum import Enum
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
from typing import Annotated, Any, Dict, Optional
|
|
21
|
+
|
|
22
|
+
import numpy as np
|
|
23
|
+
import zenoh
|
|
24
|
+
from numpy.typing import NDArray
|
|
25
|
+
from scipy.spatial.transform import Rotation as R
|
|
26
|
+
|
|
27
|
+
if typing.TYPE_CHECKING:
|
|
28
|
+
from reachy_mini.daemon.backend.mujoco.backend import MujocoBackendStatus
|
|
29
|
+
from reachy_mini.daemon.backend.robot.backend import RobotBackendStatus
|
|
30
|
+
from reachy_mini.kinematics import AnyKinematics
|
|
31
|
+
from reachy_mini.media.audio_sounddevice import SoundDeviceAudio
|
|
32
|
+
from reachy_mini.motion.goto import GotoMove
|
|
33
|
+
from reachy_mini.motion.move import Move
|
|
34
|
+
from reachy_mini.utils.constants import MODELS_ROOT_PATH, URDF_ROOT_PATH
|
|
35
|
+
from reachy_mini.utils.interpolation import (
|
|
36
|
+
InterpolationTechnique,
|
|
37
|
+
distance_between_poses,
|
|
38
|
+
time_trajectory,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class MotorControlMode(str, Enum):
|
|
43
|
+
"""Enum for motor control modes."""
|
|
44
|
+
|
|
45
|
+
Enabled = "enabled" # Torque ON and controlled in position
|
|
46
|
+
Disabled = "disabled" # Torque OFF
|
|
47
|
+
GravityCompensation = "gravity_compensation" # Torque ON and controlled in current to compensate for gravity
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class Backend:
|
|
51
|
+
"""Base class for robot backends, simulated or real."""
|
|
52
|
+
|
|
53
|
+
def __init__(
|
|
54
|
+
self,
|
|
55
|
+
log_level: str = "INFO",
|
|
56
|
+
check_collision: bool = False,
|
|
57
|
+
kinematics_engine: str = "AnalyticalKinematics",
|
|
58
|
+
) -> None:
|
|
59
|
+
"""Initialize the backend."""
|
|
60
|
+
self.logger = logging.getLogger(__name__)
|
|
61
|
+
self.logger.setLevel(log_level)
|
|
62
|
+
|
|
63
|
+
self.should_stop = threading.Event()
|
|
64
|
+
self.ready = threading.Event()
|
|
65
|
+
|
|
66
|
+
self.check_collision = (
|
|
67
|
+
check_collision # Flag to enable/disable collision checking
|
|
68
|
+
)
|
|
69
|
+
self.kinematics_engine = kinematics_engine
|
|
70
|
+
|
|
71
|
+
self.logger.info(f"Using {self.kinematics_engine} kinematics engine")
|
|
72
|
+
|
|
73
|
+
if self.check_collision:
|
|
74
|
+
assert self.kinematics_engine == "Placo", (
|
|
75
|
+
"Collision checking is only available with Placo Kinematics"
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
self.gravity_compensation_mode = False # Flag for gravity compensation mode
|
|
79
|
+
|
|
80
|
+
if self.gravity_compensation_mode:
|
|
81
|
+
assert self.kinematics_engine == "Placo", (
|
|
82
|
+
"Gravity compensation is only available with Placo kinematics"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
if self.kinematics_engine == "Placo":
|
|
86
|
+
from reachy_mini.kinematics import PlacoKinematics
|
|
87
|
+
|
|
88
|
+
self.head_kinematics: AnyKinematics = PlacoKinematics(
|
|
89
|
+
URDF_ROOT_PATH, check_collision=self.check_collision
|
|
90
|
+
)
|
|
91
|
+
elif self.kinematics_engine == "NN":
|
|
92
|
+
from reachy_mini.kinematics import NNKinematics
|
|
93
|
+
|
|
94
|
+
self.head_kinematics = NNKinematics(MODELS_ROOT_PATH)
|
|
95
|
+
elif self.kinematics_engine == "AnalyticalKinematics":
|
|
96
|
+
from reachy_mini.kinematics import AnalyticalKinematics
|
|
97
|
+
|
|
98
|
+
self.head_kinematics = AnalyticalKinematics()
|
|
99
|
+
else:
|
|
100
|
+
raise ValueError(
|
|
101
|
+
f"Unknown kinematics engine: {self.kinematics_engine}. Use 'Placo', 'NN' or 'AnalyticalKinematics'."
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
self.current_head_pose: Annotated[NDArray[np.float64], (4, 4)] | None = (
|
|
105
|
+
None # 4x4 pose matrix
|
|
106
|
+
)
|
|
107
|
+
self.target_head_pose: Annotated[NDArray[np.float64], (4, 4)] | None = (
|
|
108
|
+
None # 4x4 pose matrix
|
|
109
|
+
)
|
|
110
|
+
self.target_body_yaw: float | None = (
|
|
111
|
+
None # Last body yaw used in IK computations
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
self.target_head_joint_positions: (
|
|
115
|
+
Annotated[NDArray[np.float64], (7,)] | None
|
|
116
|
+
) = None # [yaw, 0, 1, 2, 3, 4, 5]
|
|
117
|
+
self.current_head_joint_positions: (
|
|
118
|
+
Annotated[NDArray[np.float64], (7,)] | None
|
|
119
|
+
) = None # [yaw, 0, 1, 2, 3, 4, 5]
|
|
120
|
+
self.target_antenna_joint_positions: (
|
|
121
|
+
Annotated[NDArray[np.float64], (2,)] | None
|
|
122
|
+
) = None # [0, 1]
|
|
123
|
+
self.current_antenna_joint_positions: (
|
|
124
|
+
Annotated[NDArray[np.float64], (2,)] | None
|
|
125
|
+
) = None # [0, 1]
|
|
126
|
+
|
|
127
|
+
self.joint_positions_publisher: zenoh.Publisher | None = None
|
|
128
|
+
self.pose_publisher: zenoh.Publisher | None = None
|
|
129
|
+
self.recording_publisher: zenoh.Publisher | None = None
|
|
130
|
+
self.error: str | None = None # To store any error that occurs during execution
|
|
131
|
+
self.is_recording = False # Flag to indicate if recording is active
|
|
132
|
+
self.recorded_data: list[dict[str, Any]] = [] # List to store recorded data
|
|
133
|
+
|
|
134
|
+
# variables to store the last computed head joint positions and pose
|
|
135
|
+
self._last_target_body_yaw: float | None = (
|
|
136
|
+
None # Last body yaw used in IK computations
|
|
137
|
+
)
|
|
138
|
+
self._last_target_head_pose: Annotated[NDArray[np.float64], (4, 4)] | None = (
|
|
139
|
+
None # Last head pose used in IK computations
|
|
140
|
+
)
|
|
141
|
+
self.target_head_joint_current: Annotated[NDArray[np.float64], (7,)] | None = (
|
|
142
|
+
None # Placeholder for head joint torque
|
|
143
|
+
)
|
|
144
|
+
self.ik_required = False # Flag to indicate if IK computation is required
|
|
145
|
+
|
|
146
|
+
self.is_shutting_down = False
|
|
147
|
+
|
|
148
|
+
# Tolerance for kinematics computations
|
|
149
|
+
# For Forward kinematics (around 0.25deg)
|
|
150
|
+
# - FK is calculated at each timestep and is susceptible to noise
|
|
151
|
+
self._fk_kin_tolerance = 1e-3 # rads
|
|
152
|
+
# For Inverse kinematics (around 0.5mm and 0.1 degrees)
|
|
153
|
+
# - IK is calculated only when the head pose is set by the user
|
|
154
|
+
self._ik_kin_tolerance = {
|
|
155
|
+
"rad": 2e-3, # rads
|
|
156
|
+
"m": 0.5e-3, # m
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
# Recording lock to guard buffer swaps and appends
|
|
160
|
+
self._rec_lock = threading.Lock()
|
|
161
|
+
|
|
162
|
+
self.audio = SoundDeviceAudio(log_level=log_level)
|
|
163
|
+
|
|
164
|
+
# Life cycle methods
|
|
165
|
+
def wrapped_run(self) -> None:
|
|
166
|
+
"""Run the backend in a try-except block to store errors."""
|
|
167
|
+
try:
|
|
168
|
+
self.run()
|
|
169
|
+
except Exception as e:
|
|
170
|
+
self.error = str(e)
|
|
171
|
+
self.close()
|
|
172
|
+
raise e
|
|
173
|
+
|
|
174
|
+
def run(self) -> None:
|
|
175
|
+
"""Run the backend.
|
|
176
|
+
|
|
177
|
+
This method is a placeholder and should be overridden by subclasses.
|
|
178
|
+
"""
|
|
179
|
+
raise NotImplementedError("The method run should be overridden by subclasses.")
|
|
180
|
+
|
|
181
|
+
def close(self) -> None:
|
|
182
|
+
"""Close the backend.
|
|
183
|
+
|
|
184
|
+
This method is a placeholder and should be overridden by subclasses.
|
|
185
|
+
"""
|
|
186
|
+
raise NotImplementedError(
|
|
187
|
+
"The method close should be overridden by subclasses."
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
def get_status(self) -> "RobotBackendStatus | MujocoBackendStatus":
|
|
191
|
+
"""Return backend statistics.
|
|
192
|
+
|
|
193
|
+
This method is a placeholder and should be overridden by subclasses.
|
|
194
|
+
"""
|
|
195
|
+
raise NotImplementedError(
|
|
196
|
+
"The method get_status should be overridden by subclasses."
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
# Present/Target joint positions
|
|
200
|
+
def set_joint_positions_publisher(self, publisher: zenoh.Publisher) -> None:
|
|
201
|
+
"""Set the publisher for joint positions.
|
|
202
|
+
|
|
203
|
+
Args:
|
|
204
|
+
publisher: A publisher object that will be used to publish joint positions.
|
|
205
|
+
|
|
206
|
+
"""
|
|
207
|
+
self.joint_positions_publisher = publisher
|
|
208
|
+
|
|
209
|
+
def set_pose_publisher(self, publisher: zenoh.Publisher) -> None:
|
|
210
|
+
"""Set the publisher for head pose.
|
|
211
|
+
|
|
212
|
+
Args:
|
|
213
|
+
publisher: A publisher object that will be used to publish head pose.
|
|
214
|
+
|
|
215
|
+
"""
|
|
216
|
+
self.pose_publisher = publisher
|
|
217
|
+
|
|
218
|
+
def update_target_head_joints_from_ik(
|
|
219
|
+
self,
|
|
220
|
+
pose: Annotated[NDArray[np.float64], (4, 4)] | None = None,
|
|
221
|
+
body_yaw: float | None = None,
|
|
222
|
+
) -> None:
|
|
223
|
+
"""Update the target head joint positions from inverse kinematics.
|
|
224
|
+
|
|
225
|
+
Args:
|
|
226
|
+
pose (np.ndarray): 4x4 pose matrix representing the head pose.
|
|
227
|
+
body_yaw (float): The yaw angle of the body, used to adjust the head pose.
|
|
228
|
+
|
|
229
|
+
"""
|
|
230
|
+
if pose is None:
|
|
231
|
+
pose = (
|
|
232
|
+
self.target_head_pose
|
|
233
|
+
if self.target_head_pose is not None
|
|
234
|
+
else np.eye(4)
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
if body_yaw is None:
|
|
238
|
+
body_yaw = self.target_body_yaw if self.target_body_yaw is not None else 0.0
|
|
239
|
+
|
|
240
|
+
# Compute the inverse kinematics to get the head joint positions
|
|
241
|
+
joints = self.head_kinematics.ik(pose, body_yaw=body_yaw)
|
|
242
|
+
if joints is None or np.any(np.isnan(joints)):
|
|
243
|
+
raise ValueError("WARNING: Collision detected or head pose not achievable!")
|
|
244
|
+
|
|
245
|
+
# update the target head pose and body yaw
|
|
246
|
+
self._last_target_head_pose = pose
|
|
247
|
+
self._last_target_body_yaw = body_yaw
|
|
248
|
+
|
|
249
|
+
self.target_head_joint_positions = joints
|
|
250
|
+
|
|
251
|
+
def set_target_head_pose(
|
|
252
|
+
self,
|
|
253
|
+
pose: Annotated[NDArray[np.float64], (4, 4)],
|
|
254
|
+
) -> None:
|
|
255
|
+
"""Set the target head pose for the robot.
|
|
256
|
+
|
|
257
|
+
Args:
|
|
258
|
+
pose (np.ndarray): 4x4 pose matrix representing the head pose.
|
|
259
|
+
|
|
260
|
+
"""
|
|
261
|
+
self.target_head_pose = pose
|
|
262
|
+
self.ik_required = True
|
|
263
|
+
|
|
264
|
+
def set_target_body_yaw(self, body_yaw: float) -> None:
|
|
265
|
+
"""Set the target body yaw for the robot.
|
|
266
|
+
|
|
267
|
+
Only used when doing a set_target() with a standalone body_yaw (no head pose).
|
|
268
|
+
|
|
269
|
+
Args:
|
|
270
|
+
body_yaw (float): The yaw angle of the body
|
|
271
|
+
|
|
272
|
+
"""
|
|
273
|
+
self.target_body_yaw = body_yaw
|
|
274
|
+
self.ik_required = True # Do we need that here?
|
|
275
|
+
|
|
276
|
+
def set_target_head_joint_positions(
|
|
277
|
+
self, positions: Annotated[NDArray[np.float64], (7,)] | None
|
|
278
|
+
) -> None:
|
|
279
|
+
"""Set the head joint positions.
|
|
280
|
+
|
|
281
|
+
Args:
|
|
282
|
+
positions (List[float]): A list of joint positions for the head.
|
|
283
|
+
|
|
284
|
+
"""
|
|
285
|
+
self.target_head_joint_positions = positions
|
|
286
|
+
self.ik_required = False
|
|
287
|
+
|
|
288
|
+
def set_target(
|
|
289
|
+
self,
|
|
290
|
+
head: Annotated[NDArray[np.float64], (4, 4)] | None = None, # 4x4 pose matrix
|
|
291
|
+
antennas: Annotated[NDArray[np.float64], (2,)]
|
|
292
|
+
| None = None, # [right_angle, left_angle] (in rads)
|
|
293
|
+
body_yaw: float = 0.0, # Body yaw angle in radians
|
|
294
|
+
) -> None:
|
|
295
|
+
"""Set the target head pose and/or antenna positions and/or body_yaw."""
|
|
296
|
+
if head is not None:
|
|
297
|
+
self.set_target_head_pose(head)
|
|
298
|
+
|
|
299
|
+
if body_yaw is not None:
|
|
300
|
+
self.set_target_body_yaw(body_yaw)
|
|
301
|
+
|
|
302
|
+
if antennas is not None:
|
|
303
|
+
self.set_target_antenna_joint_positions(antennas)
|
|
304
|
+
|
|
305
|
+
def set_target_antenna_joint_positions(
|
|
306
|
+
self,
|
|
307
|
+
positions: Annotated[NDArray[np.float64], (2,)],
|
|
308
|
+
) -> None:
|
|
309
|
+
"""Set the antenna joint positions.
|
|
310
|
+
|
|
311
|
+
Args:
|
|
312
|
+
positions (List[float]): A list of joint positions for the antenna.
|
|
313
|
+
|
|
314
|
+
"""
|
|
315
|
+
self.target_antenna_joint_positions = positions
|
|
316
|
+
|
|
317
|
+
def set_target_head_joint_current(
|
|
318
|
+
self,
|
|
319
|
+
current: Annotated[NDArray[np.float64], (7,)],
|
|
320
|
+
) -> None:
|
|
321
|
+
"""Set the head joint current.
|
|
322
|
+
|
|
323
|
+
Args:
|
|
324
|
+
current (Annotated[NDArray[np.float64], (7,)]): A list of current values for the head motors.
|
|
325
|
+
|
|
326
|
+
"""
|
|
327
|
+
self.target_head_joint_current = current
|
|
328
|
+
self.ik_required = False
|
|
329
|
+
|
|
330
|
+
async def play_move(
|
|
331
|
+
self,
|
|
332
|
+
move: Move,
|
|
333
|
+
play_frequency: float = 100.0,
|
|
334
|
+
initial_goto_duration: float = 0.0,
|
|
335
|
+
) -> None:
|
|
336
|
+
"""Asynchronously play a Move.
|
|
337
|
+
|
|
338
|
+
Args:
|
|
339
|
+
move (Move): The Move object to be played.
|
|
340
|
+
play_frequency (float): The frequency at which to evaluate the move (in Hz).
|
|
341
|
+
initial_goto_duration (float): Duration for an initial goto to the move's starting position. If 0.0, no initial goto is performed.
|
|
342
|
+
|
|
343
|
+
"""
|
|
344
|
+
if initial_goto_duration > 0.0:
|
|
345
|
+
start_head_pose, start_antennas_positions, start_body_yaw = move.evaluate(
|
|
346
|
+
0.0
|
|
347
|
+
)
|
|
348
|
+
await self.goto_target(
|
|
349
|
+
head=start_head_pose,
|
|
350
|
+
antennas=start_antennas_positions,
|
|
351
|
+
duration=initial_goto_duration,
|
|
352
|
+
body_yaw=start_body_yaw,
|
|
353
|
+
)
|
|
354
|
+
sleep_period = 1.0 / play_frequency
|
|
355
|
+
|
|
356
|
+
t0 = time.time()
|
|
357
|
+
while time.time() - t0 < move.duration:
|
|
358
|
+
t = time.time() - t0
|
|
359
|
+
|
|
360
|
+
head, antennas, body_yaw = move.evaluate(t)
|
|
361
|
+
if head is not None:
|
|
362
|
+
self.set_target_head_pose(head)
|
|
363
|
+
if body_yaw is not None:
|
|
364
|
+
self.set_target_body_yaw(body_yaw)
|
|
365
|
+
if antennas is not None:
|
|
366
|
+
self.set_target_antenna_joint_positions(antennas)
|
|
367
|
+
|
|
368
|
+
elapsed = time.time() - t0 - t
|
|
369
|
+
if elapsed < sleep_period:
|
|
370
|
+
await asyncio.sleep(sleep_period - elapsed)
|
|
371
|
+
else:
|
|
372
|
+
await asyncio.sleep(0.001)
|
|
373
|
+
|
|
374
|
+
async def goto_target(
|
|
375
|
+
self,
|
|
376
|
+
head: Annotated[NDArray[np.float64], (4, 4)] | None = None, # 4x4 pose matrix
|
|
377
|
+
antennas: Annotated[NDArray[np.float64], (2,)]
|
|
378
|
+
| None = None, # [right_angle, left_angle] (in rads)
|
|
379
|
+
duration: float = 0.5, # Duration in seconds for the movement, default is 0.5 seconds.
|
|
380
|
+
method: InterpolationTechnique = InterpolationTechnique.MIN_JERK, # can be "linear", "minjerk", "ease" or "cartoon", default is "minjerk"
|
|
381
|
+
body_yaw: float | None = 0.0, # Body yaw angle in radians
|
|
382
|
+
) -> None:
|
|
383
|
+
"""Asynchronously go to a target head pose and/or antennas position using task space interpolation, in "duration" seconds.
|
|
384
|
+
|
|
385
|
+
Args:
|
|
386
|
+
head (np.ndarray | None): 4x4 pose matrix representing the target head pose.
|
|
387
|
+
antennas (np.ndarray | list[float] | None): 1D array with two elements representing the angles of the antennas in radians.
|
|
388
|
+
duration (float): Duration of the movement in seconds.
|
|
389
|
+
method (str): Interpolation method to use ("linear", "minjerk", "ease", "cartoon"). Default is "minjerk".
|
|
390
|
+
body_yaw (float | None): Body yaw angle in radians.
|
|
391
|
+
|
|
392
|
+
Raises:
|
|
393
|
+
ValueError: If neither head nor antennas are provided, or if duration is not positive.
|
|
394
|
+
|
|
395
|
+
"""
|
|
396
|
+
return await self.play_move(
|
|
397
|
+
move=GotoMove(
|
|
398
|
+
start_head_pose=self.get_present_head_pose(),
|
|
399
|
+
target_head_pose=head,
|
|
400
|
+
start_body_yaw=self.get_present_body_yaw(),
|
|
401
|
+
target_body_yaw=body_yaw,
|
|
402
|
+
start_antennas=np.array(self.get_present_antenna_joint_positions()),
|
|
403
|
+
target_antennas=np.array(antennas) if antennas is not None else None,
|
|
404
|
+
duration=duration,
|
|
405
|
+
method=method,
|
|
406
|
+
)
|
|
407
|
+
)
|
|
408
|
+
|
|
409
|
+
async def goto_joint_positions(
|
|
410
|
+
self,
|
|
411
|
+
head_joint_positions: list[float]
|
|
412
|
+
| None = None, # [yaw, stewart_platform x 6] length 7
|
|
413
|
+
antennas_joint_positions: list[float]
|
|
414
|
+
| None = None, # [right_angle, left_angle] length 2
|
|
415
|
+
duration: float = 0.5, # Duration in seconds for the movement
|
|
416
|
+
method: InterpolationTechnique = InterpolationTechnique.MIN_JERK, # can be "linear", "minjerk", "ease" or "cartoon", default is "minjerk"
|
|
417
|
+
) -> None:
|
|
418
|
+
"""Asynchronously go to a target head joint positions and/or antennas joint positions using joint space interpolation, in "duration" seconds.
|
|
419
|
+
|
|
420
|
+
Go to a target head joint positions and/or antennas joint positions using joint space interpolation, in "duration" seconds.
|
|
421
|
+
|
|
422
|
+
Args:
|
|
423
|
+
head_joint_positions (Optional[List[float]]): List of head joint positions in radians (length 7).
|
|
424
|
+
antennas_joint_positions (Optional[List[float]]): List of antennas joint positions in radians (length 2).
|
|
425
|
+
duration (float): Duration of the movement in seconds. Default is 0.5 seconds.
|
|
426
|
+
method (str): Interpolation method to use ("linear", "minjerk", "ease", "cartoon"). Default is "minjerk".
|
|
427
|
+
|
|
428
|
+
Raises:
|
|
429
|
+
ValueError: If neither head_joint_positions nor antennas_joint_positions are provided, or if duration is not positive.
|
|
430
|
+
|
|
431
|
+
"""
|
|
432
|
+
if duration <= 0.0:
|
|
433
|
+
raise ValueError(
|
|
434
|
+
"Duration must be positive and non-zero. Use set_target() for immediate position setting."
|
|
435
|
+
)
|
|
436
|
+
|
|
437
|
+
start_head = np.array(self.get_present_head_joint_positions())
|
|
438
|
+
start_antennas = np.array(self.get_present_antenna_joint_positions())
|
|
439
|
+
|
|
440
|
+
target_head = (
|
|
441
|
+
np.array(head_joint_positions)
|
|
442
|
+
if head_joint_positions is not None
|
|
443
|
+
else start_head
|
|
444
|
+
)
|
|
445
|
+
target_antennas = (
|
|
446
|
+
np.array(antennas_joint_positions)
|
|
447
|
+
if antennas_joint_positions is not None
|
|
448
|
+
else start_antennas
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
t0 = time.time()
|
|
452
|
+
while time.time() - t0 < duration:
|
|
453
|
+
t = time.time() - t0
|
|
454
|
+
|
|
455
|
+
interp_time = time_trajectory(t / duration, method=method)
|
|
456
|
+
|
|
457
|
+
head_joint = start_head + (target_head - start_head) * interp_time
|
|
458
|
+
antennas_joint = (
|
|
459
|
+
start_antennas + (target_antennas - start_antennas) * interp_time
|
|
460
|
+
)
|
|
461
|
+
|
|
462
|
+
self.set_target_head_joint_positions(head_joint)
|
|
463
|
+
self.set_target_antenna_joint_positions(antennas_joint)
|
|
464
|
+
await asyncio.sleep(0.01)
|
|
465
|
+
|
|
466
|
+
def set_recording_publisher(self, publisher: zenoh.Publisher) -> None:
|
|
467
|
+
"""Set the publisher for recording data.
|
|
468
|
+
|
|
469
|
+
Args:
|
|
470
|
+
publisher: A publisher object that will be used to publish recorded data.
|
|
471
|
+
|
|
472
|
+
"""
|
|
473
|
+
self.recording_publisher = publisher
|
|
474
|
+
|
|
475
|
+
def append_record(self, record: dict[str, Any]) -> None:
|
|
476
|
+
"""Append a record to the recorded data.
|
|
477
|
+
|
|
478
|
+
Args:
|
|
479
|
+
record (dict): A dictionary containing the record data to be appended.
|
|
480
|
+
|
|
481
|
+
"""
|
|
482
|
+
if not self.is_recording:
|
|
483
|
+
return
|
|
484
|
+
# Double-check under lock to avoid race with stop_recording
|
|
485
|
+
with self._rec_lock:
|
|
486
|
+
if self.is_recording:
|
|
487
|
+
self.recorded_data.append(record)
|
|
488
|
+
|
|
489
|
+
def start_recording(self) -> None:
|
|
490
|
+
"""Start recording data."""
|
|
491
|
+
with self._rec_lock:
|
|
492
|
+
self.recorded_data = []
|
|
493
|
+
self.is_recording = True
|
|
494
|
+
|
|
495
|
+
def stop_recording(self) -> None:
|
|
496
|
+
"""Stop recording data and publish the recorded data."""
|
|
497
|
+
# Swap buffer under lock so writers cannot touch the published list
|
|
498
|
+
with self._rec_lock:
|
|
499
|
+
self.is_recording = False
|
|
500
|
+
recorded_data, self.recorded_data = self.recorded_data, []
|
|
501
|
+
# Publish outside the lock
|
|
502
|
+
if self.recording_publisher is not None:
|
|
503
|
+
self.recording_publisher.put(json.dumps(recorded_data))
|
|
504
|
+
else:
|
|
505
|
+
self.logger.warning(
|
|
506
|
+
"stop_recording called but recording_publisher is not set; dropping data."
|
|
507
|
+
)
|
|
508
|
+
|
|
509
|
+
def get_present_head_joint_positions(self) -> Annotated[NDArray[np.float64], (7,)]:
|
|
510
|
+
"""Return the present head joint positions.
|
|
511
|
+
|
|
512
|
+
This method is a placeholder and should be overridden by subclasses.
|
|
513
|
+
"""
|
|
514
|
+
raise NotImplementedError(
|
|
515
|
+
"The method get_present_head_joint_positions should be overridden by subclasses."
|
|
516
|
+
)
|
|
517
|
+
|
|
518
|
+
def get_present_body_yaw(self) -> float:
|
|
519
|
+
"""Return the present body yaw."""
|
|
520
|
+
yaw: float = self.get_present_head_joint_positions()[0]
|
|
521
|
+
return yaw
|
|
522
|
+
|
|
523
|
+
def get_present_head_pose(self) -> Annotated[NDArray[np.float64], (4, 4)]:
|
|
524
|
+
"""Return the present head pose as a 4x4 matrix."""
|
|
525
|
+
assert self.current_head_pose is not None, (
|
|
526
|
+
"The current head pose is not set. Please call the update_head_kinematics_model method first."
|
|
527
|
+
)
|
|
528
|
+
return self.current_head_pose
|
|
529
|
+
|
|
530
|
+
def get_current_head_pose(self) -> Annotated[NDArray[np.float64], (4, 4)]:
|
|
531
|
+
"""Return the present head pose as a 4x4 matrix."""
|
|
532
|
+
return self.get_present_head_pose()
|
|
533
|
+
|
|
534
|
+
def get_present_antenna_joint_positions(
|
|
535
|
+
self,
|
|
536
|
+
) -> Annotated[NDArray[np.float64], (2,)]:
|
|
537
|
+
"""Return the present antenna joint positions.
|
|
538
|
+
|
|
539
|
+
This method is a placeholder and should be overridden by subclasses.
|
|
540
|
+
"""
|
|
541
|
+
raise NotImplementedError(
|
|
542
|
+
"The method get_present_antenna_joint_positions should be overridden by subclasses."
|
|
543
|
+
)
|
|
544
|
+
|
|
545
|
+
# Kinematics methods
|
|
546
|
+
def update_head_kinematics_model(
|
|
547
|
+
self,
|
|
548
|
+
head_joint_positions: Annotated[NDArray[np.float64], (7,)] | None = None,
|
|
549
|
+
antennas_joint_positions: Annotated[NDArray[np.float64], (2,)] | None = None,
|
|
550
|
+
) -> None:
|
|
551
|
+
"""Update the placo kinematics of the robot.
|
|
552
|
+
|
|
553
|
+
Args:
|
|
554
|
+
head_joint_positions (List[float] | None): The joint positions of the head.
|
|
555
|
+
antennas_joint_positions (List[float] | None): The joint positions of the antennas.
|
|
556
|
+
|
|
557
|
+
Returns:
|
|
558
|
+
None: This method does not return anything.
|
|
559
|
+
|
|
560
|
+
This method updates the head kinematics model with the given joint positions.
|
|
561
|
+
- If the joint positions are not provided, it will use the current joint positions.
|
|
562
|
+
- If the head joint positions have not changed, it will return without recomputing the forward kinematics.
|
|
563
|
+
- If the head joint positions have changed, it will compute the forward kinematics to get the current head pose.
|
|
564
|
+
- If the forward kinematics fails, it will raise an assertion error.
|
|
565
|
+
- If the antennas joint positions are provided, it will update the current antenna joint positions.
|
|
566
|
+
|
|
567
|
+
Note:
|
|
568
|
+
This method will update the `current_head_pose` and `current_head_joint_positions`
|
|
569
|
+
attributes of the backend instance with the computed values. And the `current_antenna_joint_positions` if provided.
|
|
570
|
+
|
|
571
|
+
"""
|
|
572
|
+
if head_joint_positions is None:
|
|
573
|
+
head_joint_positions = self.get_present_head_joint_positions()
|
|
574
|
+
|
|
575
|
+
# Compute the forward kinematics to get the current head pose
|
|
576
|
+
self.current_head_pose = self.head_kinematics.fk(head_joint_positions)
|
|
577
|
+
|
|
578
|
+
# Check if the FK was successful
|
|
579
|
+
assert self.current_head_pose is not None, (
|
|
580
|
+
"FK failed to compute the current head pose."
|
|
581
|
+
)
|
|
582
|
+
|
|
583
|
+
# Store the last head joint positions
|
|
584
|
+
self.current_head_joint_positions = head_joint_positions
|
|
585
|
+
|
|
586
|
+
if antennas_joint_positions is not None:
|
|
587
|
+
self.current_antenna_joint_positions = antennas_joint_positions
|
|
588
|
+
|
|
589
|
+
def set_automatic_body_yaw(self, body_yaw: float) -> None:
|
|
590
|
+
"""Set the automatic body yaw.
|
|
591
|
+
|
|
592
|
+
Args:
|
|
593
|
+
body_yaw (float): The yaw angle of the body.
|
|
594
|
+
|
|
595
|
+
"""
|
|
596
|
+
self.head_kinematics.start_body_yaw = body_yaw
|
|
597
|
+
|
|
598
|
+
def get_urdf(self) -> str:
|
|
599
|
+
"""Get the URDF representation of the robot."""
|
|
600
|
+
urdf_path = Path(URDF_ROOT_PATH) / "robot.urdf"
|
|
601
|
+
|
|
602
|
+
with open(urdf_path, "r") as f:
|
|
603
|
+
return f.read()
|
|
604
|
+
|
|
605
|
+
# Multimedia methods
|
|
606
|
+
def play_sound(self, sound_file: str) -> None:
|
|
607
|
+
"""Play a sound file from the assets directory.
|
|
608
|
+
|
|
609
|
+
If the file is not found in the assets directory, try to load the path itself.
|
|
610
|
+
|
|
611
|
+
Args:
|
|
612
|
+
sound_file (str): The name of the sound file to play (e.g., "wake_up.wav").
|
|
613
|
+
|
|
614
|
+
"""
|
|
615
|
+
self.audio.play_sound(sound_file, autoclean=True)
|
|
616
|
+
|
|
617
|
+
# Basic move definitions
|
|
618
|
+
INIT_HEAD_POSE = np.eye(4)
|
|
619
|
+
|
|
620
|
+
SLEEP_HEAD_JOINT_POSITIONS = [
|
|
621
|
+
0,
|
|
622
|
+
-0.9848156658225817,
|
|
623
|
+
1.2624661884298831,
|
|
624
|
+
-0.24390294527381684,
|
|
625
|
+
0.20555342557667577,
|
|
626
|
+
-1.2363885150358267,
|
|
627
|
+
1.0032234352772091,
|
|
628
|
+
]
|
|
629
|
+
|
|
630
|
+
SLEEP_ANTENNAS_JOINT_POSITIONS = np.array((-3.05, 3.05))
|
|
631
|
+
SLEEP_HEAD_POSE = np.array(
|
|
632
|
+
[
|
|
633
|
+
[0.911, 0.004, 0.413, -0.021],
|
|
634
|
+
[-0.004, 1.0, -0.001, 0.001],
|
|
635
|
+
[-0.413, -0.001, 0.911, -0.044],
|
|
636
|
+
[0.0, 0.0, 0.0, 1.0],
|
|
637
|
+
]
|
|
638
|
+
)
|
|
639
|
+
|
|
640
|
+
async def wake_up(self) -> None:
|
|
641
|
+
"""Wake up the robot - go to the initial head position and play the wake up emote and sound."""
|
|
642
|
+
await asyncio.sleep(0.1)
|
|
643
|
+
|
|
644
|
+
_, _, magic_distance = distance_between_poses(
|
|
645
|
+
self.get_current_head_pose(), self.INIT_HEAD_POSE
|
|
646
|
+
)
|
|
647
|
+
|
|
648
|
+
await self.goto_target(
|
|
649
|
+
self.INIT_HEAD_POSE,
|
|
650
|
+
antennas=np.array((0.0, 0.0)),
|
|
651
|
+
duration=magic_distance * 20 / 1000, # ms_per_magic_mm = 10
|
|
652
|
+
)
|
|
653
|
+
await asyncio.sleep(0.1)
|
|
654
|
+
|
|
655
|
+
# Toudoum
|
|
656
|
+
self.play_sound("wake_up.wav")
|
|
657
|
+
|
|
658
|
+
# Roll 20° to the left
|
|
659
|
+
pose = self.INIT_HEAD_POSE.copy()
|
|
660
|
+
pose[:3, :3] = R.from_euler("xyz", [20, 0, 0], degrees=True).as_matrix()
|
|
661
|
+
await self.goto_target(pose, duration=0.2)
|
|
662
|
+
|
|
663
|
+
# Go back to the initial position
|
|
664
|
+
await self.goto_target(self.INIT_HEAD_POSE, duration=0.2)
|
|
665
|
+
|
|
666
|
+
async def goto_sleep(self) -> None:
|
|
667
|
+
"""Put the robot to sleep by moving the head and antennas to a predefined sleep position.
|
|
668
|
+
|
|
669
|
+
- If we are already very close to the sleep position, we do nothing.
|
|
670
|
+
- If we are far from the sleep position:
|
|
671
|
+
- If we are far from the initial position, we move there first.
|
|
672
|
+
- If we are close to the initial position, we move directly to the sleep position.
|
|
673
|
+
"""
|
|
674
|
+
# Magic units
|
|
675
|
+
_, _, dist_to_sleep_pose = distance_between_poses(
|
|
676
|
+
self.get_current_head_pose(), self.SLEEP_HEAD_POSE
|
|
677
|
+
)
|
|
678
|
+
_, _, dist_to_init_pose = distance_between_poses(
|
|
679
|
+
self.get_current_head_pose(), self.INIT_HEAD_POSE
|
|
680
|
+
)
|
|
681
|
+
sleep_time = 2.0
|
|
682
|
+
|
|
683
|
+
# Thresholds found empirically.
|
|
684
|
+
if dist_to_sleep_pose > 10:
|
|
685
|
+
if dist_to_init_pose > 30:
|
|
686
|
+
# Move to the initial position
|
|
687
|
+
await self.goto_target(
|
|
688
|
+
self.INIT_HEAD_POSE, antennas=np.array((0.0, 0.0)), duration=1
|
|
689
|
+
)
|
|
690
|
+
await asyncio.sleep(0.2)
|
|
691
|
+
|
|
692
|
+
self.play_sound("go_sleep.wav")
|
|
693
|
+
|
|
694
|
+
# Move to the sleep position
|
|
695
|
+
await self.goto_target(
|
|
696
|
+
self.SLEEP_HEAD_POSE,
|
|
697
|
+
antennas=self.SLEEP_ANTENNAS_JOINT_POSITIONS,
|
|
698
|
+
duration=2,
|
|
699
|
+
)
|
|
700
|
+
else:
|
|
701
|
+
# The sound doesn't play fully if we don't wait enough
|
|
702
|
+
self.play_sound("go_sleep.wav")
|
|
703
|
+
sleep_time += 3
|
|
704
|
+
|
|
705
|
+
self._last_head_pose = self.SLEEP_HEAD_POSE
|
|
706
|
+
await asyncio.sleep(sleep_time)
|
|
707
|
+
|
|
708
|
+
# Motor control modes
|
|
709
|
+
@abstractmethod
|
|
710
|
+
def get_motor_control_mode(self) -> MotorControlMode:
|
|
711
|
+
"""Get the motor control mode."""
|
|
712
|
+
pass
|
|
713
|
+
|
|
714
|
+
@abstractmethod
|
|
715
|
+
def set_motor_control_mode(self, mode: MotorControlMode) -> None:
|
|
716
|
+
"""Set the motor control mode."""
|
|
717
|
+
pass
|
|
718
|
+
|
|
719
|
+
def get_present_passive_joint_positions(self) -> Optional[Dict[str, float]]:
|
|
720
|
+
"""Get the present passive joint positions.
|
|
721
|
+
|
|
722
|
+
Requires the Placo kinematics engine.
|
|
723
|
+
"""
|
|
724
|
+
# This is would be better, and fix mypy issues, but Placo is dynamically imported
|
|
725
|
+
# if not isinstance(self.head_kinematics, PlacoKinematics):
|
|
726
|
+
if self.kinematics_engine != "Placo":
|
|
727
|
+
return None
|
|
728
|
+
return {
|
|
729
|
+
"passive_1_x": self.head_kinematics.get_joint("passive_1_x"), # type: ignore [union-attr]
|
|
730
|
+
"passive_1_y": self.head_kinematics.get_joint("passive_1_y"), # type: ignore [union-attr]
|
|
731
|
+
"passive_1_z": self.head_kinematics.get_joint("passive_1_z"), # type: ignore [union-attr]
|
|
732
|
+
"passive_2_x": self.head_kinematics.get_joint("passive_2_x"), # type: ignore [union-attr]
|
|
733
|
+
"passive_2_y": self.head_kinematics.get_joint("passive_2_y"), # type: ignore [union-attr]
|
|
734
|
+
"passive_2_z": self.head_kinematics.get_joint("passive_2_z"), # type: ignore [union-attr]
|
|
735
|
+
"passive_3_x": self.head_kinematics.get_joint("passive_3_x"), # type: ignore [union-attr]
|
|
736
|
+
"passive_3_y": self.head_kinematics.get_joint("passive_3_y"), # type: ignore [union-attr]
|
|
737
|
+
"passive_3_z": self.head_kinematics.get_joint("passive_3_z"), # type: ignore [union-attr]
|
|
738
|
+
"passive_4_x": self.head_kinematics.get_joint("passive_4_x"), # type: ignore [union-attr]
|
|
739
|
+
"passive_4_y": self.head_kinematics.get_joint("passive_4_y"), # type: ignore [union-attr]
|
|
740
|
+
"passive_4_z": self.head_kinematics.get_joint("passive_4_z"), # type: ignore [union-attr]
|
|
741
|
+
"passive_5_x": self.head_kinematics.get_joint("passive_5_x"), # type: ignore [union-attr]
|
|
742
|
+
"passive_5_y": self.head_kinematics.get_joint("passive_5_y"), # type: ignore [union-attr]
|
|
743
|
+
"passive_5_z": self.head_kinematics.get_joint("passive_5_z"), # type: ignore [union-attr]
|
|
744
|
+
"passive_6_x": self.head_kinematics.get_joint("passive_6_x"), # type: ignore [union-attr]
|
|
745
|
+
"passive_6_y": self.head_kinematics.get_joint("passive_6_y"), # type: ignore [union-attr]
|
|
746
|
+
"passive_6_z": self.head_kinematics.get_joint("passive_6_z"), # type: ignore [union-attr]
|
|
747
|
+
"passive_7_x": self.head_kinematics.get_joint("passive_7_x"), # type: ignore [union-attr]
|
|
748
|
+
"passive_7_y": self.head_kinematics.get_joint("passive_7_y"), # type: ignore [union-attr]
|
|
749
|
+
"passive_7_z": self.head_kinematics.get_joint("passive_7_z"), # type: ignore [union-attr]
|
|
750
|
+
}
|