2024-05-22T21:26:29.png

XEDU:

import cv2
import numpy as np
import pygame
import sys
import socket
from XEdu.hub import Workflow as wf

# 初始化 pygame
pygame.init()
pygame.joystick.init()

# 确保至少有一个手柄连接
if pygame.joystick.get_count() == 0:
    print("请连接一个Xbox手柄")
    sys.exit()

# 获取第一个手柄
joystick = pygame.joystick.Joystick(0)
joystick.init()

print(f"检测到手柄: {joystick.get_name()}")

# 设置屏幕大小
screen = pygame.display.set_mode((640, 480))
pygame.display.set_caption("Xbox手柄摇杆值显示")

# 设置UDP通信
esp32_left_ip = "192.168.1.100"   # 替换为左侧ESP32的IP地址
esp32_right_ip = "192.168.1.54"  # 替换为右侧ESP32的IP地址
esp32_port = 12345                # 替换为ESP32的端口号

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 初始化视频捕捉
cap = cv2.VideoCapture(0)
body = wf(task='body17')  # 实例化pose模型
det = wf(task='bodydetect')  # 实例化detect模型

hands_up_prev = False  # 用于跟踪上一次的状态
# 设置窗口的初始大小
cv2.namedWindow('video', cv2.WINDOW_NORMAL)
cv2.resizeWindow('video', 1280, 1024)

# 创建字体对象
font = pygame.font.Font(None, 36)

# 初始化手柄摇杆变量
left_stick_x = 0.0
left_stick_y = 0.0
right_stick_x = 0.0
right_stick_y = 0.0

# 初始化 hands_up 变量
hands_up = False

# 主循环
running = True
while running and cap.isOpened():
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.JOYAXISMOTION:
            # 获取左右摇杆的值
            left_stick_x = joystick.get_axis(0)
            left_stick_y = joystick.get_axis(1)
            right_stick_x = joystick.get_axis(2)  # 修改为2
            right_stick_y = joystick.get_axis(3)
            
            # 打印摇杆值
            print(f"左摇杆: X={left_stick_x:.3f}, Y={left_stick_y:.3f} | 右摇杆: X={right_stick_x:.3f}, Y={right_stick_y:.3f}")
            
            # 发送数据到ESP32
            left_stick_data = f"LX={left_stick_x:.3f},LY={left_stick_y:.3f}"
            right_stick_data = f"RX={right_stick_x:.3f},RY={right_stick_y:.3f}"
            
            sock.sendto(left_stick_data.encode(), (esp32_left_ip, esp32_port))
            sock.sendto(right_stick_data.encode(), (esp32_right_ip, esp32_port))

    ret, frame = cap.read()
    if not ret:
        break

    bboxs = det.inference(data=frame, thr=0.3)
    img = frame

    hands_up = False

    for i, bbox in enumerate(bboxs):
        keypoints, img = body.inference(data=img, img_type='cv2', bbox=bbox)

        # 计算鼻子位置
        nose_x, nose_y = keypoints[0][0], keypoints[0][1]

        # 计算两手高度
        left_hand_y = keypoints[9][2]
        right_hand_y = keypoints[10][3]

        # 判断是否两手都比鼻子高
        if left_hand_y < nose_y and right_hand_y < nose_y:
            hands_up = True

    for [x1, y1, x2, y2] in bboxs:  # 画检测框
        cv2.rectangle(img, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2)

    if hands_up != hands_up_prev:  # 只有在状态改变时发送 UDP 消息
        if hands_up:
            udp_message = "hands_up:on"
        else:
            udp_message = "hands_up:off"
        sock.sendto(udp_message.encode(), (esp32_left_ip, esp32_port))  # 发送到左侧ESP32的IP和端口
        sock.sendto(udp_message.encode(), (esp32_right_ip, esp32_port))  # 发送到左侧ESP32的IP和端口
        hands_up_prev = hands_up  # 更新状态

    # 清屏
    screen.fill((0, 0, 0))

    # 显示摇杆数据
    left_text = font.render(f"left_stick: X={left_stick_x:.3f}, Y={left_stick_y:.3f}", True, (255, 255, 255))
    right_text = font.render(f"right_stick: X={right_stick_x:.3f}, Y={right_stick_y:.3f}", True, (255, 255, 255))
    screen.blit(left_text, (20, 20))
    screen.blit(right_text, (20, 60))

    # 显示 hands_up 状态
    hands_up_text = "hands_up:on" if hands_up else "hands_up:off"
    hands_up_display = font.render(hands_up_text, True, (255, 255, 255))
    screen.blit(hands_up_display, (20, 100))

    # 更新显示
    pygame.display.flip()

    cv2.imshow('video', img)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()
pygame.quit()
sock.close()
sys.exit()

esp32:

#include <WiFi.h>
#include <WiFiUdp.h>

const char* ssid = "42101";
const char* password = "15657859912";
const unsigned int localPort = 12345; // 与Python代码中的端口匹配
const int ledPin = 2;

WiFiUDP udp;

void setup() {
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  
  Serial.begin(115200);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }

  Serial.println("Connected to WiFi");
  udp.begin(localPort);
  Serial.println(WiFi.localIP());
  digitalWrite(ledPin, HIGH);
  delay(2000);
  digitalWrite(ledPin, LOW);
}

void loop() {
  int packetSize = udp.parsePacket();
  if (packetSize) {
    char incomingPacket[255];
    int len = udp.read(incomingPacket, 255);
    if (len > 0) {
      incomingPacket[len] = 0;
    }
    Serial.printf("Received packet: %s\n", incomingPacket);

    // 处理接收到的数据,例如解析 hands_up:on 或 hands_up:off
    if (strcmp(incomingPacket, "hands_up:on") == 0) {
      digitalWrite(ledPin, HIGH);  // 点亮 LED
    } else if (strcmp(incomingPacket, "hands_up:off") == 0) {
      digitalWrite(ledPin, LOW);   // 熄灭 LED
    }
  }
}

发表评论