Форум сайта python.su
Пишу самоходную коляску с ip камерой. Python скрипт на компе, принимает rtsp поток с камеры и отсылает http запросы на управление двигателями в зависимости от нажатых клавиш. Сделано в 2 потока, но есть проблемка. Когда я жму стрелку для движения на компе, то в окне питона видео зависает, пока не отпущу клавишу, потом видео догоняет и я вижу что произошло и куда я уехал. Очень не удобно, а как придумать что бы видео не останавливалось пока жмешь клавишу ни как не могу понять. Хелп.
import threading import cv2 import requests import numpy as np import math from pynput import keyboard from threading import Thread class Roboto: def __init__(self): self.u = 0 self.d = 0 self.l = 0 self.r = 0 self.rtsp = 'rtsp://192.168.1.118:554/ch0_1.h264' self.token = '******************************' def move(self, forward, side): response = requests.get( 'http://blynk-cloud.com/' + self.token + '/update/V0?value=' + str(side) + '&value=' + str(forward)) def on_press(self, key): k = format(key) if k == 'Key.up' and self.u == 0: self.move(10, 0) self.u = 1 if k == 'Key.down' and self.d == 0: self.move(-10, 0) self.d = 1 if k == 'Key.left' and self.l == 0: self.move(0, -5) self.l = 1 if k == 'Key.right' and self.r == 0: self.move(0, 5) self.r = 1 def on_release(self, key): k = format(key) if k == 'Key.down' or k == 'Key.up' or k == 'Key.left' or k == 'Key.right': self.move(0, 0) self.u = 0 self.d = 0 self.l = 0 self.r = 0 if key == keyboard.Key.esc: # Stop listener return False def camera(self): cam = cv2.VideoCapture(self.rtsp) cv2.namedWindow('cam') while True: ret, frame = cam.read() if ret: frame = frame[0:360, 0:640] frame = cv2.rotate(frame, cv2.ROTATE_90_CLOCKWISE) cv2.imshow('cam', frame) else: print("Cam not release") break k = cv2.waitKey(24) & 0xFF if k == 27: break cam.release() cv2.destroyAllWindows() def controll(self): with keyboard.Listener( on_press=self.on_press, on_release=self.on_release) as listener: listener.join() def main(): roboto = Roboto() thread1 = Thread(name='camera', target=roboto.camera) thread2 = Thread(name='controll', target=roboto.controll) thread1.start() thread2.start() thread1.join() thread2.join() if __name__ == '__main__': main()
Отредактировано alexzlo (Окт. 9, 2020 01:18:27)
Офлайн
Мдаа… Интересный проект. Похоже не хватает быстродействия цикла передачи данных от клавиатуры.
Надо залоггировать действия в файл и посмотреть где тормозит. press release move(те http get) и посмотреть сколько команды вместе требуют времени и влезают ли они в цикл генерации событий от клавы.
Что неясно:
Что такое format
Как устроен чам робот, что с той стороны. Каков код, аппаратура.
Что можно сделать:
Очевидно форматирование строк в цикле рального времени не гуд.
def on_press(self, key): #k = format(key) - Убираем формтирование # if k == 'Key.up' and self.u == 0: # Проверка строк это нехорошо сравнивать коды. Сначала проверять то что быстрее проверяется self.u == 0 if self.u == 0 and k == code_up: self.move(10, 0) self.u = 1 # if k == 'Key.down' and self.d == 0: # зачем все 4 варианта проверять? elif k == code_dn and self.d == 0: self.move(-10, 0) self.d = 1
def on_release(self, key): if key == keyboard.Key.esc: return False else: self.move(0, 0) self.u = 0 self.d = 0 self.l = 0 self.r = 0
Офлайн
На той стороне старый робот пылесос с ip камерой, мозгом пылесоса выступает nodemcu, который принимает get запросы через облачный сервис blynk и рулит моторами. Сделано все так потому что нет pasberry py. Собрал из того что нашел в тумбочке.
format взят из примеров либы pynput, либу использую потому что как я понял из коробки python не умеет отслеживать нажатие стрелочных клавиш.
Изначально у меня был цикл видео и цикл pynput, но оно не работало, скрипт вечно висел в одном из циклов, смотря какой из них первый в скрипте, поэтому пришел к Threads.
Отредактировано alexzlo (Окт. 9, 2020 11:40:10)
Офлайн
Сейчас проверил, если использовать камеру ноутбука, а не rtsp поток то видео не зависает
Офлайн
По идее от вас команда уходит только в начале периода когда вы кнопку зажали, поэтому не должно видео виснуть на весь период нажатия. Обмен с локальной камерой идет по другому каналу связи, что конечно влияет на все процессы.
Поэтому результат этого эксперимента не отменяет необходимости залоггировать последовательность происходящих событий.
alexzlo
Изначально у меня был цикл видео и цикл pynput,
def controll(self): with keyboard.Listener( on_press=self.on_press, on_release=self.on_release) as listener: listener.join()
Офлайн