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,162 @@
|
|
|
1
|
+
"""GStreamer camera backend.
|
|
2
|
+
|
|
3
|
+
This module provides an implementation of the CameraBase class using GStreamer.
|
|
4
|
+
By default the module directly returns JPEG images as output by the camera.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from threading import Thread
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
import numpy as np
|
|
11
|
+
import numpy.typing as npt
|
|
12
|
+
|
|
13
|
+
from reachy_mini.media.camera_constants import CameraResolution
|
|
14
|
+
|
|
15
|
+
from .camera_base import CameraBackend, CameraBase
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
import gi
|
|
19
|
+
except ImportError as e:
|
|
20
|
+
raise ImportError(
|
|
21
|
+
"The 'gi' module is required for GStreamerCamera but could not be imported. \
|
|
22
|
+
Please install the GStreamer backend: pip install .[gstreamer]."
|
|
23
|
+
) from e
|
|
24
|
+
|
|
25
|
+
gi.require_version("Gst", "1.0")
|
|
26
|
+
gi.require_version("GstApp", "1.0")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
from gi.repository import GLib, Gst, GstApp # noqa: E402
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class GStreamerCamera(CameraBase):
|
|
33
|
+
"""Camera implementation using GStreamer."""
|
|
34
|
+
|
|
35
|
+
def __init__(
|
|
36
|
+
self,
|
|
37
|
+
log_level: str = "INFO",
|
|
38
|
+
resolution: CameraResolution = CameraResolution.R1280x720,
|
|
39
|
+
) -> None:
|
|
40
|
+
"""Initialize the GStreamer camera."""
|
|
41
|
+
super().__init__(
|
|
42
|
+
backend=CameraBackend.GSTREAMER, log_level=log_level, resolution=resolution
|
|
43
|
+
)
|
|
44
|
+
Gst.init(None)
|
|
45
|
+
self._loop = GLib.MainLoop()
|
|
46
|
+
self._thread_bus_calls: Optional[Thread] = None
|
|
47
|
+
|
|
48
|
+
self.pipeline = Gst.Pipeline.new("camera_recorder")
|
|
49
|
+
|
|
50
|
+
# note for some applications the jpeg image could be directly used
|
|
51
|
+
self._appsink_video: GstApp = Gst.ElementFactory.make("appsink")
|
|
52
|
+
caps_video = Gst.Caps.from_string(
|
|
53
|
+
f"video/x-raw,format=BGR, width={self.resolution[0]},height={self.resolution[1]},framerate={self.framerate}/1"
|
|
54
|
+
)
|
|
55
|
+
self._appsink_video.set_property("caps", caps_video)
|
|
56
|
+
self._appsink_video.set_property("drop", True) # avoid overflow
|
|
57
|
+
self._appsink_video.set_property("max-buffers", 1) # keep last image only
|
|
58
|
+
self.pipeline.add(self._appsink_video)
|
|
59
|
+
|
|
60
|
+
cam_path = self.get_arducam_video_device()
|
|
61
|
+
if cam_path == "":
|
|
62
|
+
self.logger.warning("Recording pipeline set without camera.")
|
|
63
|
+
self.pipeline.remove(self._appsink_video)
|
|
64
|
+
else:
|
|
65
|
+
camsrc = Gst.ElementFactory.make("v4l2src")
|
|
66
|
+
camsrc.set_property("device", cam_path)
|
|
67
|
+
self.pipeline.add(camsrc)
|
|
68
|
+
queue = Gst.ElementFactory.make("queue")
|
|
69
|
+
self.pipeline.add(queue)
|
|
70
|
+
# use vaapijpegdec or nvjpegdec for hardware acceleration
|
|
71
|
+
jpegdec = Gst.ElementFactory.make("jpegdec")
|
|
72
|
+
self.pipeline.add(jpegdec)
|
|
73
|
+
videoconvert = Gst.ElementFactory.make("videoconvert")
|
|
74
|
+
self.pipeline.add(videoconvert)
|
|
75
|
+
camsrc.link(queue)
|
|
76
|
+
queue.link(jpegdec)
|
|
77
|
+
jpegdec.link(videoconvert)
|
|
78
|
+
videoconvert.link(self._appsink_video)
|
|
79
|
+
|
|
80
|
+
def _on_bus_message(self, bus: Gst.Bus, msg: Gst.Message, loop) -> bool: # type: ignore[no-untyped-def]
|
|
81
|
+
t = msg.type
|
|
82
|
+
if t == Gst.MessageType.EOS:
|
|
83
|
+
self.logger.warning("End-of-stream")
|
|
84
|
+
return False
|
|
85
|
+
|
|
86
|
+
elif t == Gst.MessageType.ERROR:
|
|
87
|
+
err, debug = msg.parse_error()
|
|
88
|
+
self.logger.error(f"Error: {err} {debug}")
|
|
89
|
+
return False
|
|
90
|
+
|
|
91
|
+
return True
|
|
92
|
+
|
|
93
|
+
def _handle_bus_calls(self) -> None:
|
|
94
|
+
self.logger.debug("starting bus message loop")
|
|
95
|
+
bus = self.pipeline.get_bus()
|
|
96
|
+
bus.add_watch(GLib.PRIORITY_DEFAULT, self._on_bus_message, self._loop)
|
|
97
|
+
self._loop.run()
|
|
98
|
+
bus.remove_watch()
|
|
99
|
+
self.logger.debug("bus message loop stopped")
|
|
100
|
+
|
|
101
|
+
def open(self) -> None:
|
|
102
|
+
"""Open the camera using GStreamer."""
|
|
103
|
+
self.pipeline.set_state(Gst.State.PLAYING)
|
|
104
|
+
self._thread_bus_calls = Thread(target=self._handle_bus_calls, daemon=True)
|
|
105
|
+
self._thread_bus_calls.start()
|
|
106
|
+
|
|
107
|
+
def _get_sample(self, appsink: GstApp.AppSink) -> Optional[bytes]:
|
|
108
|
+
sample = appsink.try_pull_sample(20_000_000)
|
|
109
|
+
if sample is None:
|
|
110
|
+
return None
|
|
111
|
+
data = None
|
|
112
|
+
if isinstance(sample, Gst.Sample):
|
|
113
|
+
buf = sample.get_buffer()
|
|
114
|
+
if buf is None:
|
|
115
|
+
self.logger.warning("Buffer is None")
|
|
116
|
+
|
|
117
|
+
data = buf.extract_dup(0, buf.get_size())
|
|
118
|
+
return data
|
|
119
|
+
|
|
120
|
+
def read(self) -> Optional[npt.NDArray[np.uint8]]:
|
|
121
|
+
"""Read a frame from the camera. Returns the frame or None if error.
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
Optional[npt.NDArray[np.uint8]]: The captured BGR frame as a NumPy array, or None if error.
|
|
125
|
+
|
|
126
|
+
"""
|
|
127
|
+
data = self._get_sample(self._appsink_video)
|
|
128
|
+
if data is None:
|
|
129
|
+
return None
|
|
130
|
+
|
|
131
|
+
arr = np.frombuffer(data, dtype=np.uint8).reshape(
|
|
132
|
+
(self.resolution[1], self.resolution[0], 3)
|
|
133
|
+
)
|
|
134
|
+
return arr
|
|
135
|
+
|
|
136
|
+
def close(self) -> None:
|
|
137
|
+
"""Release the camera resource."""
|
|
138
|
+
self._loop.quit()
|
|
139
|
+
self.pipeline.set_state(Gst.State.NULL)
|
|
140
|
+
|
|
141
|
+
def get_arducam_video_device(self) -> str:
|
|
142
|
+
"""Use Gst.DeviceMonitor to find the unix camera path /dev/videoX of the Arducam_12MP webcam.
|
|
143
|
+
|
|
144
|
+
Returns the device path (e.g., '/dev/video2'), or '' if not found.
|
|
145
|
+
"""
|
|
146
|
+
monitor = Gst.DeviceMonitor()
|
|
147
|
+
monitor.add_filter("Video/Source")
|
|
148
|
+
monitor.start()
|
|
149
|
+
|
|
150
|
+
devices = monitor.get_devices()
|
|
151
|
+
for device in devices:
|
|
152
|
+
name = device.get_display_name()
|
|
153
|
+
device_props = device.get_properties()
|
|
154
|
+
if name and "Arducam_12MP" in name:
|
|
155
|
+
if device_props and device_props.has_field("api.v4l2.path"):
|
|
156
|
+
device_path = device_props.get_string("api.v4l2.path")
|
|
157
|
+
self.logger.debug(f"Found Arducam_12MP at {device_path}")
|
|
158
|
+
monitor.stop()
|
|
159
|
+
return str(device_path)
|
|
160
|
+
monitor.stop()
|
|
161
|
+
self.logger.warning("Arducam_12MP webcam not found.")
|
|
162
|
+
return ""
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""OpenCv camera backend.
|
|
2
|
+
|
|
3
|
+
This module provides an implementation of the CameraBase class using OpenCV.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
import cv2
|
|
9
|
+
import numpy as np
|
|
10
|
+
import numpy.typing as npt
|
|
11
|
+
|
|
12
|
+
from reachy_mini.media.camera_constants import CameraResolution
|
|
13
|
+
from reachy_mini.media.camera_utils import find_camera
|
|
14
|
+
|
|
15
|
+
from .camera_base import CameraBackend, CameraBase
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class OpenCVCamera(CameraBase):
|
|
19
|
+
"""Camera implementation using OpenCV."""
|
|
20
|
+
|
|
21
|
+
def __init__(
|
|
22
|
+
self,
|
|
23
|
+
log_level: str = "INFO",
|
|
24
|
+
resolution: CameraResolution = CameraResolution.R1280x720,
|
|
25
|
+
) -> None:
|
|
26
|
+
"""Initialize the OpenCV camera."""
|
|
27
|
+
super().__init__(
|
|
28
|
+
backend=CameraBackend.OPENCV, log_level=log_level, resolution=resolution
|
|
29
|
+
)
|
|
30
|
+
self.cap: Optional[cv2.VideoCapture] = None
|
|
31
|
+
|
|
32
|
+
def open(self, udp_camera: Optional[str] = None) -> None:
|
|
33
|
+
"""Open the camera using OpenCV VideoCapture."""
|
|
34
|
+
if udp_camera:
|
|
35
|
+
self.cap = cv2.VideoCapture(udp_camera)
|
|
36
|
+
else:
|
|
37
|
+
self.cap = find_camera()
|
|
38
|
+
if self.cap is None:
|
|
39
|
+
raise RuntimeError("Camera not found")
|
|
40
|
+
self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, self.resolution[0])
|
|
41
|
+
self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, self.resolution[1])
|
|
42
|
+
|
|
43
|
+
if not self.cap.isOpened():
|
|
44
|
+
raise RuntimeError("Failed to open camera")
|
|
45
|
+
|
|
46
|
+
def read(self) -> Optional[npt.NDArray[np.uint8]]:
|
|
47
|
+
"""Read a frame from the camera. Returns the frame or None if error."""
|
|
48
|
+
if self.cap is None:
|
|
49
|
+
raise RuntimeError("Camera is not opened.")
|
|
50
|
+
|
|
51
|
+
ret, frame = self.cap.read()
|
|
52
|
+
if not ret:
|
|
53
|
+
return None
|
|
54
|
+
|
|
55
|
+
return np.asarray(frame, dtype=np.uint8, copy=False)
|
|
56
|
+
|
|
57
|
+
def close(self) -> None:
|
|
58
|
+
"""Release the camera resource."""
|
|
59
|
+
if self.cap is not None:
|
|
60
|
+
self.cap.release()
|
|
61
|
+
self.cap = None
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""Camera utility for Reachy Mini."""
|
|
2
|
+
|
|
3
|
+
import platform
|
|
4
|
+
|
|
5
|
+
import cv2
|
|
6
|
+
from cv2_enumerate_cameras import enumerate_cameras
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def find_camera(
|
|
10
|
+
vid: int = 0x0C45,
|
|
11
|
+
pid: int = 0x636D,
|
|
12
|
+
apiPreference: int = cv2.CAP_ANY,
|
|
13
|
+
) -> cv2.VideoCapture | None:
|
|
14
|
+
"""Find and return a camera with the specified VID and PID.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
vid (int): Vendor ID of the camera. Default is 0x0C45 (Arducam).
|
|
18
|
+
pid (int): Product ID of the camera. Default is 0x636D (Arducam).
|
|
19
|
+
apiPreference (int): Preferred API backend for the camera. Default is cv2.CAP_ANY.
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
cv2.VideoCapture | None: A VideoCapture object if the camera is found and opened successfully, otherwise None.
|
|
23
|
+
|
|
24
|
+
"""
|
|
25
|
+
if platform.system() == "Linux":
|
|
26
|
+
apiPreference = cv2.CAP_V4L2
|
|
27
|
+
|
|
28
|
+
selected_cap = None
|
|
29
|
+
for c in enumerate_cameras(apiPreference):
|
|
30
|
+
if c.vid == vid and c.pid == pid:
|
|
31
|
+
# the Arducam camera creates two /dev/videoX devices
|
|
32
|
+
# that enumerate_cameras cannot differentiate
|
|
33
|
+
try:
|
|
34
|
+
cap = cv2.VideoCapture(c.index, c.backend)
|
|
35
|
+
if cap.isOpened():
|
|
36
|
+
selected_cap = cap
|
|
37
|
+
except Exception as e:
|
|
38
|
+
print(f"Error opening camera {c.index}: {e}")
|
|
39
|
+
return selected_cap
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
if __name__ == "__main__":
|
|
43
|
+
from reachy_mini.media.camera_constants import CameraResolution
|
|
44
|
+
|
|
45
|
+
cam = find_camera()
|
|
46
|
+
|
|
47
|
+
if cam is None:
|
|
48
|
+
print("Camera not found")
|
|
49
|
+
else:
|
|
50
|
+
cam.set(cv2.CAP_PROP_FRAME_WIDTH, CameraResolution.R1280x720.value[0])
|
|
51
|
+
cam.set(cv2.CAP_PROP_FRAME_HEIGHT, CameraResolution.R1280x720.value[1])
|
|
52
|
+
|
|
53
|
+
while True:
|
|
54
|
+
ret, frame = cam.read()
|
|
55
|
+
if not ret:
|
|
56
|
+
print("Failed to grab frame")
|
|
57
|
+
break
|
|
58
|
+
cv2.imshow("Camera Feed", frame)
|
|
59
|
+
if cv2.waitKey(1) & 0xFF == ord("q"):
|
|
60
|
+
break
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"""Media Manager.
|
|
2
|
+
|
|
3
|
+
Provides camera and audio access based on the selected backedn
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import logging
|
|
7
|
+
from enum import Enum
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
import numpy as np
|
|
11
|
+
import numpy.typing as npt
|
|
12
|
+
|
|
13
|
+
from reachy_mini.media.audio_base import AudioBase
|
|
14
|
+
from reachy_mini.media.camera_base import CameraBase
|
|
15
|
+
from reachy_mini.media.camera_constants import CameraResolution
|
|
16
|
+
|
|
17
|
+
# actual backends are dynamically imported
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class MediaBackend(Enum):
|
|
21
|
+
"""Media backends."""
|
|
22
|
+
|
|
23
|
+
NO_MEDIA = "no_media"
|
|
24
|
+
DEFAULT = "default"
|
|
25
|
+
DEFAULT_NO_VIDEO = "default_no_video"
|
|
26
|
+
GSTREAMER = "gstreamer"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class MediaManager:
|
|
30
|
+
"""Abstract class for opening and managing audio devices."""
|
|
31
|
+
|
|
32
|
+
def __init__(
|
|
33
|
+
self,
|
|
34
|
+
backend: MediaBackend = MediaBackend.DEFAULT,
|
|
35
|
+
log_level: str = "INFO",
|
|
36
|
+
use_sim: bool = False,
|
|
37
|
+
resolution: CameraResolution = CameraResolution.R1280x720,
|
|
38
|
+
) -> None:
|
|
39
|
+
"""Initialize the audio device."""
|
|
40
|
+
self.logger = logging.getLogger(__name__)
|
|
41
|
+
self.logger.setLevel(log_level)
|
|
42
|
+
self.backend = backend
|
|
43
|
+
self.camera: Optional[CameraBase] = None
|
|
44
|
+
if (
|
|
45
|
+
not backend == MediaBackend.DEFAULT_NO_VIDEO
|
|
46
|
+
and not backend == MediaBackend.NO_MEDIA
|
|
47
|
+
):
|
|
48
|
+
self._init_camera(use_sim, log_level, resolution)
|
|
49
|
+
self.audio: Optional[AudioBase] = None
|
|
50
|
+
if not backend == MediaBackend.NO_MEDIA:
|
|
51
|
+
self._init_audio(log_level)
|
|
52
|
+
|
|
53
|
+
def __del__(self) -> None:
|
|
54
|
+
"""Destructor to ensure resources are released."""
|
|
55
|
+
if self.camera is not None:
|
|
56
|
+
self.camera.close()
|
|
57
|
+
if self.audio is not None:
|
|
58
|
+
self.audio.stop_recording()
|
|
59
|
+
self.audio.stop_playing()
|
|
60
|
+
|
|
61
|
+
def _init_camera(
|
|
62
|
+
self,
|
|
63
|
+
use_sim: bool,
|
|
64
|
+
log_level: str,
|
|
65
|
+
resolution: CameraResolution,
|
|
66
|
+
) -> None:
|
|
67
|
+
"""Initialize the camera."""
|
|
68
|
+
self.logger.debug("Initializing camera...")
|
|
69
|
+
if self.backend == MediaBackend.DEFAULT:
|
|
70
|
+
self.logger.info("Using OpenCV camera backend.")
|
|
71
|
+
from reachy_mini.media.camera_opencv import OpenCVCamera
|
|
72
|
+
|
|
73
|
+
self.camera = OpenCVCamera(log_level=log_level, resolution=resolution)
|
|
74
|
+
if use_sim:
|
|
75
|
+
self.camera.open(udp_camera="udp://@127.0.0.1:5005")
|
|
76
|
+
else:
|
|
77
|
+
self.camera.open()
|
|
78
|
+
elif self.backend == MediaBackend.GSTREAMER:
|
|
79
|
+
self.logger.info("Using GStreamer camera backend.")
|
|
80
|
+
from reachy_mini.media.camera_gstreamer import GStreamerCamera
|
|
81
|
+
|
|
82
|
+
self.camera = GStreamerCamera(log_level=log_level, resolution=resolution)
|
|
83
|
+
self.camera.open()
|
|
84
|
+
# Todo: use simulation with gstreamer?
|
|
85
|
+
|
|
86
|
+
else:
|
|
87
|
+
raise NotImplementedError(f"Camera backend {self.backend} not implemented.")
|
|
88
|
+
|
|
89
|
+
def get_frame(self) -> Optional[npt.NDArray[np.uint8]]:
|
|
90
|
+
"""Get a frame from the camera.
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
Optional[npt.NDArray[np.uint8]]: The captured BGR frame, or None if the camera is not available.
|
|
94
|
+
|
|
95
|
+
"""
|
|
96
|
+
if self.camera is None:
|
|
97
|
+
self.logger.warning("Camera is not initialized.")
|
|
98
|
+
return None
|
|
99
|
+
return self.camera.read()
|
|
100
|
+
|
|
101
|
+
def _init_audio(self, log_level: str) -> None:
|
|
102
|
+
"""Initialize the audio system."""
|
|
103
|
+
self.logger.debug("Initializing audio...")
|
|
104
|
+
if (
|
|
105
|
+
self.backend == MediaBackend.DEFAULT
|
|
106
|
+
or self.backend == MediaBackend.DEFAULT_NO_VIDEO
|
|
107
|
+
):
|
|
108
|
+
self.logger.info("Using SoundDevice audio backend.")
|
|
109
|
+
from reachy_mini.media.audio_sounddevice import SoundDeviceAudio
|
|
110
|
+
|
|
111
|
+
self.audio = SoundDeviceAudio(log_level=log_level)
|
|
112
|
+
elif self.backend == MediaBackend.GSTREAMER:
|
|
113
|
+
self.logger.info("Using GStreamer audio backend.")
|
|
114
|
+
from reachy_mini.media.audio_gstreamer import GStreamerAudio
|
|
115
|
+
|
|
116
|
+
self.audio = GStreamerAudio(log_level=log_level)
|
|
117
|
+
else:
|
|
118
|
+
raise NotImplementedError(f"Audio backend {self.backend} not implemented.")
|
|
119
|
+
|
|
120
|
+
def play_sound(self, sound_file: str) -> None:
|
|
121
|
+
"""Play a sound file.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
sound_file (str): Path to the sound file to play.
|
|
125
|
+
|
|
126
|
+
"""
|
|
127
|
+
if self.audio is None:
|
|
128
|
+
self.logger.warning("Audio system is not initialized.")
|
|
129
|
+
return
|
|
130
|
+
self.audio.play_sound(sound_file)
|
|
131
|
+
|
|
132
|
+
def start_recording(self) -> None:
|
|
133
|
+
"""Start recording audio."""
|
|
134
|
+
if self.audio is None:
|
|
135
|
+
self.logger.warning("Audio system is not initialized.")
|
|
136
|
+
return
|
|
137
|
+
self.audio.start_recording()
|
|
138
|
+
|
|
139
|
+
def get_audio_sample(self) -> Optional[bytes | npt.NDArray[np.float32]]:
|
|
140
|
+
"""Get an audio sample from the audio device.
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
Optional[np.ndarray]: The recorded audio sample, or None if no data is available.
|
|
144
|
+
|
|
145
|
+
"""
|
|
146
|
+
if self.audio is None:
|
|
147
|
+
self.logger.warning("Audio system is not initialized.")
|
|
148
|
+
return None
|
|
149
|
+
return self.audio.get_audio_sample()
|
|
150
|
+
|
|
151
|
+
def get_audio_samplerate(self) -> int:
|
|
152
|
+
"""Get the samplerate of the audio device.
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
int: The samplerate of the audio device.
|
|
156
|
+
|
|
157
|
+
"""
|
|
158
|
+
if self.audio is None:
|
|
159
|
+
self.logger.warning("Audio system is not initialized.")
|
|
160
|
+
return -1
|
|
161
|
+
return self.audio.SAMPLE_RATE
|
|
162
|
+
|
|
163
|
+
def stop_recording(self) -> None:
|
|
164
|
+
"""Stop recording audio."""
|
|
165
|
+
if self.audio is None:
|
|
166
|
+
self.logger.warning("Audio system is not initialized.")
|
|
167
|
+
return
|
|
168
|
+
self.audio.stop_recording()
|
|
169
|
+
|
|
170
|
+
def start_playing(self) -> None:
|
|
171
|
+
"""Start playing audio."""
|
|
172
|
+
if self.audio is None:
|
|
173
|
+
self.logger.warning("Audio system is not initialized.")
|
|
174
|
+
return
|
|
175
|
+
self.audio.start_playing()
|
|
176
|
+
|
|
177
|
+
def push_audio_sample(self, data: npt.NDArray[np.float32]) -> None:
|
|
178
|
+
"""Push audio data to the output device.
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
data (npt.NDArray[np.float32]): The audio data to push to the output device (mono format).
|
|
182
|
+
|
|
183
|
+
"""
|
|
184
|
+
if self.audio is None:
|
|
185
|
+
self.logger.warning("Audio system is not initialized.")
|
|
186
|
+
return
|
|
187
|
+
self.audio.push_audio_sample(data)
|
|
188
|
+
|
|
189
|
+
def stop_playing(self) -> None:
|
|
190
|
+
"""Stop playing audio."""
|
|
191
|
+
if self.audio is None:
|
|
192
|
+
self.logger.warning("Audio system is not initialized.")
|
|
193
|
+
return
|
|
194
|
+
self.audio.stop_playing()
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""A goto move to a target head pose and/or antennas position."""
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import numpy.typing as npt
|
|
5
|
+
|
|
6
|
+
from reachy_mini.utils.interpolation import (
|
|
7
|
+
InterpolationTechnique,
|
|
8
|
+
linear_pose_interpolation,
|
|
9
|
+
time_trajectory,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
from .move import Move
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class GotoMove(Move):
|
|
16
|
+
"""A goto move to a target head pose and/or antennas position."""
|
|
17
|
+
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
start_head_pose: npt.NDArray[np.float64],
|
|
21
|
+
target_head_pose: npt.NDArray[np.float64] | None,
|
|
22
|
+
start_antennas: npt.NDArray[np.float64],
|
|
23
|
+
target_antennas: npt.NDArray[np.float64] | None,
|
|
24
|
+
start_body_yaw: float,
|
|
25
|
+
target_body_yaw: float | None,
|
|
26
|
+
duration: float,
|
|
27
|
+
method: InterpolationTechnique,
|
|
28
|
+
):
|
|
29
|
+
"""Set up the goto move."""
|
|
30
|
+
self.start_head_pose = start_head_pose
|
|
31
|
+
self.target_head_pose = (
|
|
32
|
+
target_head_pose if target_head_pose is not None else start_head_pose
|
|
33
|
+
)
|
|
34
|
+
self.start_antennas = start_antennas
|
|
35
|
+
self.target_antennas = (
|
|
36
|
+
target_antennas if target_antennas is not None else start_antennas
|
|
37
|
+
)
|
|
38
|
+
self.start_body_yaw = start_body_yaw
|
|
39
|
+
self.target_body_yaw = (
|
|
40
|
+
target_body_yaw if target_body_yaw is not None else start_body_yaw
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
self._duration = duration
|
|
44
|
+
self.method = method
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def duration(self) -> float:
|
|
48
|
+
"""Duration of the goto in seconds."""
|
|
49
|
+
return self._duration
|
|
50
|
+
|
|
51
|
+
def evaluate(
|
|
52
|
+
self, t: float
|
|
53
|
+
) -> tuple[
|
|
54
|
+
npt.NDArray[np.float64] | None, npt.NDArray[np.float64] | None, float | None
|
|
55
|
+
]:
|
|
56
|
+
"""Evaluate the goto at time t."""
|
|
57
|
+
interp_time = time_trajectory(t / self.duration, method=self.method)
|
|
58
|
+
|
|
59
|
+
interp_head_pose = linear_pose_interpolation(
|
|
60
|
+
self.start_head_pose, self.target_head_pose, interp_time
|
|
61
|
+
)
|
|
62
|
+
interp_antennas_joint = (
|
|
63
|
+
self.start_antennas
|
|
64
|
+
+ (self.target_antennas - self.start_antennas) * interp_time
|
|
65
|
+
)
|
|
66
|
+
interp_body_yaw_joint = (
|
|
67
|
+
self.start_body_yaw
|
|
68
|
+
+ (self.target_body_yaw - self.start_body_yaw) * interp_time
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
return interp_head_pose, interp_antennas_joint, interp_body_yaw_joint
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Module for defining motion moves on the ReachyMini robot."""
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
import numpy.typing as npt
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Move(ABC):
|
|
10
|
+
"""Abstract base class for defining a move on the ReachyMini robot."""
|
|
11
|
+
|
|
12
|
+
@property
|
|
13
|
+
@abstractmethod
|
|
14
|
+
def duration(self) -> float:
|
|
15
|
+
"""Duration of the move in seconds."""
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
@abstractmethod
|
|
19
|
+
def evaluate(
|
|
20
|
+
self,
|
|
21
|
+
t: float,
|
|
22
|
+
) -> tuple[
|
|
23
|
+
npt.NDArray[np.float64] | None, npt.NDArray[np.float64] | None, float | None
|
|
24
|
+
]:
|
|
25
|
+
"""Evaluate the move at time t, typically called at a high-frequency (eg. 100Hz).
|
|
26
|
+
|
|
27
|
+
Arguments:
|
|
28
|
+
t: The time at which to evaluate the move (in seconds). It will always be between 0 and duration.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
head: The head position (4x4 homogeneous matrix).
|
|
32
|
+
antennas: The antennas positions (rad).
|
|
33
|
+
body_yaw: The body yaw angle (rad).
|
|
34
|
+
|
|
35
|
+
"""
|
|
36
|
+
pass
|