diff --git a/README.md b/README.md index 26f5e29..9a0239c 100644 --- a/README.md +++ b/README.md @@ -197,12 +197,5 @@ pip install numpy==1.24.3 Закрытие окна игры или нажатие `q` в окне камеры – выход. При завершении игры (неважно выигрыш или проигрыш) нажмите `r` чтобы перезапустить симулятор. -## Создание собственного контроллера скоростей -По умолчанию преобразование позы в скорости реализовано в классе `ArmController` (файл `arm_control.py`). -Чтобы изменить логику управления, выполните одно из действий: -1. Изменить метод `compute_speeds` в `arm_control.py` – он должен принимать аргумент landmarks (список из 33 точек MediaPipe) и возвращать кортеж (linear, angular) – числа с плавающей точкой. -2. Создать свой класс-наследник от `ArmController` и переопределить `compute_speeds`. Затем в `main.py` заменить создание экземпляра на свой класс. - -После этого не забудьте изменить параметры словаря `ARM_CONTROL` в `Config` вы можете добавлять туда свои поля и читать их в методе. ## Добавление своих жестов Подмодуль `gesture_detection` содержит всё необходимое для обучения собственных моделей жестов. diff --git a/geom_controll/arm_control.py b/geom_controll/arm_control.py deleted file mode 100644 index f7bcd75..0000000 --- a/geom_controll/arm_control.py +++ /dev/null @@ -1,126 +0,0 @@ -import numpy as np - -class ArmController: - def __init__(self, config, mirror=False): - self.config = config - self.mirror = mirror - self.shoulder_idx = {'left': 11, 'right': 12} - self.wrist_idx = {'left': 15, 'right': 16} - self.hip_idx = {'left': 23, 'right': 24} - self.dead_zone = config.get('dead_zone', 0.2) - self.debug = config.get('debug', False) - - def _get_side_indices(self, side): - """ - Возвращает (shoulder_idx, wrist_idx) для заданной стороны (left/right). - При mirror=True интерпретируем сторону как в реальности: левая/правая рука. - """ - if self.mirror: - if side == 'left': - s_idx = 12 - w_idx = 16 - else: - s_idx = 11 - w_idx = 15 - else: - if side == 'left': - s_idx = 11 - w_idx = 15 - else: - s_idx = 12 - w_idx = 16 - return s_idx, w_idx - - def _get_shoulder_width(self, landmarks): - """Ширина плеч для нормировки горизонтальных смещений.""" - left = landmarks[11][:2] - right = landmarks[12][:2] - width = np.linalg.norm(right - left) - if width < 50 or width > 300: - return None - return width - - def _get_torso_height(self, landmarks): - """Высота торса для нормировки вертикальных смещений.""" - left_shoulder = landmarks[11][:2] - right_shoulder = landmarks[12][:2] - left_hip = landmarks[23][:2] - right_hip = landmarks[24][:2] - shoulder_center = (left_shoulder + right_shoulder) / 2 - hip_center = (left_hip + right_hip) / 2 - height = np.linalg.norm(shoulder_center - hip_center) - if height < 50: - return None - return height - - def _horizontal_displacement_rel(self, landmarks, side): - """ - Нормированное горизонтальное смещение запястья относительно плеча. - Сторона `side` — это реальная сторона руки - """ - s_idx, w_idx = self._get_side_indices(side) - - if landmarks[s_idx][3] < 0.5 or landmarks[w_idx][3] < 0.5: - return 0.0 - - shoulder = landmarks[s_idx][:2] - wrist = landmarks[w_idx][:2] - - shoulder_width = self._get_shoulder_width(landmarks) - if shoulder_width is None: - return 0.0 - - disp = wrist[0] - shoulder[0] - return disp / shoulder_width - - def _vertical_displacement_rel(self, landmarks, side): - """ - Вертикальное смещение: верх/низ запястья относительно плеча. - Сторона `side` — реальная сторона руки. - """ - s_idx, w_idx = self._get_side_indices(side) - - if landmarks[s_idx][3] < 0.5 or landmarks[w_idx][3] < 0.5: - return 0.0 - - shoulder = landmarks[s_idx][:2] - wrist = landmarks[w_idx][:2] - - torso_height = self._get_torso_height(landmarks) - if torso_height is None: - return 0.0 - - disp = shoulder[1] - wrist[1] - return disp / torso_height - - def compute_speeds(self, landmarks): - if (landmarks[11][3] < 0.5 or landmarks[12][3] < 0.5 or - landmarks[15][3] < 0.5 or landmarks[16][3] < 0.5): - if self.debug: - print("Руки не видны") - return 0.0, 0.0 - - linear_side = self.config['linear_arm'] - angular_side = self.config['angular_arm'] - - lin_rel = self._horizontal_displacement_rel(landmarks, linear_side) - ang_rel = self._vertical_displacement_rel(landmarks, angular_side) - - if self.debug: - print(f"lin_rel={lin_rel:.3f}, ang_rel={ang_rel:.3f}") - - # Линейная скорость (только вперёд) - if lin_rel < self.dead_zone: - linear = 0.0 - else: - linear = min(lin_rel, 1.0) * self.config['max_speed_linear'] - - # Угловая скорость - if abs(ang_rel) < self.dead_zone: - angular = 0.0 - else: - ang_rel_clipped = np.clip(ang_rel, -1.0, 1.0) - angular = ang_rel_clipped * self.config['max_speed_angular'] - - return linear, angular - diff --git a/main.py b/main.py index a17a350..361d42d 100644 --- a/main.py +++ b/main.py @@ -8,9 +8,10 @@ from config import Config from skeleton.mediapipe_detector import MediaPipeDetector from skeleton.oak_pose_detector import OakPoseDetector from gesture_control.special_gestures import SpecialGestureDetector +from gesture_control.arm_control import ArmController from ml_gestures_dynamic.predict import DynamicGesturePredictor -from geom_controll.arm_control import ArmController +#from geom_controll.arm_control import ArmController from robot.simulated_robot import DummySimRobot from robot.debug_robot import DebugRobot diff --git a/submodules/gesture_detection b/submodules/gesture_detection index 0415ff9..0b3c74c 160000 --- a/submodules/gesture_detection +++ b/submodules/gesture_detection @@ -1 +1 @@ -Subproject commit 0415ff9f429d9f23bd14897447a0d555955eb17a +Subproject commit 0b3c74c4632339ba743bd2093c50d40cdf5de4ab