From 40b19caba52adbc5288b347bf323393cba9786ea Mon Sep 17 00:00:00 2001 From: aidanahram Date: Thu, 27 Jul 2023 16:25:00 -0400 Subject: [PATCH] maybe this will work?? --- bin/dashboard.dart | 4 +--- lib/src/camera.dart | 45 ++++++++++++++++++++++++++++++++++++++++ lib/src/collection.dart | 46 +++++++++++++++++++---------------------- lib/src/constants.dart | 26 +++++++++++++---------- lib/src/udp.dart | 15 +++++++++++++- 5 files changed, 96 insertions(+), 40 deletions(-) diff --git a/bin/dashboard.dart b/bin/dashboard.dart index b2e6ec5..65c19df 100644 --- a/bin/dashboard.dart +++ b/bin/dashboard.dart @@ -1,5 +1,3 @@ -import "dart:io"; - import "package:burt_network/burt_network.dart"; import "package:burt_network/generated.dart"; @@ -34,4 +32,4 @@ class VideoServer extends ProtoSocket{ // TODO: implement updateSettings } } -*/ \ No newline at end of file +*/ diff --git a/lib/src/camera.dart b/lib/src/camera.dart index e69de29..c02644a 100644 --- a/lib/src/camera.dart +++ b/lib/src/camera.dart @@ -0,0 +1,45 @@ +import "package:burt_network/burt_network.dart"; +import "package:opencv_ffi/opencv_ffi.dart"; +import "dart:async"; +import "collection.dart"; + +class CameraManager { + late final Camera camera; + late final CameraDetails details; + Timer? timer; + + CameraManager({required this.camera, required this.details}){ + init(); + } + + void init(){ // init the timer + timer = Timer.periodic(Duration(milliseconds: 1000 ~/ details.fps), (runner) { + if(!camera.isOpened){ + runner.cancel(); + details.mergeFromMessage(CameraDetails(status: CameraStatus.CAMERA_DISCONNECTED)); + } + sendFrame(); + }); + } + + void dispose(){ // dispose the camera and the timer + camera.dispose(); + timer?.cancel(); + } + + void updateDetails({required CameraDetails details}){ // reset the timer for FPS if needed, change resolution, enable or disable + details.mergeFromMessage(details); + } + + void sendFrame(){ // run this with the timer. Read frame, send to dashboard, handle errors + final frame = camera.getJpg(); + if(frame == null){ + collection.videoServer.sendMessage(VideoData(details: CameraDetails(name: CameraName.ROVER_FRONT, status: CameraStatus.CAMERA_NOT_RESPONDING))); + } else { + collection.videoServer.sendMessage(VideoData(frame: frame.data, details: CameraDetails(name: CameraName.ROVER_FRONT, status: CameraStatus.CAMERA_ENABLED))); + frame.dispose(); + } + } + + bool get isOpened => camera.isOpened; +} diff --git a/lib/src/collection.dart b/lib/src/collection.dart index 595d05a..4956ffc 100644 --- a/lib/src/collection.dart +++ b/lib/src/collection.dart @@ -1,43 +1,39 @@ // ignore_for_file: avoid_print +import "dart:io"; +import "dart:async"; import "package:burt_network/burt_network.dart"; import "package:opencv_ffi/opencv_ffi.dart"; import "udp.dart"; -import "dart:async"; +import "constants.dart"; +import "camera.dart"; + + + class VideoCollection{ /// Holds a list of available cameras - final cameras = []; + Map cameras = {}; int cameraCount = 0; final videoServer = VideoServer(port: 8002); - void addCamera(int index){ - final camera = Camera.fromIndex(index); - cameras.add(camera); - cameraCount++; - } - - void runCameras(){ - Timer.periodic(const Duration(milliseconds: 100), (run) { - print("There are ${cameraCount + 1} running"); - for(int i = 0; i < cameraCount; i++){ - //cameras[i].showFrame(); - final frame = cameras[i].getJpg(); - if(frame == null){ - videoServer.sendMessage(VideoData(details: CameraDetails(name: CameraName.ROVER_FRONT, status: CameraStatus.CAMERA_NOT_RESPONDING))); - } else { - videoServer.sendMessage(VideoData(frame: frame.data, details: CameraDetails(name: CameraName.ROVER_FRONT, status: CameraStatus.CAMERA_ENABLED))); - frame.dispose(); - } - } - }); - } - Future init() async{ await videoServer.init(); print("Starting Cameras..."); - runCameras(); + connectCameras(); + } + + void connectCameras(){ + final cameraDetails = CameraDetails(resolutionWidth: 300, resolutionHeight: 300, quality: 50, fps: 24, status: CameraStatus.CAMERA_ENABLED); + for(int i = 0; i < cameraNames.length; ++i){ + cameraDetails.mergeFromMessage(CameraDetails(name: cameraIndexes.values.elementAt(i))); + if(Platform.isWindows){ + cameras[cameraIndexes.keys.elementAt(i)] = CameraManager(camera: Camera.fromIndex(int.parse(cameraIndexes.keys.elementAt(i))), details: cameraDetails); + } else { + cameras[cameraNames.keys.elementAt(i)] = CameraManager(camera: Camera.fromName(cameraNames.keys.elementAt(i)), details: cameraDetails); + } + } } } diff --git a/lib/src/constants.dart b/lib/src/constants.dart index 08e2302..3165af7 100644 --- a/lib/src/constants.dart +++ b/lib/src/constants.dart @@ -1,17 +1,21 @@ import "package:burt_network/burt_network.dart"; +// These list maps OpenCV IDs (index) to [CameraName]s. +// +// This is HIGHLY dependent on the EXACT order of the USB ports. Map cameraNames = { "/dev/realsense_rgb": CameraName.ROVER_FRONT, - "/dev/realsense_depth": CameraName.AUTONOMY_DEPTH, - "/dev/subsystem1": CameraName.SUBSYSTEM1, - "/dev/subsystem2": CameraName.SUBSYSTEM2, - "/dev/subsystem3": CameraName.SUBSYSTEM3, + "/dev/realsense_depth": CameraName.AUTONOMY_DEPTH, + "/dev/subsystem1": CameraName.SUBSYSTEM1, + "/dev/subsystem2": CameraName.SUBSYSTEM2, + "/dev/subsystem3": CameraName.SUBSYSTEM3, }; -Map cameraIndexesWindows = { - 0: CameraName.ROVER_FRONT, - 1: CameraName.AUTONOMY_DEPTH, - 2: CameraName.SUBSYSTEM1, - 3: CameraName.SUBSYSTEM2, - 4: CameraName.SUBSYSTEM3, -}; \ No newline at end of file +// WINDOWS +Map cameraIndexes = { + "0": CameraName.ROVER_FRONT, + "1": CameraName.AUTONOMY_DEPTH, + "2": CameraName.SUBSYSTEM1, + "3": CameraName.SUBSYSTEM2, + "4": CameraName.SUBSYSTEM3, +}; diff --git a/lib/src/udp.dart b/lib/src/udp.dart index ad6acd0..4fd9f74 100644 --- a/lib/src/udp.dart +++ b/lib/src/udp.dart @@ -9,7 +9,20 @@ class VideoServer extends ServerSocket{ if(wrapper.name != VideoCommand().messageName){ // Can ignore message if not a video message return; } + // Return the message to tell dashboard the message was received + sendMessage(wrapper); final command = VideoCommand.fromBuffer(wrapper.data); - //command.id + // Send LOADING before making any changes + sendMessage(VideoData(id: command.id, details: CameraDetails(status: CameraStatus.CAMERA_LOADING))); + // Change the settings + if(collection.cameras[command.id]!.isOpened){ + collection.cameras[command.id]!.updateDetails(details: command.details); + } + } + + @override + void sendMessage(Message message, {SocketInfo? socketOverride}) { + if(!isConnected) return; + super.sendMessage(message); } }