diff --git a/backend/Main.py b/backend/Main.py index d1c752ba2..e1a47bc3e 100644 --- a/backend/Main.py +++ b/backend/Main.py @@ -4,9 +4,12 @@ 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 def run_server(): + asyncio.set_event_loop(asyncio.new_event_loop()) tornado.options.parse_command_line() app = ChameleonApplication() print(f"Serving on port {options.port}") @@ -19,7 +22,8 @@ if __name__ == "__main__": SettingsManager() VisionHandler().run() - run_server() + server_thread = threading.Thread(target=run_server) + server_thread.start() while True: pass diff --git a/backend/app/classes/SettingsManager.py b/backend/app/classes/SettingsManager.py index 7de5badcd..76a1f0309 100644 --- a/backend/app/classes/SettingsManager.py +++ b/backend/app/classes/SettingsManager.py @@ -1,3 +1,4 @@ +import socket import os import json import cv2 @@ -12,12 +13,12 @@ class SettingsManager(metaclass=Singleton): usb_cameras = {} usb_cameras_info = {} general_settings = {} + cams_port = {} default_pipeline = { "exposure": 50, "brightness": 50, "orientation": "Normal", - "resolution": [320, 160], "hue": [0, 100], "saturation": [0, 100], "value": [0, 100], @@ -36,7 +37,7 @@ class SettingsManager(metaclass=Singleton): "connection_type": "DHCP", "ip": "", "gateway": "", - "hostname": "Chameleon-Vision", + "hostname": "", "curr_camera": "", "curr_pipeline": "" } @@ -133,8 +134,10 @@ class SettingsManager(metaclass=Singleton): "height": video_mode.height, "pixel_format": str(video_mode.pixelFormat).split('.')[1] } - self.usb_cameras[camera_name].setVideoMode(self.usb_cameras[camera_name].enumerateVideoModes()[int(dic["resolution"])]) + self.usb_cameras[camera_name].setVideoMode(self.usb_cameras[camera_name].enumerateVideoModes()[int(dic["resolution"])]) + if "FOV" in dic: + self.cams[camera_name]["FOV"] = float(dic["FOV"]) # Access methods def get_curr_pipeline(self): @@ -163,7 +166,7 @@ class SettingsManager(metaclass=Singleton): def set_curr_camera(self, cam_name): if cam_name in self.cams: self.general_settings["curr_camera"] = cam_name - self.general_settings["curr_pipeline"] = self.get_curr_cam()["pipelines"].keys()[0] + self.general_settings["curr_pipeline"] = list(self.get_curr_cam()["pipelines"].keys())[0] def set_curr_pipeline(self, pipe_name): if pipe_name in self.get_curr_cam()["pipelines"]: @@ -182,9 +185,13 @@ class SettingsManager(metaclass=Singleton): self.cams[cam_name]["pipelines"][pipe_name][key] = dic[key] def change_general_settings_values(self, dic): - for key in dic: + for key in dic['change_general_settings_values']: if self.default_general_settings[key]: - self.general_settings[key] = dic[key] + self.general_settings[key] = dic['change_general_settings_values'][key] + self.settings_manager.save_settings() + #after all values has been set change settings + self.change_general_settings() + # Creators @@ -218,8 +225,10 @@ class SettingsManager(metaclass=Singleton): "fps": video_mode.fps, "width": video_mode.width, "height": video_mode.height, - "pixel_format": str(video_mode.pixelFormat).split('.')[1] + "pixel_format": str(video_mode.pixelFormat).split('.')[1], } + self.cams[cam_name]['resolution'] = 0 + self.cams[cam_name]["FOV"] = 60.8 # Savers @@ -242,3 +251,8 @@ class SettingsManager(metaclass=Singleton): with open(os.path.join(self.settings_path, 'settings.json'), 'w+') as setting_file: json.dump(self.general_settings, setting_file) + + def change_general_settings(self): + pass + + diff --git a/backend/app/classes/imagezmq.py b/backend/app/classes/imagezmq.py deleted file mode 100644 index f05e6dbf5..000000000 --- a/backend/app/classes/imagezmq.py +++ /dev/null @@ -1,232 +0,0 @@ -""" imagezmq: Transport OpenCV images via ZMQ. - -Classes that transport OpenCV images from one computer to another. For example, -OpenCV images gathered by a Raspberry Pi camera could be sent to another -computer for displaying the images using cv2.imshow() or for further image -processing. See API and Usage Examples for details. - -Copyright (c) 2017 by Jeff Bass. -License: MIT, see LICENSE for more details. -""" - -import zmq -import numpy as np -import cv2 - - -class ImageSender(): - """Opens zmq REQ socket and sends images. - - Opens a zmq REQ socket on the image sending computer, often a - Raspberry Pi, that will be sending OpenCV images and - related text messages to the hub computer. Provides methods to - send images or send jpg compressed images. - - Arguments: - connect_to: the tcp address:port of the hub computer. - """ - - def __init__(self, connect_to='tcp://127.0.0.1:5555'): - """Initializes zmq socket for sending images to the hub. - - Expects an open socket at the connect_to tcp address; it will - connect to that remote socket after setting up the REQ - socket on this computer. - """ - - self.zmq_context = SerializingContext() - self.zmq_socket = self.zmq_context.socket(zmq.REQ) - self.zmq_socket.connect(connect_to) - - def send_image(self, msg, image): - """Sends OpenCV image and msg to hub computer. - - Arguments: - msg: text message or image name. - image: OpenCV image to send to hub. - - Returns: - A text reply from hub. - """ - - if image.flags['C_CONTIGUOUS']: - # if image is already contiguous in memory just send it - self.zmq_socket.send_array(image, msg, copy=False) - else: - # else make it contiguous before sending - image = np.ascontiguousarray(image) - self.zmq_socket.send_array(image, msg, copy=False) - hub_reply = self.zmq_socket.recv() # receive the reply message - return hub_reply - - def send_jpg(self, msg, jpg_buffer): - """Sends msg text and jpg buffer to hub computer. - - Arguments: - msg: image name or message text. - jpg_buffer: bytestring containing the jpg image to send to hub. - Returns: - A text reply from hub. - """ - - self.zmq_socket.send_jpg(msg, jpg_buffer, copy=False) - hub_reply = self.zmq_socket.recv() # receive the reply message - return hub_reply - - -class ImageHub(): - """Opens zmq REP socket and receives images. - - Opens a zmq REP socket on the hub compuer, for example, - a Mac, that will be receiving and displaying or processing OpenCV images - and related text messages. Provides methods to receive images or receive - jpg compressed images. - - Arguments: - open_port: (optional) the socket to open for receiving REQ requests. - """ - - def __init__(self, open_port='tcp://*:5555'): - """Initializes zmq REP socket to receive images and text. - """ - - self.zmq_context = SerializingContext() - self.zmq_socket = self.zmq_context.socket(zmq.REP) - self.zmq_socket.bind(open_port) - - def recv_image(self, copy=False): - """Receives OpenCV image and text msg. - - Arguments: - copy: (optional) zmq copy flag. - - Returns: - msg: text msg, often the image name. - image: OpenCV image. - """ - - msg, image = self.zmq_socket.recv_array(copy=False) - return msg, image - - def recv_jpg(self, copy=False): - """Receives text msg, jpg buffer. - - Arguments: - copy: (optional) zmq copy flag - Returns: - msg: text message, often image name - jpg_buffer: bytestring jpg compressed image - """ - - msg, jpg_buffer = self.zmq_socket.recv_jpg(copy=False) - return msg, jpg_buffer - - def send_reply(self, reply_message=b'OK'): - """Sends the zmq REP reply message. - - Arguments: - reply_message: reply message text, often just string 'OK' - """ - self.zmq_socket.send(reply_message) - - -class SerializingSocket(zmq.Socket): - """Numpy array serialization methods. - - Modelled on PyZMQ serialization examples. - - Used for sending / receiving OpenCV images, which are Numpy arrays. - Also used for sending / receiving jpg compressed OpenCV images. - """ - - def send_array(self, A, msg='NoName', flags=0, copy=True, track=False): - """Sends a numpy array with metadata and text message. - - Sends a numpy array with the metadata necessary for reconstructing - the array (dtype,shape). Also sends a text msg, often the array or - image name. - - Arguments: - A: numpy array or OpenCV image. - msg: (optional) array name, image name or text message. - flags: (optional) zmq flags. - copy: (optional) zmq copy flag. - track: (optional) zmq track flag. - """ - - md = dict( - msg=msg, - dtype=str(A.dtype), - shape=A.shape, - ) - self.send_json(md, flags | zmq.SNDMORE) - return self.send(A, flags, copy=copy, track=track) - - def send_jpg(self, - msg='NoName', - jpg_buffer=b'00', - flags=0, - copy=True, - track=False): - """Send a jpg buffer with a text message. - - Sends a jpg bytestring of an OpenCV image. - Also sends text msg, often the image name. - - Arguments: - msg: image name or text message. - jpg_buffer: jpg buffer of compressed image to be sent. - flags: (optional) zmq flags. - copy: (optional) zmq copy flag. - track: (optional) zmq track flag. - """ - - md = dict(msg=msg, ) - self.send_json(md, flags | zmq.SNDMORE) - return self.send(jpg_buffer, flags, copy=copy, track=track) - - def recv_array(self, flags=0, copy=True, track=False): - """Receives a numpy array with metadata and text message. - - Receives a numpy array with the metadata necessary - for reconstructing the array (dtype,shape). - Returns the array and a text msg, often the array or image name. - - Arguments: - flags: (optional) zmq flags. - copy: (optional) zmq copy flag. - track: (optional) zmq track flag. - - Returns: - msg: image name or text message. - A: numpy array or OpenCV image reconstructed with dtype and shape. - """ - - md = self.recv_json(flags=flags) - msg = self.recv(flags=flags, copy=copy, track=track) - A = np.frombuffer(msg, dtype=md['dtype']) - return (md['msg'], A.reshape(md['shape'])) - - def recv_jpg(self, flags=0, copy=True, track=False): - """Receives a jpg buffer and a text msg. - - Receives a jpg bytestring of an OpenCV image. - Also receives a text msg, often the image name. - - Arguments: - flags: (optional) zmq flags. - copy: (optional) zmq copy flag. - track: (optional) zmq track flag. - - Returns: - msg: image name or text message. - jpg_buffer: bytestring, containing jpg image. - """ - - md = self.recv_json(flags=flags) # metadata text - jpg_buffer = self.recv(flags=flags, copy=copy, track=track) - return (md['msg'], jpg_buffer) - - -class SerializingContext(zmq.Context): - _socket_class = SerializingSocket diff --git a/backend/app/handlers/CamerasHandler.py b/backend/app/handlers/CamerasHandler.py deleted file mode 100644 index 9ab112722..000000000 --- a/backend/app/handlers/CamerasHandler.py +++ /dev/null @@ -1,75 +0,0 @@ -import cscore -import cv2 -from cscore._cscore import VideoMode - -class CamerasHandler: - - #@staticmethod - # def get_cameras_info(): - # - # if not getattr(CamerasHandler, "cams_info", False): - # - # arr = [] - # - # usb_devices = cscore.UsbCamera.enumerateUsbCameras() - # - # for index in range(len(usb_devices)): - # cap = cv2.VideoCapture(index) - # if cap.isOpened(): - # arr.append(index) - # cap.release() - # index += 1 - # - # setattr(CamerasHandler, "cams_info", [usb_devices[i] for i in arr]) - # - # return getattr(CamerasHandler, "cams_info") - - # @staticmethod - # def get_or_start_cameras(usb_devices): - # - # if not getattr(CamerasHandler, "cams", False): - # cameras = {} - # for device in usb_devices: - # device_name = device.name - # - # if device.name in cameras: - # suffix = 0 - # device_name = device.name + str(suffix) - # - # while device_name in cameras: - # suffix += 1 - # device_name = "pipeline" + str(suffix) - # - # camera = cscore.UsbCamera(name=device_name, dev=device.dev) - # camera.setPixelFormat(pixelFormat= - # getattr(VideoMode.PixelFormat, SettingsManager() - # .get_curr_cam()["video_mode"]["pixel_format"])) - # camera.setFPS(SettingsManager().get_curr_cam()["video_mode"]["fps"]) - # camera.setResolution(width=SettingsManager().get_curr_cam()["video_mode"]["width"], - # height=SettingsManager().get_curr_cam()["video_mode"]["height"]) - # - # cameras[device_name] = camera - # - # setattr(CamerasHandler, "cams", cameras) - # - # return getattr(CamerasHandler, "cams") - - # @staticmethod - # def init_camera(): - # return CamerasHandler.get_or_start_cameras(CamerasHandler.get_cameras_info()) - # - # @staticmethod - # def get_usb_camera_by_name(cam_name): - # return CamerasHandler.get_or_start_cameras(CamerasHandler.get_cameras_info())[cam_name] - - @staticmethod - def set_camera_settings(usb_camera: cscore.UsbCamera, dic): - - if "brightness" in dic: - usb_camera.setBrightness(dic["brightness"]) - - if "exposure" in dic: - usb_camera.setExposureManual(dic["exposure"]) - - if "video_mode" in dic: - usb_camera.setVideoMode(dic["video_mode"]) diff --git a/backend/app/handlers/SocketHandler.py b/backend/app/handlers/SocketHandler.py index 5db7edc60..618cbb84e 100644 --- a/backend/app/handlers/SocketHandler.py +++ b/backend/app/handlers/SocketHandler.py @@ -4,10 +4,27 @@ from ..classes.Exceptions import NoCameraConnectedException from ..classes.SettingsManager import SettingsManager +web_socket_clients = [] + + +def send_all_async(message): + for ws in web_socket_clients: + try: + if not ws.ws_connection.stream.socket: + web_socket_clients.remove(ws) + else: + try: + ws.write_message(message) + except AssertionError as a: + pass + except AssertionError: + pass + + class ChameleonWebSocket(tornado.websocket.WebSocketHandler): actions = {} - set_this_camera_settings = ["exposure", "brightness", "resolution"] + set_this_camera_settings = ["exposure", "brightness"] def __init__(self, application, request, **kwargs): super().__init__(application, request, **kwargs) @@ -17,32 +34,44 @@ class ChameleonWebSocket(tornado.websocket.WebSocketHandler): def init_actions(self): self.actions["change_pipeline_values"] = self.change_pipeline_values self.actions["change_general_settings_values"] = self.settings_manager.change_general_settings_values - self.actions["change_cam"] = self.change_curr_camera - self.actions["change_pipeline"] = self.change_curr_pipeline + self.actions["curr_camera"] = self.change_curr_camera + self.actions["curr_pipeline"] = self.change_curr_pipeline + self.actions['resolution'] = self.set_resolution + self.actions['FOV'] = self.set_fov def open(self): - self.send_full_settings() + if self not in web_socket_clients: + web_socket_clients.append(self) print("WebSocket opened") def on_message(self, message): - message_dic = json.loads(message) for key in message_dic: self.actions.get(key, self.actions["change_pipeline_values"])(message_dic) - print(message) def on_close(self): self.settings_manager.save_settings() - + if self in web_socket_clients: + web_socket_clients.remove(self) print("WebSocket closed") def check_origin(self, origin): return True + def set_resolution(self, message): + self.settings_manager.get_curr_cam()['resolution'] = message['resolution'] + SettingsManager().set_camera_settings(camera_name=SettingsManager().general_settings['curr_camera'], + dic=message) + self.settings_manager.save_settings() + + def set_fov(self, message): + self.settings_manager.get_curr_cam()['FOV'] = message['FOV'] + self.settings_manager.save_settings() + def send_curr_pipeline(self): try: self.write_message(self.settings_manager.get_curr_pipeline()) @@ -57,14 +86,21 @@ class ChameleonWebSocket(tornado.websocket.WebSocketHandler): # TODO: return something if no camera connected self.write_message("No camera connected") + def send_curr_port(self): + self.write_message({ + 'port': self.settings_manager.cams_port[self.settings_manager.general_settings["curr_camera"]] + }) + def send_full_settings(self): full_settings = self.settings_manager.general_settings.copy() full_settings["cameraList"] = list(self.settings_manager.cams.copy().keys()) - try: full_settings.update(self.settings_manager.get_curr_pipeline()) full_settings["pipelineList"] = list(self.settings_manager.cams[self.settings_manager.general_settings["curr_camera"]]["pipelines"].keys()) full_settings["resolutionList"] = self.settings_manager.get_resolution_list() + full_settings['resolution'] = self.settings_manager.get_curr_cam()['resolution'] + full_settings['FOV'] = self.settings_manager.get_curr_cam()['FOV'] + full_settings['port'] = self.settings_manager.cams_port[self.settings_manager.general_settings["curr_camera"]] except NoCameraConnectedException: # TODO: return something if no camera connected full_settings["data"] = None @@ -72,16 +108,16 @@ class ChameleonWebSocket(tornado.websocket.WebSocketHandler): self.write_message(full_settings) def change_curr_camera(self, dic): - self.settings_manager.set_curr_camera(cam_name=dic["cam"]) + self.settings_manager.set_curr_camera(cam_name=dic["curr_camera"]) + self.send_curr_port() self.send_curr_cam() def change_curr_pipeline(self, dic): - self.settings_manager.set_curr_pipeline(pipe_name=dic["pipeline"]) + self.settings_manager.set_curr_pipeline(pipe_name=dic["curr_pipeline"]) self.send_curr_pipeline() def change_pipeline_values(self, dic): self.settings_manager.change_pipeline_values(dic) - for key in self.set_this_camera_settings: if key in dic: self.settings_manager.set_camera_settings(self.settings_manager.general_settings["curr_camera"], diff --git a/backend/app/handlers/VisionHandler.py b/backend/app/handlers/VisionHandler.py index 362d4b7f7..56c1433ba 100644 --- a/backend/app/handlers/VisionHandler.py +++ b/backend/app/handlers/VisionHandler.py @@ -1,3 +1,4 @@ +import asyncio from networktables import NetworkTables import networktables import cv2 @@ -10,6 +11,7 @@ import threading import zmq import math from enum import Enum, unique +from ..handlers.SocketHandler import send_all_async class VisionHandler(metaclass=Singleton): @@ -252,7 +254,10 @@ class VisionHandler(metaclass=Singleton): port += 1 def thread_proc(self, cs, cam_name, port=5557): - pipeline = SettingsManager().cams[cam_name]["pipelines"]["pipeline0"] + asyncio.set_event_loop(asyncio.new_event_loop()) + pipeline_name = 'pipeline0' + pipeline = SettingsManager().cams[cam_name]["pipelines"][pipeline_name] + FOV = SettingsManager().cams[cam_name]["FOV"] def change_camera_values(pipline): SettingsManager.usb_cameras[cam_name].setBrightness(pipeline['brightness']) @@ -274,7 +279,7 @@ class VisionHandler(metaclass=Singleton): flags=networktables.NetworkTablesInstance.NotifyFlags.UPDATE) table.addEntryListenerEx(mode_listener, key="Driver_Mode", flags=networktables.NetworkTablesInstance.NotifyFlags.UPDATE) - + #gettings video from curent camera cv_sink = cs.getVideo(camera=SettingsManager.usb_cameras[cam_name]) width = SettingsManager().cams[cam_name]["video_mode"]["width"] @@ -282,34 +287,58 @@ class VisionHandler(metaclass=Singleton): image = numpy.zeros(shape=(width, height, 3), dtype=numpy.uint8) + #setting up a video server for camera cv_publish = cs.putVideo(name=cam_name, width=width, height=height) + # saving camera port in cam name dict for usage in client + SettingsManager().cams_port[cam_name] = cs._sinks['serve_'+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)) - p = Process(target=self.camera_process, args=(cam_name, port)) + #starting the process with inital values + p = Process(target=self.camera_process, args=(cam_name, port, FOV)) p.start() change_camera_values(pipeline) + while True: _, image = cv_sink.grabFrame(image) socket.send_json(dict( pipeline=pipeline )) + socket.send_pyobj(image) p_image = socket.recv_pyobj() nt_data = socket.recv_json() + table.putBoolean('valid', nt_data['valid']) + # check if point is valid if nt_data['valid']: + #send the point using network tables table.putNumber('pitch', nt_data['pitch']) table.putNumber('yaw', nt_data['yaw']) - table.putBoolean('valid', nt_data['valid']) + #if the selected camera in ui is this cam send the point to the ui + if SettingsManager().general_settings['curr_camera'] == cam_name: + try: + if nt_data['raw_point'] is not None: + send_all_async({ + 'raw_point': nt_data['raw_point'], + 'point': { + 'pitch': nt_data['pitch'], + 'yaw': nt_data['yaw'] + } + }) + except Exception as e: + print(e) + #send the image to the camera server + cv_publish.putFrame(p_image) - def camera_process(self, cam_name, port): + def camera_process(self, cam_name, port, FOV): from fractions import Fraction - diagonalView = math.radians(68.5) #needs to be implemented in client + diagonalView = math.radians(FOV) #needs to be implemented in client width = SettingsManager().cams[cam_name]["video_mode"]["width"] height = SettingsManager().cams[cam_name]["video_mode"]["height"] @@ -354,6 +383,7 @@ class VisionHandler(metaclass=Singleton): yaw = self.calculate_yaw(pixel_x=center[0], center_x=centerX, h_focal_length=H_FOCAL_LENGTH) valid = True except IndexError: + center = None pitch = None yaw = None valid = False @@ -367,8 +397,8 @@ class VisionHandler(metaclass=Singleton): socket.send_json(dict( pitch=pitch, yaw=yaw, - valid= valid - + valid=valid, + raw_point=center )) diff --git a/backend/settings/cams/AN-VC500 Camera.json b/backend/settings/cams/AN-VC500 Camera.json deleted file mode 100644 index 4d38cbed0..000000000 --- a/backend/settings/cams/AN-VC500 Camera.json +++ /dev/null @@ -1 +0,0 @@ -{"pipelines": {"pipeline0": {"exposure": 4, "brightness": 74, "orientation": "Normal", "resolution": [320, 160], "hue": [43, 80], "saturation": [159, 255], "value": [55, 255], "erode": false, "dilate": false, "area": [0, 100], "ratio": [0, 89.9], "extent": [61, 100], "is_binary": 0, "sort_mode": "Largest", "target_group": "Dual", "target_intersection": "Up"}}, "path": "/dev/v4l/by-path/pci-0000:02:03.0-usb-0:1:1.0-video-index0", "video_mode": {"fps": 30, "width": 640, "height": 480, "pixel_format": "kYUYV"}} \ No newline at end of file diff --git a/backend/settings/cams/USB Camera-B4.09.24.1.json b/backend/settings/cams/USB Camera-B4.09.24.1.json index 4d9c86199..794e41662 100644 --- a/backend/settings/cams/USB Camera-B4.09.24.1.json +++ b/backend/settings/cams/USB Camera-B4.09.24.1.json @@ -1 +1 @@ -{"pipelines": {"pipeline0": {"exposure": 50, "brightness": 11, "orientation": "Normal", "resolution": [320, 160], "hue": [0, 100], "saturation": [0, 100], "value": [0, 100], "erode": false, "dilate": false, "area": [20, 34], "ratio": [0, 22.9], "extent": [13, 71], "is_binary": "Normal", "sort_mode": "Largest", "target_group": "Single", "target_intersection": "Up"}}, "path": "/dev/v4l/by-path/pci-0000:02:03.0-usb-0:1:1.0-video-index0", "video_mode": {"fps": 187, "width": 320, "height": 240, "pixel_format": "kYUYV"}} \ No newline at end of file +{"pipelines": {"pipeline0": {"exposure": 50, "brightness": 10, "orientation": "Normal", "hue": [0, 56], "saturation": [0, 47], "value": [0, 100], "erode": false, "dilate": false, "area": [0, 100], "ratio": [0, 99], "extent": [0, 100], "is_binary": 1, "sort_mode": "Rightmost", "target_group": "Single", "target_intersection": "Up"}}, "path": "/dev/v4l/by-path/pci-0000:02:03.0-usb-0:1:1.0-video-index0", "video_mode": {"fps": 15, "width": 640, "height": 480, "pixel_format": "kYUYV"}, "resolution": 14, "FOV": 56} \ No newline at end of file diff --git a/backend/settings/cams/USB2.0 PC CAMERA.json b/backend/settings/cams/USB2.0 PC CAMERA.json new file mode 100644 index 000000000..c26acf48d --- /dev/null +++ b/backend/settings/cams/USB2.0 PC CAMERA.json @@ -0,0 +1 @@ +{"pipelines": {"pipeline0": {"exposure": 50, "brightness": 50, "orientation": "Normal", "hue": [0, 100], "saturation": [0, 100], "value": [0, 100], "erode": false, "dilate": false, "area": [0, 100], "ratio": [0, 20], "extent": [0, 100], "is_binary": "Normal", "sort_mode": "Largest", "target_group": "Single", "target_intersection": "Up"}}, "path": "/dev/v4l/by-path/pci-0000:02:03.0-usb-0:2:1.0-video-index0", "video_mode": {"fps": 30, "width": 640, "height": 480, "pixel_format": "kYUYV"}, "resolution": 0, "FOV": 60.8} \ No newline at end of file diff --git a/backend/settings/settings.json b/backend/settings/settings.json index 30370a80d..41fe0b582 100644 --- a/backend/settings/settings.json +++ b/backend/settings/settings.json @@ -1 +1 @@ -{"team_number": 1577, "connection_type": "DHCP", "ip": "", "gateway": "", "hostname": "Chameleon-Vision", "curr_camera": "AN-VC500 Camera", "curr_pipeline": "pipeline0"} \ No newline at end of file +{"team_number": 1567, "connection_type": "DHCP", "ip": "", "gateway": "", "hostname": "Chameleon-Vision", "curr_camera": "USB2.0 PC CAMERA", "curr_pipeline": "pipeline0"} \ No newline at end of file diff --git a/chameleon-client/src/App.vue b/chameleon-client/src/App.vue index d01c6d84c..ba7f0c132 100644 --- a/chameleon-client/src/App.vue +++ b/chameleon-client/src/App.vue @@ -76,12 +76,17 @@ }, created () { this.$options.sockets.onmessage = (data) => { - console.log(data.data); - let message = JSON.parse(data.data); - for (var prop in message){ + try{ + let message = JSON.parse(data.data); + for (var prop in message){ if(message.hasOwnProperty(prop)){ this.$store.state[prop] = message[prop]; } + console.log(data.data); + } + } + catch{ + console.log("error" + data.data) } } // console writes recived data } diff --git a/chameleon-client/src/components/CameraTab.vue b/chameleon-client/src/components/CameraTab.vue index c265dacb9..e237466ab 100644 --- a/chameleon-client/src/components/CameraTab.vue +++ b/chameleon-client/src/components/CameraTab.vue @@ -1,18 +1,95 @@ - \ No newline at end of file diff --git a/chameleon-client/src/components/InputTab.vue b/chameleon-client/src/components/InputTab.vue index 07737f056..d96692bb0 100644 --- a/chameleon-client/src/components/InputTab.vue +++ b/chameleon-client/src/components/InputTab.vue @@ -4,7 +4,6 @@ - diff --git a/chameleon-client/src/components/SystemTab.vue b/chameleon-client/src/components/SystemTab.vue index b1983d51c..c08ed1918 100644 --- a/chameleon-client/src/components/SystemTab.vue +++ b/chameleon-client/src/components/SystemTab.vue @@ -6,31 +6,31 @@

Team Number:

- + Networking
- +
-

IP:

+

IP:

- +
-

Gateway:

+

Gateway:

- +
@@ -38,7 +38,7 @@

Hostname:

- + http://Chameleon-Vision .local @@ -69,32 +69,33 @@ }, methods: { socketSendAll: function(){ - this.$socket.sendObj([ - {'team_number':this.teamNum}, - {'connection_type':this.connectionType}, - {'ip':this.ip}, - {'gateway':this.gateWay}, - {'hostname':this.hostName}]); + this.$socket.sendObj( + {'change_general_settings_values':{ + 'team_number':this.team_number, + 'connection_type':this.connection_type, + 'ip':this.ip, + 'gateway':this.gateway, + 'hostname':this.hostname}}); } }, computed: { - teamNum:{ + team_number:{ get: function(){ - return this.$store.state.teamValue; + return this.$store.state.team_number; }, set: function(value){ - this.$store.commit('teamValue',value); + this.$store.commit('team_number',value); } }, - connectionType:{ + connection_type:{ get: function(){ - return this.$store.state.connectionType; + return this.$store.state.connection_type; }, set: function(value){ - this.$store.commit('connectionType',value); + this.$store.commit('connection_type',value); } }, - IP:{ + ip:{ get: function(){ return this.$store.state.ip; }, @@ -102,20 +103,20 @@ this.$store.commit('ip',value); } }, - gateWay:{ + gateway:{ get: function(){ - return this.$store.state.gateWay; + return this.$store.state.gateway; }, set: function(value){ - this.$store.commit('gateWay',value); + this.$store.commit('gateway',value); } }, - hostName:{ + hostname:{ get: function(){ - return this.$store.state.hostName; + return this.$store.state.hostname; }, set: function(value){ - this.$store.commit('hostName',value); + this.$store.commit('hostname',value); } }, isConnection: function(){ diff --git a/chameleon-client/src/components/Vision.vue b/chameleon-client/src/components/Vision.vue index 349de6798..ab20901ab 100644 --- a/chameleon-client/src/components/Vision.vue +++ b/chameleon-client/src/components/Vision.vue @@ -59,7 +59,7 @@ }, steamAdress: { get: function(){ - return this.$store.state.streamAdress; + return "http://"+location.hostname + ":"+ this.$store.state.port +"/stream.mjpg"; } }, isBinary: { diff --git a/chameleon-client/src/components/outputTab.vue b/chameleon-client/src/components/outputTab.vue index 0f17531ef..e8701d4f6 100644 --- a/chameleon-client/src/components/outputTab.vue +++ b/chameleon-client/src/components/outputTab.vue @@ -2,7 +2,7 @@
-

calibrate crosshair

+
calibrate crosshair
@@ -34,4 +34,5 @@ import chrange from './ch-range.vue' .spacing{ margin-top: 20px; } + \ No newline at end of file diff --git a/chameleon-client/src/store.js b/chameleon-client/src/store.js index 9c9763535..29be7a60d 100644 --- a/chameleon-client/src/store.js +++ b/chameleon-client/src/store.js @@ -19,6 +19,7 @@ export const store = new Vuex.Store({ orientation:0, resolution:0, resolutionList:[], + FOV:0, //threshold hue:[0,10], saturation:[0,10], @@ -33,20 +34,20 @@ export const store = new Vuex.Store({ target_group:'Single', // target_intersection:'Up', // //Settings - teamValue:0, - connectionType:"DHCP", + team_number:0, + connection_type:"DHCP", ip:0, gateWay:0, - hostName:"", + hostname:"", //live info - streamAdress:("http://"+location.hostname + ":1181/stream.mjpg"), + port:1181, is_binary:0, //camera lists }, mutations:{ - camera (state,value){ - state['camera'] = value; + curr_camera (state,value){ + state['curr_camera'] = value; state['pipeline'] = "0"; }, pipeline: set('curr_pipeline'), @@ -62,21 +63,22 @@ export const store = new Vuex.Store({ area: set('area'), ratio: set('ratio'), extent: set('extent'), - teamValue: set('team_number'), - connectionType: set('connection_type'), + team_number: set('team_number'), + connection_type: set('connection_type'), ip: set('ip'), gateWay : set('gateway'), - hostName : set('hostname'), - streamAdress : set('streamAdress'), + hostname : set('hostname'), is_binary: set('is_binary'), cameraList : set('cameraList'), pipelineList: set('piplineList'), sort_mode: set('sort_mode'), target_group:set('target_group'), - target_intersection:set('target_intersection') + target_intersection:set('target_intersection'), + FOV:set('FOV'), + port:set('port') }, getters:{ - camera: state => state.camera, + curr_camera: state => state.curr_camera, pipeline: state => state.pipeline, brightness: state => state.brightness, exposure: state => state.exposure, @@ -90,19 +92,19 @@ export const store = new Vuex.Store({ area: state =>state.area, ratio: state =>state.ratio, extent: state =>state.extent, - teamValue: state => state.teamValue, - connectionType: state => state.connectionType, + team_number: state => state.teamValue, + connection_type: state => state.connectionType, ip: state => state.ip, gateWay: state => state.gateWay, - hostName: state => state.hostName, - streamAdress: state => state.streamAdress, + hostname: state => state.hostName, is_binary: state => state.is_binary, cameraList: state => state.cameraList, pipelineList: state => state.pipelineList, sort_mode: state => state.sort_mode, target_group: state => state.target_group, - target_intersection: state => state.target_intersection - + target_intersection: state => state.target_intersection, + FOV: state => state.FOV, + port: state => state.port }, }); \ No newline at end of file diff --git a/settings/cams/USB Camera-B4.09.24.1.json b/settings/cams/USB Camera-B4.09.24.1.json deleted file mode 100644 index ff8a54b9b..000000000 --- a/settings/cams/USB Camera-B4.09.24.1.json +++ /dev/null @@ -1 +0,0 @@ -{"pipelines": {"pipeline0": {"exposure": 50, "brightness": 50, "orientation": "Normal", "resolution": [320, 160], "hue": [0, 100], "saturation": [0, 100], "value": [0, 100], "erode": false, "dilate": false, "area": [0, 100], "ratio": [0, 20], "extent": [0, 100], "is_binary": "Normal"}}, "path": "/dev/v4l/by-path/pci-0000:02:03.0-usb-0:1:1.0-video-index0", "video_mode": {"fps": 187, "width": 320, "height": 240, "pixel_format": "kYUYV"}} \ No newline at end of file diff --git a/settings/settings.json b/settings/settings.json deleted file mode 100644 index c89e02900..000000000 --- a/settings/settings.json +++ /dev/null @@ -1 +0,0 @@ -{"team_number": 1577, "connection_type": "DHCP", "ip": "", "gateway": "", "hostname": "Chameleon-Vision", "curr_camera": "USB Camera-B4.09.24.1", "curr_pipeline": "pipeline0"} \ No newline at end of file