reachy-mini 1.2.5rc1__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.
- reachy_mini/__init__.py +4 -0
- reachy_mini/apps/__init__.py +25 -0
- reachy_mini/apps/app.py +258 -0
- reachy_mini/apps/assistant.py +787 -0
- reachy_mini/apps/manager.py +312 -0
- reachy_mini/apps/sources/__init__.py +4 -0
- reachy_mini/apps/sources/hf_space.py +106 -0
- reachy_mini/apps/sources/local_common_venv.py +567 -0
- reachy_mini/apps/templates/README.md.j2 +12 -0
- reachy_mini/apps/templates/gitignore.j2 +3 -0
- reachy_mini/apps/templates/index.html.j2 +40 -0
- reachy_mini/apps/templates/main.py.j2 +74 -0
- reachy_mini/apps/templates/pyproject.toml.j2 +28 -0
- reachy_mini/apps/templates/static/index.html.j2 +27 -0
- reachy_mini/apps/templates/static/main.js.j2 +47 -0
- reachy_mini/apps/templates/static/style.css.j2 +25 -0
- reachy_mini/apps/templates/style.css.j2 +411 -0
- reachy_mini/apps/utils.py +30 -0
- reachy_mini/assets/config/hardware_config.yaml +164 -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/firmware/CHANGELOG.md +15 -0
- reachy_mini/assets/firmware/reachymini_ua_io16_lin_v2.1.2.bin +0 -0
- reachy_mini/assets/firmware/reachymini_ua_io16_lin_v2.1.3.bin +0 -0
- reachy_mini/assets/firmware/update.sh +9 -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/css/app.css +1433 -0
- reachy_mini/daemon/app/dashboard/static/fonts/Archivo-Italic-VariableFont_wdth,wght.ttf +0 -0
- reachy_mini/daemon/app/dashboard/static/fonts/Archivo-VariableFont_wdth,wght.ttf +0 -0
- reachy_mini/daemon/app/dashboard/static/fonts/Asap-Italic-VariableFont_wdth,wght.ttf +0 -0
- reachy_mini/daemon/app/dashboard/static/fonts/Asap-VariableFont_wdth,wght.ttf +0 -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 +323 -0
- reachy_mini/daemon/app/dashboard/static/js/appstore.js +167 -0
- reachy_mini/daemon/app/dashboard/static/js/daemon.js +169 -0
- reachy_mini/daemon/app/dashboard/static/js/health_check.js +9 -0
- reachy_mini/daemon/app/dashboard/static/js/move_player.js +132 -0
- reachy_mini/daemon/app/dashboard/static/js/notification.js +41 -0
- reachy_mini/daemon/app/dashboard/static/js/update.js +132 -0
- reachy_mini/daemon/app/dashboard/static/js/volume_control.js +252 -0
- reachy_mini/daemon/app/dashboard/static/js/wifi.js +176 -0
- reachy_mini/daemon/app/dashboard/tailwindcss/README.md +15 -0
- reachy_mini/daemon/app/dashboard/tailwindcss/package-lock.json +1127 -0
- reachy_mini/daemon/app/dashboard/tailwindcss/package.json +6 -0
- reachy_mini/daemon/app/dashboard/tailwindcss/pnpm-lock.yaml +608 -0
- reachy_mini/daemon/app/dashboard/tailwindcss/postcss.config.js +6 -0
- reachy_mini/daemon/app/dashboard/tailwindcss/styles/app.css +185 -0
- reachy_mini/daemon/app/dashboard/tailwindcss/tailwind.config.js +11 -0
- reachy_mini/daemon/app/dashboard/templates/base.html +21 -0
- reachy_mini/daemon/app/dashboard/templates/index.html +20 -0
- reachy_mini/daemon/app/dashboard/templates/sections/apps.html +8 -0
- reachy_mini/daemon/app/dashboard/templates/sections/appstore.html +35 -0
- reachy_mini/daemon/app/dashboard/templates/sections/daemon.html +45 -0
- reachy_mini/daemon/app/dashboard/templates/sections/move_player.html +121 -0
- reachy_mini/daemon/app/dashboard/templates/sections/notification.html +19 -0
- reachy_mini/daemon/app/dashboard/templates/sections/update.html +54 -0
- reachy_mini/daemon/app/dashboard/templates/sections/wifi.html +46 -0
- reachy_mini/daemon/app/dashboard/templates/settings.html +14 -0
- reachy_mini/daemon/app/dependencies.py +41 -0
- reachy_mini/daemon/app/main.py +469 -0
- reachy_mini/daemon/app/models.py +149 -0
- reachy_mini/daemon/app/routers/apps.py +114 -0
- reachy_mini/daemon/app/routers/daemon.py +85 -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 +265 -0
- reachy_mini/daemon/app/routers/state.py +146 -0
- reachy_mini/daemon/app/routers/update.py +86 -0
- reachy_mini/daemon/app/routers/volume.py +423 -0
- reachy_mini/daemon/app/routers/wifi_config.py +219 -0
- reachy_mini/daemon/app/services/__init__.py +1 -0
- reachy_mini/daemon/app/services/bluetooth/bluetooth_service.py +796 -0
- reachy_mini/daemon/app/services/bluetooth/commands/HOTSPOT.sh +7 -0
- reachy_mini/daemon/app/services/bluetooth/commands/RESTART_DAEMON.sh +4 -0
- reachy_mini/daemon/app/services/bluetooth/commands/SOFTWARE_RESET.sh +7 -0
- reachy_mini/daemon/app/services/bluetooth/install_service_bluetooth.sh +39 -0
- reachy_mini/daemon/app/services/gpio_shutdown/__init__.py +1 -0
- reachy_mini/daemon/app/services/gpio_shutdown/install_service.sh +33 -0
- reachy_mini/daemon/app/services/gpio_shutdown/launcher.sh +3 -0
- reachy_mini/daemon/app/services/gpio_shutdown/shutdown_monitor.py +28 -0
- reachy_mini/daemon/app/services/wireless/generate_asoundrc.sh +70 -0
- reachy_mini/daemon/app/services/wireless/install_service.sh +33 -0
- reachy_mini/daemon/app/services/wireless/launcher.sh +5 -0
- reachy_mini/daemon/backend/__init__.py +1 -0
- reachy_mini/daemon/backend/abstract.py +815 -0
- reachy_mini/daemon/backend/mujoco/__init__.py +36 -0
- reachy_mini/daemon/backend/mujoco/backend.py +395 -0
- reachy_mini/daemon/backend/mujoco/utils.py +59 -0
- reachy_mini/daemon/backend/mujoco/video_udp.py +57 -0
- reachy_mini/daemon/backend/robot/__init__.py +8 -0
- reachy_mini/daemon/backend/robot/backend.py +597 -0
- reachy_mini/daemon/daemon.py +651 -0
- reachy_mini/daemon/utils.py +116 -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/collision/README.m +1 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_back_0.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_back_1.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_back_2.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_back_3.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_front_0.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_front_1.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_front_2.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/head_one_3dprint_collider_0.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_back_0.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_back_1.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_back_2.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_back_3.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_front_0.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_front_1.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_front_2.stl +0 -0
- reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/head_one_3dprint_collider_0.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 +642 -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 +132 -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/collision/README.m +1 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_back_0.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_back_1.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_back_2.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_back_3.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_front_0.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_front_1.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_front_2.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/head_one_3dprint_collider_0.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_back_0.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_back_1.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_back_2.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_back_3.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_front_0.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_front_1.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_front_2.stl +0 -0
- reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/head_one_3dprint_collider_0.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/descriptions/reachy_mini/urdf/robot_simple_collision.urdf +2399 -0
- reachy_mini/io/__init__.py +15 -0
- reachy_mini/io/abstract.py +70 -0
- reachy_mini/io/audio_ws.py +242 -0
- reachy_mini/io/protocol.py +44 -0
- reachy_mini/io/video_ws.py +135 -0
- reachy_mini/io/ws_controller.py +120 -0
- reachy_mini/io/zenoh_client.py +273 -0
- reachy_mini/io/zenoh_server.py +230 -0
- reachy_mini/kinematics/__init__.py +68 -0
- reachy_mini/kinematics/analytical_kinematics.py +151 -0
- reachy_mini/kinematics/nn_kinematics.py +109 -0
- reachy_mini/kinematics/placo_kinematics.py +656 -0
- reachy_mini/media/__init__.py +1 -0
- reachy_mini/media/audio_base.py +111 -0
- reachy_mini/media/audio_control_utils.py +455 -0
- reachy_mini/media/audio_gstreamer.py +272 -0
- reachy_mini/media/audio_sounddevice.py +321 -0
- reachy_mini/media/audio_utils.py +114 -0
- reachy_mini/media/camera_base.py +100 -0
- reachy_mini/media/camera_constants.py +152 -0
- reachy_mini/media/camera_gstreamer.py +231 -0
- reachy_mini/media/camera_opencv.py +89 -0
- reachy_mini/media/camera_utils.py +111 -0
- reachy_mini/media/media_manager.py +281 -0
- reachy_mini/media/webrtc_client_gstreamer.py +288 -0
- reachy_mini/media/webrtc_daemon.py +334 -0
- reachy_mini/motion/__init__.py +4 -0
- reachy_mini/motion/goto.py +71 -0
- reachy_mini/motion/move.py +43 -0
- reachy_mini/motion/recorded_move.py +146 -0
- reachy_mini/reachy_mini.py +753 -0
- reachy_mini/tools/reflash_motors.py +116 -0
- reachy_mini/tools/setup_motor.py +422 -0
- reachy_mini/tools/setup_motor_rpi.py +108 -0
- reachy_mini/utils/__init__.py +46 -0
- reachy_mini/utils/constants.py +9 -0
- reachy_mini/utils/hardware_config/__init__.py +1 -0
- reachy_mini/utils/hardware_config/parser.py +65 -0
- reachy_mini/utils/interpolation.py +227 -0
- reachy_mini/utils/parse_urdf_for_kinematics.py +110 -0
- reachy_mini/utils/rerun.py +320 -0
- reachy_mini/utils/wireless_version/__init__.py +1 -0
- reachy_mini/utils/wireless_version/startup_check.py +144 -0
- reachy_mini/utils/wireless_version/update.py +20 -0
- reachy_mini/utils/wireless_version/update_available.py +61 -0
- reachy_mini/utils/wireless_version/utils.py +39 -0
- reachy_mini-1.2.5rc1.dist-info/METADATA +161 -0
- reachy_mini-1.2.5rc1.dist-info/RECORD +479 -0
- reachy_mini-1.2.5rc1.dist-info/WHEEL +5 -0
- reachy_mini-1.2.5rc1.dist-info/entry_points.txt +4 -0
- reachy_mini-1.2.5rc1.dist-info/licenses/LICENSE +201 -0
- reachy_mini-1.2.5rc1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,567 @@
|
|
|
1
|
+
"""Utilities for local common venv apps source."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import logging
|
|
5
|
+
import platform
|
|
6
|
+
import re
|
|
7
|
+
import shutil
|
|
8
|
+
import sys
|
|
9
|
+
from importlib.metadata import entry_points
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
from huggingface_hub import snapshot_download
|
|
13
|
+
|
|
14
|
+
from .. import AppInfo, SourceKind
|
|
15
|
+
from ..utils import running_command
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _check_uv_available() -> bool:
|
|
19
|
+
"""Check if uv is available on the system."""
|
|
20
|
+
return shutil.which("uv") is not None
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _is_windows() -> bool:
|
|
24
|
+
"""Check if the current platform is Windows."""
|
|
25
|
+
return platform.system() == "Windows"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _should_use_separate_venvs(
|
|
29
|
+
wireless_version: bool = False, desktop_app_daemon: bool = False
|
|
30
|
+
) -> bool:
|
|
31
|
+
"""Determine if we should use separate venvs based on version flags."""
|
|
32
|
+
# Use separate venvs for desktop (one per app) and wireless (shared apps venv)
|
|
33
|
+
return desktop_app_daemon or wireless_version
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _get_venv_parent_dir() -> Path:
|
|
37
|
+
"""Get the parent directory of the current venv (OS-agnostic)."""
|
|
38
|
+
# sys.executable is typically: /path/to/venv/bin/python (Linux/Mac)
|
|
39
|
+
# or: C:\path\to\venv\Scripts\python.exe (Windows)
|
|
40
|
+
executable = Path(sys.executable)
|
|
41
|
+
|
|
42
|
+
# Determine expected subdirectory based on platform
|
|
43
|
+
expected_subdir = "Scripts" if _is_windows() else "bin"
|
|
44
|
+
|
|
45
|
+
# Go up from bin/python or Scripts/python.exe to venv dir, then to parent
|
|
46
|
+
if executable.parent.name == expected_subdir:
|
|
47
|
+
venv_dir = executable.parent.parent
|
|
48
|
+
return venv_dir.parent
|
|
49
|
+
|
|
50
|
+
# Fallback: assume we're already in the venv root
|
|
51
|
+
return executable.parent.parent
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _get_app_venv_path(
|
|
55
|
+
app_name: str,
|
|
56
|
+
wireless_version: bool = False,
|
|
57
|
+
desktop_app_daemon: bool = False,
|
|
58
|
+
) -> Path:
|
|
59
|
+
"""Get the venv path for a given app (sibling to current venv).
|
|
60
|
+
|
|
61
|
+
On wireless: returns a shared 'apps_venv' for all apps
|
|
62
|
+
On desktop: returns a separate venv per app '{app_name}_venv'
|
|
63
|
+
"""
|
|
64
|
+
parent_dir = _get_venv_parent_dir()
|
|
65
|
+
if wireless_version and not desktop_app_daemon:
|
|
66
|
+
# Wireless: shared venv for all apps
|
|
67
|
+
return parent_dir / "apps_venv"
|
|
68
|
+
else:
|
|
69
|
+
# Desktop: separate venv per app
|
|
70
|
+
return parent_dir / f"{app_name}_venv"
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _get_app_python(
|
|
74
|
+
app_name: str,
|
|
75
|
+
wireless_version: bool = False,
|
|
76
|
+
desktop_app_daemon: bool = False,
|
|
77
|
+
) -> Path:
|
|
78
|
+
"""Get the Python executable path for a given app (OS-agnostic)."""
|
|
79
|
+
venv_path = _get_app_venv_path(app_name, wireless_version, desktop_app_daemon)
|
|
80
|
+
|
|
81
|
+
if _is_windows():
|
|
82
|
+
# Windows: Scripts/python.exe
|
|
83
|
+
python_exe = venv_path / "Scripts" / "python.exe"
|
|
84
|
+
if python_exe.exists():
|
|
85
|
+
return python_exe
|
|
86
|
+
# Fallback without .exe
|
|
87
|
+
python_path = venv_path / "Scripts" / "python"
|
|
88
|
+
if python_path.exists():
|
|
89
|
+
return python_path
|
|
90
|
+
# Default
|
|
91
|
+
return venv_path / "Scripts" / "python.exe"
|
|
92
|
+
else:
|
|
93
|
+
# Linux/Mac: bin/python
|
|
94
|
+
python_path = venv_path / "bin" / "python"
|
|
95
|
+
if python_path.exists():
|
|
96
|
+
return python_path
|
|
97
|
+
# Default
|
|
98
|
+
return venv_path / "bin" / "python"
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _get_app_site_packages(
|
|
102
|
+
app_name: str,
|
|
103
|
+
wireless_version: bool = False,
|
|
104
|
+
desktop_app_daemon: bool = False,
|
|
105
|
+
) -> Path | None:
|
|
106
|
+
"""Get the site-packages directory for a given app's venv (OS-agnostic)."""
|
|
107
|
+
venv_path = _get_app_venv_path(app_name, wireless_version, desktop_app_daemon)
|
|
108
|
+
|
|
109
|
+
if _is_windows():
|
|
110
|
+
# Windows: Lib/site-packages
|
|
111
|
+
site_packages = venv_path / "Lib" / "site-packages"
|
|
112
|
+
if site_packages.exists():
|
|
113
|
+
return site_packages
|
|
114
|
+
return None
|
|
115
|
+
else:
|
|
116
|
+
# Linux/Mac: lib/python3.x/site-packages
|
|
117
|
+
lib_dir = venv_path / "lib"
|
|
118
|
+
if not lib_dir.exists():
|
|
119
|
+
return None
|
|
120
|
+
python_dirs = list(lib_dir.glob("python3.*"))
|
|
121
|
+
if not python_dirs:
|
|
122
|
+
return None
|
|
123
|
+
return python_dirs[0] / "site-packages"
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def get_app_site_packages(
|
|
127
|
+
app_name: str,
|
|
128
|
+
wireless_version: bool = False,
|
|
129
|
+
desktop_app_daemon: bool = False,
|
|
130
|
+
) -> Path | None:
|
|
131
|
+
"""Public API to get the site-packages directory for a given app's venv."""
|
|
132
|
+
return _get_app_site_packages(app_name, wireless_version, desktop_app_daemon)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def get_app_python(
|
|
136
|
+
app_name: str,
|
|
137
|
+
wireless_version: bool = False,
|
|
138
|
+
desktop_app_daemon: bool = False,
|
|
139
|
+
) -> Path:
|
|
140
|
+
"""Get the Python executable path for an app (cross-platform).
|
|
141
|
+
|
|
142
|
+
For separate venvs: returns the app's venv Python
|
|
143
|
+
For shared environment: returns the current Python interpreter
|
|
144
|
+
"""
|
|
145
|
+
if _should_use_separate_venvs(wireless_version, desktop_app_daemon):
|
|
146
|
+
return _get_app_python(app_name, wireless_version, desktop_app_daemon)
|
|
147
|
+
else:
|
|
148
|
+
return Path(sys.executable)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _get_custom_app_url_from_file(
|
|
152
|
+
app_name: str,
|
|
153
|
+
wireless_version: bool = False,
|
|
154
|
+
desktop_app_daemon: bool = False,
|
|
155
|
+
) -> str | None:
|
|
156
|
+
"""Get custom_app_url by reading it from the app's main.py file.
|
|
157
|
+
|
|
158
|
+
This is much faster than subprocess and avoids sys.path pollution.
|
|
159
|
+
Looks for patterns like: custom_app_url: str | None = "http://..."
|
|
160
|
+
"""
|
|
161
|
+
site_packages = _get_app_site_packages(
|
|
162
|
+
app_name, wireless_version, desktop_app_daemon
|
|
163
|
+
)
|
|
164
|
+
if not site_packages or not site_packages.exists():
|
|
165
|
+
return None
|
|
166
|
+
|
|
167
|
+
# Try to find main.py in the app's package directory
|
|
168
|
+
app_dir = site_packages / app_name
|
|
169
|
+
main_file = app_dir / "main.py"
|
|
170
|
+
|
|
171
|
+
if not main_file.exists():
|
|
172
|
+
return None
|
|
173
|
+
|
|
174
|
+
try:
|
|
175
|
+
content = main_file.read_text(encoding="utf-8")
|
|
176
|
+
|
|
177
|
+
# Match patterns like:
|
|
178
|
+
# custom_app_url: str | None = "http://..."
|
|
179
|
+
# custom_app_url = "http://..."
|
|
180
|
+
# custom_app_url: str = "http://..."
|
|
181
|
+
pattern = r'custom_app_url\s*(?::\s*[^=]+)?\s*=\s*["\']([^"\']+)["\']'
|
|
182
|
+
match = re.search(pattern, content)
|
|
183
|
+
|
|
184
|
+
if match:
|
|
185
|
+
return match.group(1)
|
|
186
|
+
return None
|
|
187
|
+
except Exception as e:
|
|
188
|
+
logging.getLogger("reachy_mini.apps").warning(
|
|
189
|
+
f"Could not read custom_app_url from '{app_name}/main.py': {e}"
|
|
190
|
+
)
|
|
191
|
+
return None
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
async def _list_apps_from_separate_venvs(
|
|
195
|
+
wireless_version: bool = False,
|
|
196
|
+
desktop_app_daemon: bool = False,
|
|
197
|
+
) -> list[AppInfo]:
|
|
198
|
+
"""List apps by scanning sibling venv directories or shared venv entry points."""
|
|
199
|
+
parent_dir = _get_venv_parent_dir()
|
|
200
|
+
if not parent_dir.exists():
|
|
201
|
+
return []
|
|
202
|
+
|
|
203
|
+
if wireless_version and not desktop_app_daemon:
|
|
204
|
+
# Wireless: list apps from shared venv's entry points using subprocess
|
|
205
|
+
apps_venv = parent_dir / "apps_venv"
|
|
206
|
+
if not apps_venv.exists():
|
|
207
|
+
return []
|
|
208
|
+
|
|
209
|
+
# Get Python executable from the apps_venv
|
|
210
|
+
python_path = _get_app_python("dummy", wireless_version, desktop_app_daemon)
|
|
211
|
+
if not python_path.exists():
|
|
212
|
+
return []
|
|
213
|
+
|
|
214
|
+
# Use subprocess to list entry points from the apps_venv environment
|
|
215
|
+
import subprocess
|
|
216
|
+
|
|
217
|
+
try:
|
|
218
|
+
result = subprocess.run(
|
|
219
|
+
[
|
|
220
|
+
str(python_path),
|
|
221
|
+
"-c",
|
|
222
|
+
"from importlib.metadata import entry_points; "
|
|
223
|
+
"eps = entry_points(group='reachy_mini_apps'); "
|
|
224
|
+
"print('\\n'.join(ep.name for ep in eps))",
|
|
225
|
+
],
|
|
226
|
+
capture_output=True,
|
|
227
|
+
text=True,
|
|
228
|
+
timeout=5,
|
|
229
|
+
)
|
|
230
|
+
if result.returncode != 0:
|
|
231
|
+
return []
|
|
232
|
+
|
|
233
|
+
app_names = [
|
|
234
|
+
name.strip()
|
|
235
|
+
for name in result.stdout.strip().split("\n")
|
|
236
|
+
if name.strip()
|
|
237
|
+
]
|
|
238
|
+
apps = []
|
|
239
|
+
for app_name in app_names:
|
|
240
|
+
custom_app_url = _get_custom_app_url_from_file(
|
|
241
|
+
app_name, wireless_version, desktop_app_daemon
|
|
242
|
+
)
|
|
243
|
+
apps.append(
|
|
244
|
+
AppInfo(
|
|
245
|
+
name=app_name,
|
|
246
|
+
source_kind=SourceKind.INSTALLED,
|
|
247
|
+
extra={
|
|
248
|
+
"custom_app_url": custom_app_url,
|
|
249
|
+
"venv_path": str(apps_venv),
|
|
250
|
+
},
|
|
251
|
+
)
|
|
252
|
+
)
|
|
253
|
+
return apps
|
|
254
|
+
except (subprocess.TimeoutExpired, FileNotFoundError):
|
|
255
|
+
return []
|
|
256
|
+
else:
|
|
257
|
+
# Desktop: scan for per-app venv directories
|
|
258
|
+
apps = []
|
|
259
|
+
for venv_path in parent_dir.iterdir():
|
|
260
|
+
if not venv_path.is_dir() or not venv_path.name.endswith("_venv"):
|
|
261
|
+
continue
|
|
262
|
+
|
|
263
|
+
# Skip the shared wireless apps_venv directory
|
|
264
|
+
if venv_path.name == "apps_venv":
|
|
265
|
+
continue
|
|
266
|
+
|
|
267
|
+
# Extract app name from venv directory name
|
|
268
|
+
app_name = venv_path.name[: -len("_venv")]
|
|
269
|
+
|
|
270
|
+
# Get custom_app_url by reading the main.py file (fast, no sys.path pollution)
|
|
271
|
+
# This ensures the settings icon appears in the dashboard listing
|
|
272
|
+
custom_app_url = _get_custom_app_url_from_file(
|
|
273
|
+
app_name, wireless_version, desktop_app_daemon
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
apps.append(
|
|
277
|
+
AppInfo(
|
|
278
|
+
name=app_name,
|
|
279
|
+
source_kind=SourceKind.INSTALLED,
|
|
280
|
+
extra={
|
|
281
|
+
"custom_app_url": custom_app_url,
|
|
282
|
+
"venv_path": str(venv_path),
|
|
283
|
+
},
|
|
284
|
+
)
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
return apps
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
async def _list_apps_from_entry_points() -> list[AppInfo]:
|
|
291
|
+
"""List apps from current environment's entry points."""
|
|
292
|
+
entry_point_apps = entry_points(group="reachy_mini_apps")
|
|
293
|
+
|
|
294
|
+
apps = []
|
|
295
|
+
for ep in entry_point_apps:
|
|
296
|
+
custom_app_url = None
|
|
297
|
+
try:
|
|
298
|
+
app = ep.load()
|
|
299
|
+
custom_app_url = app.custom_app_url
|
|
300
|
+
except Exception as e:
|
|
301
|
+
logging.getLogger("reachy_mini.apps").warning(
|
|
302
|
+
f"Could not load app '{ep.name}' from entry point: {e}"
|
|
303
|
+
)
|
|
304
|
+
apps.append(
|
|
305
|
+
AppInfo(
|
|
306
|
+
name=ep.name,
|
|
307
|
+
source_kind=SourceKind.INSTALLED,
|
|
308
|
+
extra={"custom_app_url": custom_app_url},
|
|
309
|
+
)
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
return apps
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
async def list_available_apps(
|
|
316
|
+
wireless_version: bool = False, desktop_app_daemon: bool = False
|
|
317
|
+
) -> list[AppInfo]:
|
|
318
|
+
"""List apps available from entry points or separate venvs."""
|
|
319
|
+
if _should_use_separate_venvs(wireless_version, desktop_app_daemon):
|
|
320
|
+
return await _list_apps_from_separate_venvs(
|
|
321
|
+
wireless_version, desktop_app_daemon
|
|
322
|
+
)
|
|
323
|
+
else:
|
|
324
|
+
return await _list_apps_from_entry_points()
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
async def install_package(
|
|
328
|
+
app: AppInfo,
|
|
329
|
+
logger: logging.Logger,
|
|
330
|
+
wireless_version: bool = False,
|
|
331
|
+
desktop_app_daemon: bool = False,
|
|
332
|
+
) -> int:
|
|
333
|
+
"""Install a package given an AppInfo object, streaming logs."""
|
|
334
|
+
# Check if uv is available
|
|
335
|
+
use_uv = _check_uv_available()
|
|
336
|
+
if not use_uv:
|
|
337
|
+
logger.warning(
|
|
338
|
+
"uv is not installed. Falling back to pip. "
|
|
339
|
+
"Install uv for faster installs: pip install uv"
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
if app.source_kind == SourceKind.HF_SPACE:
|
|
343
|
+
# Use huggingface_hub to download the repo (handles LFS automatically)
|
|
344
|
+
# This avoids requiring git-lfs to be installed on the system
|
|
345
|
+
if app.url is not None:
|
|
346
|
+
# Extract repo_id from URL like "https://huggingface.co/spaces/owner/repo"
|
|
347
|
+
parts = app.url.rstrip("/").split("/")
|
|
348
|
+
repo_id = f"{parts[-2]}/{parts[-1]}" if len(parts) >= 2 else app.name
|
|
349
|
+
else:
|
|
350
|
+
repo_id = app.name
|
|
351
|
+
|
|
352
|
+
logger.info(f"Downloading HuggingFace Space: {repo_id}")
|
|
353
|
+
try:
|
|
354
|
+
target = await asyncio.to_thread(
|
|
355
|
+
snapshot_download,
|
|
356
|
+
repo_id=repo_id,
|
|
357
|
+
repo_type="space",
|
|
358
|
+
)
|
|
359
|
+
logger.info(f"Downloaded to: {target}")
|
|
360
|
+
except Exception as e:
|
|
361
|
+
logger.error(f"Failed to download from HuggingFace: {e}")
|
|
362
|
+
return 1
|
|
363
|
+
elif app.source_kind == SourceKind.LOCAL:
|
|
364
|
+
target = app.extra.get("path", app.name)
|
|
365
|
+
else:
|
|
366
|
+
raise ValueError(f"Cannot install app from source kind '{app.source_kind}'")
|
|
367
|
+
|
|
368
|
+
if _should_use_separate_venvs(wireless_version, desktop_app_daemon):
|
|
369
|
+
# Create separate venv for this app
|
|
370
|
+
app_name = app.name
|
|
371
|
+
venv_path = _get_app_venv_path(app_name, wireless_version, desktop_app_daemon)
|
|
372
|
+
success = False
|
|
373
|
+
|
|
374
|
+
# On wireless, only create venv if it doesn't exist (shared across apps)
|
|
375
|
+
venv_exists = venv_path.exists()
|
|
376
|
+
if venv_exists and not (wireless_version and not desktop_app_daemon):
|
|
377
|
+
# Desktop: remove existing per-app venv
|
|
378
|
+
logger.info(f"Removing existing venv at {venv_path}")
|
|
379
|
+
shutil.rmtree(venv_path)
|
|
380
|
+
venv_exists = False
|
|
381
|
+
|
|
382
|
+
try:
|
|
383
|
+
# Create venv if needed
|
|
384
|
+
if not venv_exists:
|
|
385
|
+
logger.info(f"Creating venv for '{app_name}' at {venv_path}")
|
|
386
|
+
ret = await running_command(
|
|
387
|
+
[sys.executable, "-m", "venv", str(venv_path)], logger=logger
|
|
388
|
+
)
|
|
389
|
+
if ret != 0:
|
|
390
|
+
return ret
|
|
391
|
+
|
|
392
|
+
# On wireless, pre-install reachy-mini with gstreamer support
|
|
393
|
+
if wireless_version and not desktop_app_daemon:
|
|
394
|
+
logger.info(
|
|
395
|
+
"Pre-installing reachy-mini with gstreamer support in apps_venv"
|
|
396
|
+
)
|
|
397
|
+
python_path = _get_app_python(
|
|
398
|
+
app_name, wireless_version, desktop_app_daemon
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
if use_uv:
|
|
402
|
+
install_cmd = [
|
|
403
|
+
"uv",
|
|
404
|
+
"pip",
|
|
405
|
+
"install",
|
|
406
|
+
"--python",
|
|
407
|
+
str(python_path),
|
|
408
|
+
"reachy-mini[gstreamer]",
|
|
409
|
+
]
|
|
410
|
+
else:
|
|
411
|
+
install_cmd = [
|
|
412
|
+
str(python_path),
|
|
413
|
+
"-m",
|
|
414
|
+
"pip",
|
|
415
|
+
"install",
|
|
416
|
+
"reachy-mini[gstreamer]",
|
|
417
|
+
]
|
|
418
|
+
|
|
419
|
+
ret = await running_command(install_cmd, logger=logger)
|
|
420
|
+
if ret != 0:
|
|
421
|
+
logger.warning(
|
|
422
|
+
"Failed to pre-install reachy-mini, continuing anyway"
|
|
423
|
+
)
|
|
424
|
+
else:
|
|
425
|
+
logger.info(f"Using existing shared venv at {venv_path}")
|
|
426
|
+
|
|
427
|
+
# Install package in the venv
|
|
428
|
+
python_path = _get_app_python(
|
|
429
|
+
app_name, wireless_version, desktop_app_daemon
|
|
430
|
+
)
|
|
431
|
+
|
|
432
|
+
if use_uv:
|
|
433
|
+
install_cmd = ["uv", "pip", "install", "--python", str(python_path), target]
|
|
434
|
+
else:
|
|
435
|
+
install_cmd = [str(python_path), "-m", "pip", "install", target]
|
|
436
|
+
|
|
437
|
+
ret = await running_command(install_cmd, logger=logger)
|
|
438
|
+
|
|
439
|
+
if ret != 0:
|
|
440
|
+
return ret
|
|
441
|
+
|
|
442
|
+
logger.info(f"Successfully installed '{app_name}' in {venv_path}")
|
|
443
|
+
success = True
|
|
444
|
+
return 0
|
|
445
|
+
finally:
|
|
446
|
+
# Clean up broken venv on any failure (but not shared wireless venv)
|
|
447
|
+
if (
|
|
448
|
+
not success
|
|
449
|
+
and venv_path.exists()
|
|
450
|
+
and not (wireless_version and not desktop_app_daemon)
|
|
451
|
+
):
|
|
452
|
+
logger.warning(f"Installation failed, cleaning up {venv_path}")
|
|
453
|
+
shutil.rmtree(venv_path)
|
|
454
|
+
else:
|
|
455
|
+
# Original behavior: install into current environment
|
|
456
|
+
if use_uv:
|
|
457
|
+
install_cmd = ["uv", "pip", "install", "--python", sys.executable, target]
|
|
458
|
+
else:
|
|
459
|
+
install_cmd = [sys.executable, "-m", "pip", "install", target]
|
|
460
|
+
|
|
461
|
+
return await running_command(install_cmd, logger=logger)
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
def get_app_module(
|
|
465
|
+
app_name: str,
|
|
466
|
+
wireless_version: bool = False,
|
|
467
|
+
desktop_app_daemon: bool = False,
|
|
468
|
+
) -> str:
|
|
469
|
+
"""Get the module name for an app without loading it (for subprocess execution)."""
|
|
470
|
+
if _should_use_separate_venvs(wireless_version, desktop_app_daemon):
|
|
471
|
+
# Get module from separate venv's entry points
|
|
472
|
+
site_packages = _get_app_site_packages(
|
|
473
|
+
app_name, wireless_version, desktop_app_daemon
|
|
474
|
+
)
|
|
475
|
+
if not site_packages or not site_packages.exists():
|
|
476
|
+
raise ValueError(f"App '{app_name}' venv not found or invalid")
|
|
477
|
+
|
|
478
|
+
sys.path.insert(0, str(site_packages))
|
|
479
|
+
try:
|
|
480
|
+
eps = entry_points(group="reachy_mini_apps")
|
|
481
|
+
ep = eps.select(name=app_name)
|
|
482
|
+
if not ep:
|
|
483
|
+
raise ValueError(f"No entry point found for app '{app_name}'")
|
|
484
|
+
# Get module name without loading (e.g., "my_app.main" from "my_app.main:MyApp")
|
|
485
|
+
return list(ep)[0].module
|
|
486
|
+
finally:
|
|
487
|
+
sys.path.pop(0)
|
|
488
|
+
else:
|
|
489
|
+
# Get module from current environment
|
|
490
|
+
eps = entry_points(group="reachy_mini_apps", name=app_name)
|
|
491
|
+
ep_list = list(eps)
|
|
492
|
+
if not ep_list:
|
|
493
|
+
raise ValueError(f"No entry point found for app '{app_name}'")
|
|
494
|
+
return ep_list[0].module
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
async def uninstall_package(
|
|
498
|
+
app_name: str,
|
|
499
|
+
logger: logging.Logger,
|
|
500
|
+
wireless_version: bool = False,
|
|
501
|
+
desktop_app_daemon: bool = False,
|
|
502
|
+
) -> int:
|
|
503
|
+
"""Uninstall a package given an app name."""
|
|
504
|
+
if _should_use_separate_venvs(wireless_version, desktop_app_daemon):
|
|
505
|
+
venv_path = _get_app_venv_path(app_name, wireless_version, desktop_app_daemon)
|
|
506
|
+
|
|
507
|
+
if not venv_path.exists():
|
|
508
|
+
raise ValueError(f"Cannot uninstall app '{app_name}': it is not installed")
|
|
509
|
+
|
|
510
|
+
if wireless_version and not desktop_app_daemon:
|
|
511
|
+
# Wireless: shared venv, just uninstall the package
|
|
512
|
+
logger.info(f"Uninstalling '{app_name}' from shared venv at {venv_path}")
|
|
513
|
+
python_path = _get_app_python(
|
|
514
|
+
app_name, wireless_version, desktop_app_daemon
|
|
515
|
+
)
|
|
516
|
+
|
|
517
|
+
# Check if uv is available
|
|
518
|
+
use_uv = _check_uv_available()
|
|
519
|
+
|
|
520
|
+
if use_uv:
|
|
521
|
+
uninstall_cmd = [
|
|
522
|
+
"uv",
|
|
523
|
+
"pip",
|
|
524
|
+
"uninstall",
|
|
525
|
+
"--python",
|
|
526
|
+
str(python_path),
|
|
527
|
+
app_name,
|
|
528
|
+
]
|
|
529
|
+
else:
|
|
530
|
+
uninstall_cmd = [
|
|
531
|
+
str(python_path),
|
|
532
|
+
"-m",
|
|
533
|
+
"pip",
|
|
534
|
+
"uninstall",
|
|
535
|
+
"-y",
|
|
536
|
+
app_name,
|
|
537
|
+
]
|
|
538
|
+
|
|
539
|
+
ret = await running_command(uninstall_cmd, logger=logger)
|
|
540
|
+
if ret == 0:
|
|
541
|
+
logger.info(f"Successfully uninstalled '{app_name}'")
|
|
542
|
+
return ret
|
|
543
|
+
else:
|
|
544
|
+
# Desktop: remove the entire per-app venv directory
|
|
545
|
+
logger.info(f"Removing venv for '{app_name}' at {venv_path}")
|
|
546
|
+
shutil.rmtree(venv_path)
|
|
547
|
+
logger.info(f"Successfully uninstalled '{app_name}'")
|
|
548
|
+
return 0
|
|
549
|
+
else:
|
|
550
|
+
existing_apps = await list_available_apps()
|
|
551
|
+
if app_name not in [app.name for app in existing_apps]:
|
|
552
|
+
raise ValueError(f"Cannot uninstall app '{app_name}': it is not installed")
|
|
553
|
+
|
|
554
|
+
# Check if uv is available
|
|
555
|
+
use_uv = _check_uv_available()
|
|
556
|
+
|
|
557
|
+
logger.info(f"Removing package {app_name}")
|
|
558
|
+
|
|
559
|
+
if use_uv:
|
|
560
|
+
uninstall_cmd = ["uv", "pip", "uninstall", "--python", sys.executable, app_name]
|
|
561
|
+
else:
|
|
562
|
+
uninstall_cmd = [sys.executable, "-m", "pip", "uninstall", "-y", app_name]
|
|
563
|
+
|
|
564
|
+
ret = await running_command(uninstall_cmd, logger=logger)
|
|
565
|
+
if ret == 0:
|
|
566
|
+
logger.info(f"Successfully uninstalled '{app_name}'")
|
|
567
|
+
return ret
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8" />
|
|
6
|
+
<meta name="viewport" content="width=device-width" />
|
|
7
|
+
<title> {{ class_name_display }} </title>
|
|
8
|
+
<link rel="stylesheet" href="style.css" />
|
|
9
|
+
</head>
|
|
10
|
+
|
|
11
|
+
<body>
|
|
12
|
+
<div class="hero">
|
|
13
|
+
<div class="hero-content">
|
|
14
|
+
<div class="app-icon">🤖⚡</div>
|
|
15
|
+
<h1> {{ class_name_display }} </h1>
|
|
16
|
+
<p class="tagline">Enter your tagline here</p>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<div class="container">
|
|
21
|
+
<div class="main-card">
|
|
22
|
+
<div class="app-preview">
|
|
23
|
+
<div class="preview-image">
|
|
24
|
+
<div class="camera-feed">🛠️</div>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<div class="footer">
|
|
31
|
+
<p>
|
|
32
|
+
🤖 {{ class_name_display }} •
|
|
33
|
+
<a href="https://github.com/pollen-robotics" target="_blank">Pollen Robotics</a> •
|
|
34
|
+
<a href="https://huggingface.co/spaces/pollen-robotics/reachy-mini-landing-page#apps" target="_blank">Browse More
|
|
35
|
+
Apps</a>
|
|
36
|
+
</p>
|
|
37
|
+
</div>
|
|
38
|
+
</body>
|
|
39
|
+
|
|
40
|
+
</html>
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import threading
|
|
2
|
+
from reachy_mini import ReachyMini, ReachyMiniApp
|
|
3
|
+
from reachy_mini.utils import create_head_pose
|
|
4
|
+
import numpy as np
|
|
5
|
+
import time
|
|
6
|
+
from pydantic import BaseModel
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class {{ class_name }}(ReachyMiniApp):
|
|
10
|
+
# Optional: URL to a custom configuration page for the app
|
|
11
|
+
# eg. "http://localhost:8042"
|
|
12
|
+
custom_app_url: str | None = "http://0.0.0.0:8042"
|
|
13
|
+
# Optional: specify a media backend ("gstreamer", "default", etc.)
|
|
14
|
+
request_media_backend: str | None = None
|
|
15
|
+
|
|
16
|
+
def run(self, reachy_mini: ReachyMini, stop_event: threading.Event):
|
|
17
|
+
t0 = time.time()
|
|
18
|
+
|
|
19
|
+
antennas_enabled = True
|
|
20
|
+
sound_play_requested = False
|
|
21
|
+
|
|
22
|
+
# You can ignore this part if you don't want to add settings to your app. If you set custom_app_url to None, you have to remove this part as well.
|
|
23
|
+
# === vvv ===
|
|
24
|
+
class AntennaState(BaseModel):
|
|
25
|
+
enabled: bool
|
|
26
|
+
|
|
27
|
+
@self.settings_app.post("/antennas")
|
|
28
|
+
def update_antennas_state(state: AntennaState):
|
|
29
|
+
nonlocal antennas_enabled
|
|
30
|
+
antennas_enabled = state.enabled
|
|
31
|
+
return {"antennas_enabled": antennas_enabled}
|
|
32
|
+
|
|
33
|
+
@self.settings_app.post("/play_sound")
|
|
34
|
+
def request_sound_play():
|
|
35
|
+
nonlocal sound_play_requested
|
|
36
|
+
sound_play_requested = True
|
|
37
|
+
|
|
38
|
+
# === ^^^ ===
|
|
39
|
+
|
|
40
|
+
# Main control loop
|
|
41
|
+
while not stop_event.is_set():
|
|
42
|
+
t = time.time() - t0
|
|
43
|
+
|
|
44
|
+
yaw_deg = 30.0 * np.sin(2.0 * np.pi * 0.2 * t)
|
|
45
|
+
head_pose = create_head_pose(yaw=yaw_deg, degrees=True)
|
|
46
|
+
|
|
47
|
+
if antennas_enabled:
|
|
48
|
+
amp_deg = 25.0
|
|
49
|
+
a = amp_deg * np.sin(2.0 * np.pi * 0.5 * t)
|
|
50
|
+
antennas_deg = np.array([a, -a])
|
|
51
|
+
else:
|
|
52
|
+
antennas_deg = np.array([0.0, 0.0])
|
|
53
|
+
|
|
54
|
+
if sound_play_requested:
|
|
55
|
+
print("Playing sound...")
|
|
56
|
+
reachy_mini.media.play_sound("wake_up.wav")
|
|
57
|
+
sound_play_requested = False
|
|
58
|
+
|
|
59
|
+
antennas_rad = np.deg2rad(antennas_deg)
|
|
60
|
+
|
|
61
|
+
reachy_mini.set_target(
|
|
62
|
+
head=head_pose,
|
|
63
|
+
antennas=antennas_rad,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
time.sleep(0.02)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
if __name__ == "__main__":
|
|
70
|
+
app = {{ class_name }}()
|
|
71
|
+
try:
|
|
72
|
+
app.wrapped_run()
|
|
73
|
+
except KeyboardInterrupt:
|
|
74
|
+
app.stop()
|