Загрузка данных
import asyncio
import json
import struct
import numpy as np
import cv2
import websockets
from playwright.async_api import async_playwright
ROBOT_IP = "10.10.10.10"
WS_URL = f"ws://{ROBOT_IP}:8765"
CAM_URL = f"http://{ROBOT_IP}:8889/cam/"
CMD_TOPIC = "/cmd_vel"
LINEAR_SPEED = 0.25
ANGULAR_SPEED = 0.6
channel_id = 1
ws_conn = None
async def send_twist(vx, wz):
if ws_conn is None:
return
twist_data = {
"linear": {"x": float(vx), "y": 0.0, "z": 0.0},
"angular": {"x": 0.0, "y": 0.0, "z": float(wz)}
}
payload = json.dumps(twist_data).encode('utf-8')
header = struct.pack("<BI", 1, channel_id)
try:
await ws_conn.send(header + payload)
except Exception:
pass
async def main():
global ws_conn
print(f"1. Подключение к Foxglove WebSocket {WS_URL}...")
async with websockets.connect(WS_URL, subprotocols=["foxglove.websocket.v1"]) as ws:
ws_conn = ws
# Регистрируем топик скорости
advertise_msg = {
"op": "advertise",
"channels": [{
"id": channel_id,
"topic": CMD_TOPIC,
"encoding": "json",
"schemaName": "geometry_msgs/msg/Twist"
}]
}
await ws.send(json.dumps(advertise_msg))
print("Управление подключено!")
print(f"2. Подключение к видеопотоку WebRTC: {CAM_URL}...")
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
await page.goto(CAM_URL)
# Ждем появления тега video
video_element = await page.wait_for_selector("video", timeout=15000)
print("\n==============================================")
print(" ОКНО ВИДЕО ОТКРЫТО!")
print(" Кликните на появившееся окно с видео:")
print(" W - вперед | S - назад | A/D - повороты")
print(" Пробел - остановка | ESC/Q - выход")
print("==============================================\n")
current_vx = 0.0
current_wz = 0.0
try:
while True:
# Снимаем текущий кадр из видео
img_bytes = await video_element.screenshot()
nparr = np.frombuffer(img_bytes, np.uint8)
frame = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
if frame is not None:
# Текст со скоростью на кадре
status_text = f"Vx: {current_vx:.2f} | Wz: {current_wz:.2f}"
cv2.putText(frame, status_text, (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
cv2.imshow("RoboMarvel Live Camera & Control", frame)
# Читаем клавиши в окне OpenCV
key = cv2.waitKey(20) & 0xFF
if key in (ord('w'), ord('W'), 230): # W / ц
current_vx, current_wz = LINEAR_SPEED, 0.0
elif key in (ord('s'), ord('S'), 251): # S / ы
current_vx, current_wz = -LINEAR_SPEED, 0.0
elif key in (ord('a'), ord('A'), 244): # A / ф
current_vx, current_wz = 0.0, ANGULAR_SPEED
elif key in (ord('d'), ord('D'), 226): # D / в
current_vx, current_wz = 0.0, -ANGULAR_SPEED
elif key == ord(' '): # Пробел - СТОП
current_vx, current_wz = 0.0, 0.0
elif key in (27, ord('q'), ord('Q')): # ESC / Q - Выход
break
# Отправляем команду скорости
await send_twist(current_vx, current_wz)
finally:
await send_twist(0.0, 0.0)
await browser.close()
cv2.destroyAllWindows()
if __name__ == "__main__":
asyncio.run(main())