gesture control node started

main
Eliza Moscovskaya 4 weeks ago
parent aa220ba49c
commit 387c8175e0

@ -9,6 +9,11 @@ import cv2
import numpy as np
from sensor_msgs.msg import Image
from skeleton.mediapipe_detector import MediaPipeDetector
from gesture_control.special_gestures import SpecialGestureDetector
from gesture_control.arm_control import ArmController
from ml_gestures_dynamic.predict import DynamicGesturePredictor
class BaseGestureControlNode(Node):
def __init__(self, RobotController):
@ -23,6 +28,56 @@ class BaseGestureControlNode(Node):
# subscriptions
self.create_subscription(Image, 'image', self.image_cb, 10)
#ros params?
ARM_CONTROL = {
'linear_arm': 'right',
'angular_arm': 'left',
'max_speed_linear': 1.0,
'max_speed_angular': 1.0,
'dead_zone': 0.2,
'debug': False
}
SPECIAL_GESTURE_MODE = 'geometric' # 'ml' или 'geometric'
ML_GESTURE_MODEL = "path/to/special_gestures_rf.pkl"
ML_GESTURE_CLASSES ['dome', 'cross', 'none']
DG_ENABLED = True
DG_MODEL_PATH = "path/to/dynamic_model.h5"
DG_CLASSES_PATH = "path/to/dynamic_model_classes.pkl"
DG_WINDOW_SIZE = 14
DG_THRESH = 0.8
# gestures
self.detector = MediaPipeDetector()
self.arm_control = ArmController(ARM_CONTROL, mirror=True)
self.special_detector = SpecialGestureDetector(
mode=SPECIAL_GESTURE_MODE,
model_path=ML_GESTURE_MODEL,
class_names=ML_GESTURE_CLASSES
)
self.dynamic_predictor = None
if DG_ENABLED:
self.dynamic_predictor = DynamicGesturePredictor(
DG_MODEL_PATH,
DG_CLASSES_PATH,
DG_WINDOW_SIZE,
DG_THRESH
)
# Состояния управления
self.enabled = False # разрешено ли управление жестами
self.cross_cooldown = 0
self.CROSS_COOLDOWN_FRAMES = 30 # сколько кадров блокировки после переключения ждем
self.dome_processed = False # предотвращает многократное срабатывание тушителя
self.last_dynamic = None # последний жест распознанный
self.dynamic_counter = 0 # отображение последнего распознанного динамического жеста в течение 30 кадров
self.image_pub = self.create_publisher(Image, 'skeleton_image', 10)
def image_cb(self, msg):
@ -38,9 +93,89 @@ class BaseGestureControlNode(Node):
while rclpy.ok():
if not self.cv_image is None:
# DO DETECTION HERE
self.cv_image
frame = self.cv_image.copy()
# Детекция скелета
result = self.detector.detect(frame)
if result['success']:
landmarks = result['landmarks']
pose_landmarks = result.get('pose_landmarks')
else:
landmarks = None
pose_landmarks = None
vis_image = frame.copy()
if landmarks is not None:
# Распознавание статичного жеста
special = self.special_detector.predict(landmarks)
# Вкл/выкл управления жестами
if special == 'cross' and self.cross_cooldown == 0:
self.enabled = not self.enabled
self.cross_cooldown = self.CROSS_COOLDOWN_FRAMES
self.get_logger().info(
f"Gesture control {'ENABLED' if self.enabled else 'DISABLED'}"
)
if self.cross_cooldown > 0:
self.cross_cooldown -= 1
# Команда тушения
if self.enabled:
if special == 'dome' and not self.dome_processed:
self.URC.send_fire_ext_burst_cmd():
self.dome_processed = True
elif special != 'dome':
self.dome_processed = False
# Скорости
linear, angular = self.arm_control.compute_speeds(landmarks)
if self.enabled:
self.URC.send_speed_cmd(linear, angular)
else:
self.URC.send_speed_cmd(0.0, 0.0)
# Распознавание динамических жестов
if self.dynamic_predictor:
self.dynamic_predictor.add_frame(landmarks)
dynamic_gesture = self.dynamic_predictor.predict()
if dynamic_gesture:
self.last_dynamic = dynamic_gesture
self.dynamic_counter = 30
self.get_logger().info(f"Dynamic gesture: {dynamic_gesture}")
'''
Дальше можно уже отсылать команду в зависимости от жеста. Доступны: 'wave_left', 'wave_right'
'''
# Отрисовка
# Скелет
vis_image = self.detector.draw_landmarks(vis_image, pose_landmarks)
# Имена жестов и т.п.
cv2.putText(vis_image, f"Move: {'ON' if self.enabled else 'OFF'}",
(10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1,
(0, 255, 0) if self.enabled else (0, 0, 255), 2)
cv2.putText(vis_image, f"L:{linear:.2f} A:{angular:.2f}",
(10, 60), cv2.FONT_HERSHEY_SIMPLEX, 0.7,
(255, 255, 0), 2)
if special != 'none':
cv2.putText(vis_image, f"Special: {special}",
(10, 90), cv2.FONT_HERSHEY_SIMPLEX, 0.7,
(255, 255, 0), 2)
if self.dynamic_counter > 0 and self.last_dynamic:
cv2.putText(vis_image, f"Dynamic: {self.last_dynamic}",
(10, 120), cv2.FONT_HERSHEY_SIMPLEX, 0.7,
(0, 255, 255), 2)
self.dynamic_counter -= 1
else:
# Скелета нет - стоим
self.URC.send_speed_cmd(0.0, 0.0)
cv2.putText(vis_image, "No pose detected",
(10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1,
(0, 0, 255), 2)
# Паблишер изображения со скелетом
image_msg = self.bridge.cv2_to_imgmsg(vis_image, encoding='bgr8')
self.image_pub.publish(image_msg)
# SELECT COMMAND
@ -54,8 +189,6 @@ class BaseGestureControlNode(Node):
rclpy.shutdown()
def main(args=None):
rclpy.init(args=args)

Loading…
Cancel
Save