diff --git a/backend/Main.py b/backend/Main.py index 7e8054a70..48631c8ef 100644 --- a/backend/Main.py +++ b/backend/Main.py @@ -5,7 +5,6 @@ import logging from app.ChameleonVisionApp import ChameleonApplication from app.classes.SettingsManager import SettingsManager from tornado.options import options -from app.handlers.VisionHandler import VisionHandler import threading import asyncio from app.handlers.SocketHandler import send_all_async diff --git a/backend/app/ChameleonVisionApp.py b/backend/app/ChameleonVisionApp.py index cd786c272..7336ae001 100644 --- a/backend/app/ChameleonVisionApp.py +++ b/backend/app/ChameleonVisionApp.py @@ -1,7 +1,6 @@ import tornado.web import tornado.websocket import os - from .handlers.MainHandler import MainHandler from .handlers.SocketHandler import ChameleonWebSocket from tornado.options import define diff --git a/backend/app/classes/SettingsManager.py b/backend/app/classes/SettingsManager.py index 9e74507cc..75ae2182b 100644 --- a/backend/app/classes/SettingsManager.py +++ b/backend/app/classes/SettingsManager.py @@ -1,4 +1,3 @@ -import socket import os import json import cv2 diff --git a/backend/app/handlers/CameraHander.py b/backend/app/handlers/CameraHander.py index d3541685e..04eb48ab7 100644 --- a/backend/app/handlers/CameraHander.py +++ b/backend/app/handlers/CameraHander.py @@ -16,6 +16,7 @@ from .VisionHandler import VisionHandler class CameraHandler: def __init__(self, cam_name, port): + #settings vars up for vision loop self.cs = CameraServer.getInstance() self.settings_manager = SettingsManager() self.vision_handler = VisionHandler() @@ -28,27 +29,24 @@ class CameraHandler: self.time_stamp = 0 def run(self): + #starting main thread threading.Thread(target=self.thread_proc).start() def thread_proc(self): - cam_name = self.cam_name - port = self.port - - asyncio.set_event_loop(asyncio.new_event_loop()) - self.settings_manager.cams_curr_pipeline[cam_name] = "pipeline0" - pipeline = self.settings_manager.cams[cam_name]["pipelines"][self.settings_manager.cams_curr_pipeline[cam_name]] - FOV = self.settings_manager.cams[cam_name]["FOV"] + self.settings_manager.cams_curr_pipeline[self.cam_name] = "pipeline0" + pipeline = self.settings_manager.cams[self.cam_name]["pipelines"][self.settings_manager.cams_curr_pipeline[self.cam_name]] + FOV = self.settings_manager.cams[self.cam_name]["FOV"] def change_camera_values(pipline): - self.settings_manager.usb_cameras[cam_name].setBrightness(pipeline['brightness']) - self.settings_manager.usb_cameras[cam_name].setExposureManual(pipeline['exposure']) - self.settings_manager.usb_cameras[cam_name].setWhiteBalanceAuto() + self.settings_manager.usb_cameras[self.cam_name].setBrightness(pipeline['brightness']) + self.settings_manager.usb_cameras[self.cam_name].setExposureManual(pipeline['exposure']) + self.settings_manager.usb_cameras[self.cam_name].setWhiteBalanceAuto() def pipeline_listener(table, key, value, is_new): asyncio.set_event_loop(asyncio.new_event_loop()) - self.settings_manager.cams_curr_pipeline[cam_name] = value + self.settings_manager.cams_curr_pipeline[self.cam_name] = value change_camera_values(pipeline) - if cam_name == self.settings_manager.general_settings['curr_camera']: + if self.cam_name == self.settings_manager.general_settings['curr_camera']: self.settings_manager.general_settings['curr_pipeline'] = value update_settings = self.settings_manager.get_curr_pipeline() update_settings['curr_pipeline'] = self.settings_manager.general_settings["curr_pipeline"] @@ -59,45 +57,43 @@ class CameraHandler: 'brightness': 25, 'exposure': 15 }) - - self.table = NetworkTables.getTable("/Chameleon-Vision/" + cam_name) - self.table.putString('Pipeline', self.settings_manager.cams_curr_pipeline[cam_name]) + #setting up network table + self.table = NetworkTables.getTable("/Chameleon-Vision/" + self.cam_name) + self.table.putString('Pipeline', self.settings_manager.cams_curr_pipeline[self.cam_name]) self.table.addEntryListenerEx(pipeline_listener, key="Pipeline", flags=networktables.NetworkTablesInstance.NotifyFlags.UPDATE) self.table.addEntryListenerEx(mode_listener, key="Driver_Mode", flags=networktables.NetworkTablesInstance.NotifyFlags.UPDATE) - # gettings video from curent camera - cv_sink = self.cs.getVideo(camera=self.settings_manager.usb_cameras[cam_name]) - width = self.settings_manager.cams[cam_name]["video_mode"]["width"] - height = self.settings_manager.cams[cam_name]["video_mode"]["height"] + # getting video from current camera + cv_sink = self.cs.getVideo(camera=self.settings_manager.usb_cameras[self.cam_name]) + + width = self.settings_manager.cams[self.cam_name]["video_mode"]["width"] + height = self.settings_manager.cams[self.cam_name]["video_mode"]["height"] # setting up a video server for camera - cv_publish = self.cs.putVideo(name=cam_name, width=width, height=height) + cv_publish = self.cs.putVideo(name=self.cam_name, width=width, height=height) # saving camera port in cam name dict for usage in client - self.settings_manager.cams_port[cam_name] = self.cs._sinks['serve_' + cam_name].getPort() + self.settings_manager.cams_port[self.cam_name] = self.cs._sinks['serve_' + self.cam_name].getPort() # setting up a zmq connection to the opencv subprocess context = zmq.Context() socket = context.socket(zmq.PAIR) - socket.bind('tcp://*:%s' % str(port)) + socket.bind('tcp://*:%s' % str(self.port)) - # starting the process with inital values - p = Process(target=self.camera_process, args=(cam_name, port, FOV)) + # starting the process with initial values + p = Process(target=self.camera_process, args=(self.cam_name, self.port, FOV)) p.start() change_camera_values(pipeline) - def _image_thread(): + def _publish_thread(): + #getting image values and publishing process image and data self.image = numpy.zeros(shape=(width, height, 3), dtype=numpy.uint8) self.p_image = self.image - while True: - self.time_stamp, self.image = cv_sink.grabFrame(self.image) - - def _publish_thread(): - # asyncio.set_event_loop(asyncio.new_event_loop()) while True: try: + self.time_stamp, self.image = cv_sink.grabFrame(self.image) cv_publish.putFrame(self.p_image) self.table.putBoolean('valid', self.nt_data['valid']) # check if point is valid @@ -111,12 +107,31 @@ class CameraHandler: except: pass - threading.Thread(target=_image_thread).start() + def _socket_thread(): + #publishing to websocket at slower interval + asyncio.set_event_loop(asyncio.new_event_loop()) + while True: + time.sleep(0.05) + if self.settings_manager.general_settings['curr_camera'] == self.cam_name: + try: + send_all_async({ + 'raw_point': self.nt_data['raw_point'], + 'point': { + 'pitch': self.nt_data['pitch'], + 'yaw': self.nt_data['yaw'], + 'fps': self.nt_data['fps'] + } + }) + except: + pass + threading.Thread(target=_publish_thread).start() + threading.Thread(target=_socket_thread).start() while True: - pipeline = self.settings_manager.cams[cam_name]["pipelines"][ - self.settings_manager.cams_curr_pipeline[cam_name]] + #sending and reciving data from opencv sub process + pipeline = self.settings_manager.cams[self.cam_name]["pipelines"][ + self.settings_manager.cams_curr_pipeline[self.cam_name]] socket.send_json(dict( pipeline=pipeline ), zmq.SNDMORE) @@ -124,23 +139,11 @@ class CameraHandler: socket.send_pyobj(self.image) self.p_image = socket.recv_pyobj() self.nt_data = socket.recv_json() - # if self.settings_manager.general_settings['curr_camera'] == self.cam_name: - # try: - # send_all_async({ - # 'raw_point': self.nt_data['raw_point'], - # 'point': { - # 'pitch': self.nt_data['pitch'], - # 'yaw': self.nt_data['yaw'], - # 'fps': self.nt_data['fps'] - # } - # }) - # except: - # pass def camera_process(self, cam_name, port, FOV): from fractions import Fraction - - diagonalView = math.radians(FOV) # needs to be implemented in client + #calc fov + diagonalView = math.radians(FOV) width = self.settings_manager.cams[cam_name]["video_mode"]["width"] height = self.settings_manager.cams[cam_name]["video_mode"]["height"] @@ -157,15 +160,18 @@ class CameraHandler: H_FOCAL_LENGTH = width / (2 * math.tan((horizontalView / 2))) V_FOCAL_LENGTH = height / (2 * math.tan((verticalView / 2))) - + #setting up zmq socket context = zmq.Context() socket = context.socket(zmq.PAIR) socket.connect('tcp://localhost:%s' % str(port)) + #setting up filter countours class filter_contours = self.vision_handler.Filter_Contours(center_x=centerX, center_y=centerY) + x = 1 counter = 0 start_time = time.time() fps = 0 + while True: obj = socket.recv_json() image = socket.recv_pyobj() @@ -217,6 +223,3 @@ class CameraHandler: fps = (counter / (time.time() - start_time)) counter = 0 start_time = time.time() - - - diff --git a/backend/app/handlers/SocketHandler.py b/backend/app/handlers/SocketHandler.py index 6a4eaad41..b6f54d136 100644 --- a/backend/app/handlers/SocketHandler.py +++ b/backend/app/handlers/SocketHandler.py @@ -1,5 +1,3 @@ -from datetime import timedelta - import tornado.websocket import json from ..classes.Exceptions import NoCameraConnectedException diff --git a/backend/app/handlers/VisionHandler.py b/backend/app/handlers/VisionHandler.py index 38a7ca9e4..b669c0177 100644 --- a/backend/app/handlers/VisionHandler.py +++ b/backend/app/handlers/VisionHandler.py @@ -1,11 +1,10 @@ import cv2 import numpy -from ..classes.Singleton import Singleton import math from enum import Enum, unique -class VisionHandler(metaclass=Singleton): +class VisionHandler(): def __init__(self): self.kernel = numpy.ones((5, 5), numpy.uint8)