diff --git a/Main/src/main/java/com/chameleonvision/Main.java b/Main/src/main/java/com/chameleonvision/Main.java index 6941cb7ea..7e2046a19 100644 --- a/Main/src/main/java/com/chameleonvision/Main.java +++ b/Main/src/main/java/com/chameleonvision/Main.java @@ -145,7 +145,7 @@ public class Main { if (ntClientModeServer != null) { NetworkTableInstance.getDefault().startClient(ntClientModeServer); } else { - NetworkTableInstance.getDefault().startClientTeam(SettingsManager.GeneralSettings.teamNumber); + NetworkTableInstance.getDefault().startClientTeam(SettingsManager.generalSettings.teamNumber); } } diff --git a/Main/src/main/java/com/chameleonvision/network/NetworkManager.java b/Main/src/main/java/com/chameleonvision/network/NetworkManager.java index ad8e1cc15..a60db1c15 100644 --- a/Main/src/main/java/com/chameleonvision/network/NetworkManager.java +++ b/Main/src/main/java/com/chameleonvision/network/NetworkManager.java @@ -43,7 +43,7 @@ public class NetworkManager { e.printStackTrace(); } - var teamBytes = NetworkManager.GetTeamNumberIPBytes(SettingsManager.GeneralSettings.teamNumber); + var teamBytes = NetworkManager.GetTeamNumberIPBytes(SettingsManager.generalSettings.teamNumber); if (interfaces.size() > 0) { for (var inetface : interfaces) { @@ -85,7 +85,7 @@ public class NetworkManager { return true; } - var genSettings = SettingsManager.GeneralSettings; + var genSettings = SettingsManager.generalSettings; boolean isStatic = genSettings.connectionType.equals(NetworkIPMode.STATIC); if (isStatic) { diff --git a/Main/src/main/java/com/chameleonvision/settings/SettingsManager.java b/Main/src/main/java/com/chameleonvision/settings/SettingsManager.java index d26444630..52fde8312 100644 --- a/Main/src/main/java/com/chameleonvision/settings/SettingsManager.java +++ b/Main/src/main/java/com/chameleonvision/settings/SettingsManager.java @@ -14,36 +14,36 @@ import java.nio.file.Paths; public class SettingsManager { public static final Path SettingsPath = Paths.get(System.getProperty("user.dir"), "settings"); - public static com.chameleonvision.settings.GeneralSettings GeneralSettings; + public static GeneralSettings generalSettings; private SettingsManager() {} public static void initialize() { initGeneralSettings(); var allCameras = CameraManager.getAllCamerasByName(); - if (!allCameras.containsKey(GeneralSettings.currentCamera) && allCameras.size() > 0) { + if (!allCameras.containsKey(generalSettings.currentCamera) && allCameras.size() > 0) { var cam = allCameras.entrySet().stream().findFirst().get().getValue(); - GeneralSettings.currentCamera = cam.name; - GeneralSettings.currentPipeline = cam.getCurrentPipelineIndex(); + generalSettings.currentCamera = cam.name; + generalSettings.currentPipeline = cam.getCurrentPipelineIndex(); } } private static void initGeneralSettings() { FileHelper.CheckPath(SettingsPath); try { - GeneralSettings = new Gson().fromJson(new FileReader(Paths.get(SettingsPath.toString(), "settings.json").toString()), com.chameleonvision.settings.GeneralSettings.class); + generalSettings = new Gson().fromJson(new FileReader(Paths.get(SettingsPath.toString(), "settings.json").toString()), com.chameleonvision.settings.GeneralSettings.class); } catch (FileNotFoundException e) { - GeneralSettings = new GeneralSettings(); + generalSettings = new GeneralSettings(); } } public static void updateCameraSetting(String cameraName, int pipelineNumber) { - GeneralSettings.currentCamera = cameraName; - GeneralSettings.currentPipeline = pipelineNumber; + generalSettings.currentCamera = cameraName; + generalSettings.currentPipeline = pipelineNumber; } public static void updatePipelineSetting(int pipelineNumber) { - GeneralSettings.currentPipeline = pipelineNumber; + generalSettings.currentPipeline = pipelineNumber; } public static void saveSettings() { @@ -55,7 +55,7 @@ public class SettingsManager { try { Gson gson = new GsonBuilder().setPrettyPrinting().create(); FileWriter writer = new FileWriter(Paths.get(SettingsPath.toString(), "settings.json").toString()); - gson.toJson(GeneralSettings, writer); + gson.toJson(generalSettings, writer); writer.flush(); writer.close(); } catch (IOException e) { diff --git a/Main/src/main/java/com/chameleonvision/vision/camera/CameraDeserializer.java b/Main/src/main/java/com/chameleonvision/vision/camera/CameraDeserializer.java index 88152ca3e..50bf15ecd 100644 --- a/Main/src/main/java/com/chameleonvision/vision/camera/CameraDeserializer.java +++ b/Main/src/main/java/com/chameleonvision/vision/camera/CameraDeserializer.java @@ -4,19 +4,16 @@ import com.chameleonvision.vision.Pipeline; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.type.MapType; -import com.fasterxml.jackson.databind.type.ArrayType; import com.fasterxml.jackson.databind.type.TypeFactory; import com.google.gson.*; import java.lang.reflect.Type; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -public class CameraDeserializer implements JsonDeserializer { +public class CameraDeserializer implements JsonDeserializer { @Override - public Camera deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException { + public USBCamera deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException { try { var jsonObj = jsonElement.getAsJsonObject(); var camFOV = jsonObj.get("FOV").getAsDouble(); @@ -32,8 +29,8 @@ public class CameraDeserializer implements JsonDeserializer { // always null-check new features boolean isDriver = isDriverObj != null && isDriverObj.getAsBoolean(); - int driverExposure = driverExposureObj == null ? Camera.DEFAULT_EXPOSURE : driverExposureObj.getAsInt(); - int driverBrightness = driverBrightnessObj == null ? Camera.DEFAULT_BRIGHTNESS : driverBrightnessObj.getAsInt(); + int driverExposure = driverExposureObj == null ? USBCamera.DEFAULT_EXPOSURE : driverExposureObj.getAsInt(); + int driverBrightness = driverBrightnessObj == null ? USBCamera.DEFAULT_BRIGHTNESS : driverBrightnessObj.getAsInt(); StreamDivisor divisor = divisorObj == null ? StreamDivisor.none : StreamDivisor.values()[divisorObj.getAsInt()]; var pipelines = jsonObj.get("pipelines"); @@ -47,7 +44,7 @@ public class CameraDeserializer implements JsonDeserializer { e.printStackTrace(); } - var newCamera = actualPipelines != null ? new Camera(camName, camFOV, actualPipelines, videoModeIndex, divisor, isDriver) : new Camera(camName, camFOV, videoModeIndex, divisor, isDriver); + var newCamera = actualPipelines != null ? new USBCamera(camName, camFOV, actualPipelines, videoModeIndex, divisor, isDriver) : new USBCamera(camName, camFOV, videoModeIndex, divisor, isDriver); newCamera.setNickname(camNickname != null ? camNickname : ""); newCamera.setDriverExposure(driverExposure); newCamera.setDriverBrightness(driverBrightness); diff --git a/Main/src/main/java/com/chameleonvision/vision/camera/CameraManager.java b/Main/src/main/java/com/chameleonvision/vision/camera/CameraManager.java index 1fcdd9f99..a4855feec 100644 --- a/Main/src/main/java/com/chameleonvision/vision/camera/CameraManager.java +++ b/Main/src/main/java/com/chameleonvision/vision/camera/CameraManager.java @@ -1,9 +1,9 @@ package com.chameleonvision.vision.camera; -import com.chameleonvision.settings.GeneralSettings; import com.chameleonvision.util.FileHelper; import com.chameleonvision.settings.SettingsManager; import com.chameleonvision.vision.Pipeline; +import com.chameleonvision.vision.process.USBCameraProcess; import com.chameleonvision.vision.process.VisionProcess; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -21,10 +21,10 @@ public class CameraManager { private static final Path CamConfigPath = Paths.get(SettingsManager.SettingsPath.toString(), "cameras"); - private static LinkedHashMap AllCamerasByName = new LinkedHashMap<>(); - public static HashMap AllVisionProcessesByName = new HashMap<>(); + private static LinkedHashMap allCamerasByName = new LinkedHashMap<>(); + public static HashMap allVisionProcessesByName = new HashMap<>(); - static HashMap AllUsbCameraInfosByName = new HashMap<>() {{ + static HashMap allUsbCameraInfosByName = new HashMap<>() {{ var suffix = 0; for (var info : UsbCamera.enumerateUsbCameras()) { var cap = new VideoCapture(info.dev); @@ -40,31 +40,31 @@ public class CameraManager { } }}; - public static HashMap getAllCamerasByName() { - return AllCamerasByName; + public static HashMap getAllCamerasByName() { + return allCamerasByName; } public static List getAllCameraByNickname(){ var cameras = getAllCamerasByName(); - return cameras.values().stream().map(Camera::getNickname).collect(Collectors.toList()); + return cameras.values().stream().map(USBCamera::getNickname).collect(Collectors.toList()); } public static boolean initializeCameras() { - if (AllUsbCameraInfosByName.size() == 0) return false; + if (allUsbCameraInfosByName.size() == 0) return false; FileHelper.CheckPath(CamConfigPath); - AllUsbCameraInfosByName.forEach((key, value) -> { + allUsbCameraInfosByName.forEach((key, value) -> { var camPath = Paths.get(CamConfigPath.toString(), String.format("%s.json", key)); File camJsonFile = new File(camPath.toString()); if (camJsonFile.exists() && camJsonFile.length() != 0) { try { - Gson gson = new GsonBuilder().registerTypeAdapter(Camera.class, new CameraDeserializer()).create(); + Gson gson = new GsonBuilder().registerTypeAdapter(USBCamera.class, new CameraDeserializer()).create(); var camJsonFileReader = new FileReader(camPath.toString()); - var gsonRead = gson.fromJson(camJsonFileReader, Camera.class); - AllCamerasByName.put(key, gsonRead); + var gsonRead = gson.fromJson(camJsonFileReader, USBCamera.class); + allCamerasByName.put(key, gsonRead); } catch (FileNotFoundException ex) { ex.printStackTrace(); } } else { - if (!addCamera(new Camera(key), key)) { + if (!addCamera(new USBCamera(key), key)) { System.err.println("Failed to add camera! Already exists!"); } } @@ -73,39 +73,39 @@ public class CameraManager { } public static void initializeThreads(){ - AllCamerasByName.forEach((key, value) -> { - VisionProcess visionProcess = new VisionProcess(value); - AllVisionProcessesByName.put(key, visionProcess); + allCamerasByName.forEach((name, camera) -> { + VisionProcess visionProcess = new VisionProcess(new USBCameraProcess(camera)); + allVisionProcessesByName.put(name, visionProcess); new Thread(visionProcess).start(); }); } - private static boolean addCamera(Camera camera, String cameraName) { - if (AllCamerasByName.containsKey(cameraName)) return false; - camera.addPipeline(); - AllCamerasByName.put(cameraName, camera); + private static boolean addCamera(USBCamera USBCamera, String cameraName) { + if (allCamerasByName.containsKey(cameraName)) return false; + USBCamera.addPipeline(); + allCamerasByName.put(cameraName, USBCamera); return true; } - private static Camera getCamera(String cameraName) { - return AllCamerasByName.get(cameraName); + private static USBCamera getCamera(String cameraName) { + return allCamerasByName.get(cameraName); } - public static Camera getCameraByIndex(int index) { - return AllCamerasByName.get( (AllCamerasByName.keySet().toArray())[ index ] ); + public static USBCamera getCameraByIndex(int index) { + return allCamerasByName.get( (allCamerasByName.keySet().toArray())[ index ] ); } - public static Camera getCurrentCamera() throws CameraException { - if (AllCamerasByName.size() == 0) throw new CameraException(CameraException.CameraExceptionType.NO_CAMERA); - var curCam = AllCamerasByName.get(SettingsManager.GeneralSettings.currentCamera); + public static USBCamera getCurrentCamera() throws CameraException { + if (allCamerasByName.size() == 0) throw new CameraException(CameraException.CameraExceptionType.NO_CAMERA); + var curCam = allCamerasByName.get(SettingsManager.generalSettings.currentCamera); if (curCam == null) throw new CameraException(CameraException.CameraExceptionType.BAD_CAMERA); return curCam; } public static Integer getCurrentCameraIndex() throws CameraException { - if (AllCamerasByName.size() == 0) throw new CameraException(CameraException.CameraExceptionType.NO_CAMERA); - List arr = new ArrayList<>(AllCamerasByName.keySet()); - for (var i = 0; i < AllCamerasByName.size(); i++){ - if (SettingsManager.GeneralSettings.currentCamera.equals(arr.get(i))){ + if (allCamerasByName.size() == 0) throw new CameraException(CameraException.CameraExceptionType.NO_CAMERA); + List arr = new ArrayList<>(allCamerasByName.keySet()); + for (var i = 0; i < allCamerasByName.size(); i++){ + if (SettingsManager.generalSettings.currentCamera.equals(arr.get(i))){ return i; } } @@ -113,13 +113,13 @@ public class CameraManager { } public static void setCurrentCamera(String cameraName) throws CameraException { - if (!AllCamerasByName.containsKey(cameraName)) + if (!allCamerasByName.containsKey(cameraName)) throw new CameraException(CameraException.CameraExceptionType.BAD_CAMERA); - SettingsManager.GeneralSettings.currentCamera = cameraName; + SettingsManager.generalSettings.currentCamera = cameraName; SettingsManager.updateCameraSetting(cameraName, getCurrentCamera().getCurrentPipelineIndex()); } public static void setCurrentCamera(int cameraIndex) throws CameraException { - List s = new ArrayList(AllCamerasByName.keySet()); + List s = new ArrayList(allCamerasByName.keySet()); setCurrentCamera(s.get(cameraIndex)); } @@ -136,20 +136,20 @@ public class CameraManager { } public static VisionProcess getVisionProcessByCameraName(String cameraName) { - return AllVisionProcessesByName.get(cameraName); + return allVisionProcessesByName.get(cameraName); } public static VisionProcess getCurrentVisionProcess() throws CameraException { - if (!SettingsManager.GeneralSettings.currentCamera.equals("")){ - return AllVisionProcessesByName.get(SettingsManager.GeneralSettings.currentCamera); + if (!SettingsManager.generalSettings.currentCamera.equals("")){ + return allVisionProcessesByName.get(SettingsManager.generalSettings.currentCamera); } throw new CameraException(CameraException.CameraExceptionType.NO_CAMERA); } public static void saveCameras() { - for (var entry : AllCamerasByName.entrySet()) { + for (var entry : allCamerasByName.entrySet()) { try { - Gson gson = new GsonBuilder().setPrettyPrinting().registerTypeAdapter(Camera.class, new CameraSerializer()).create(); + Gson gson = new GsonBuilder().setPrettyPrinting().registerTypeAdapter(USBCamera.class, new CameraSerializer()).create(); FileWriter writer = new FileWriter(Paths.get(CamConfigPath.toString(), String.format("%s.json", entry.getKey())).toString()); gson.toJson(entry.getValue(), writer); writer.flush(); diff --git a/Main/src/main/java/com/chameleonvision/vision/camera/CameraSerializer.java b/Main/src/main/java/com/chameleonvision/vision/camera/CameraSerializer.java index 313959ddb..8d590dcff 100644 --- a/Main/src/main/java/com/chameleonvision/vision/camera/CameraSerializer.java +++ b/Main/src/main/java/com/chameleonvision/vision/camera/CameraSerializer.java @@ -3,22 +3,22 @@ import com.google.gson.*; import java.lang.reflect.Type; -public class CameraSerializer implements JsonSerializer { +public class CameraSerializer implements JsonSerializer { @Override - public JsonElement serialize(Camera camera, Type type, JsonSerializationContext context) { + public JsonElement serialize(USBCamera USBCamera, Type type, JsonSerializationContext context) { JsonObject obj = new JsonObject(); - obj.addProperty("FOV", camera.getFOV()); - obj.addProperty("path", camera.path); - obj.addProperty("name", camera.name); - obj.addProperty("nickname", camera.getNickname()); - obj.addProperty("streamDivisor", camera.getStreamDivisor().ordinal()); - var pipelines = context.serialize(camera.getPipelines()); + obj.addProperty("FOV", USBCamera.getFOV()); + obj.addProperty("path", USBCamera.path); + obj.addProperty("name", USBCamera.name); + obj.addProperty("nickname", USBCamera.getNickname()); + obj.addProperty("streamDivisor", USBCamera.getStreamDivisor().ordinal()); + var pipelines = context.serialize(USBCamera.getPipelines()); obj.add("pipelines", pipelines); - obj.addProperty("resolution", camera.getVideoModeIndex()); - obj.add("camVideoMode", context.serialize(camera.getVideoMode())); - obj.add("isDriver",context.serialize(camera.getDriverMode())); - obj.add("driverExposure",context.serialize(camera.getDriverExposure())); - obj.add("driverBrightness",context.serialize(camera.getDriverBrightness())); + obj.addProperty("resolution", USBCamera.getVideoModeIndex()); + obj.add("camVideoMode", context.serialize(USBCamera.getVideoMode())); + obj.add("isDriver",context.serialize(USBCamera.getDriverMode())); + obj.add("driverExposure",context.serialize(USBCamera.getDriverExposure())); + obj.add("driverBrightness",context.serialize(USBCamera.getDriverBrightness())); return obj; } } diff --git a/Main/src/main/java/com/chameleonvision/vision/camera/CameraValues.java b/Main/src/main/java/com/chameleonvision/vision/camera/CameraValues.java index f429b98d2..50dcde294 100644 --- a/Main/src/main/java/com/chameleonvision/vision/camera/CameraValues.java +++ b/Main/src/main/java/com/chameleonvision/vision/camera/CameraValues.java @@ -21,8 +21,8 @@ public class CameraValues { public final double HorizontalFocalLength; public final double VerticalFocalLength; - public CameraValues(Camera camera) { - this(camera.getVideoMode().width, camera.getVideoMode().height, camera.getFOV()); + public CameraValues(USBCamera USBCamera) { + this(USBCamera.getVideoMode().width, USBCamera.getVideoMode().height, USBCamera.getFOV()); } public CameraValues(int imageWidth, int imageHeight, double fov) { diff --git a/Main/src/main/java/com/chameleonvision/vision/camera/Camera.java b/Main/src/main/java/com/chameleonvision/vision/camera/USBCamera.java similarity index 89% rename from Main/src/main/java/com/chameleonvision/vision/camera/Camera.java rename to Main/src/main/java/com/chameleonvision/vision/camera/USBCamera.java index a1ecd7f2a..193947b03 100644 --- a/Main/src/main/java/com/chameleonvision/vision/camera/Camera.java +++ b/Main/src/main/java/com/chameleonvision/vision/camera/USBCamera.java @@ -13,7 +13,7 @@ import java.util.*; import java.util.stream.Collectors; import java.util.stream.IntStream; -public class Camera { +public class USBCamera { private static final double DEFAULT_FOV = 60.8; private static final StreamDivisor DEFAULT_STREAMDIVISOR = StreamDivisor.none; @@ -49,31 +49,31 @@ public class Camera { private int driverBrightness; private boolean isDriver; - public Camera(String cameraName) { + public USBCamera(String cameraName) { this(cameraName, DEFAULT_FOV); } - public Camera(String cameraName, double fov) { - this(cameraName, CameraManager.AllUsbCameraInfosByName.get(cameraName), fov); + public USBCamera(String cameraName, double fov) { + this(cameraName, CameraManager.allUsbCameraInfosByName.get(cameraName), fov); } - public Camera(String cameraName, UsbCameraInfo usbCameraInfo, double fov) { + public USBCamera(String cameraName, UsbCameraInfo usbCameraInfo, double fov) { this(cameraName, usbCameraInfo, fov, DEFAULT_STREAMDIVISOR); } - public Camera(String cameraName, UsbCameraInfo usbCamInfo, double fov, StreamDivisor divisor) { + public USBCamera(String cameraName, UsbCameraInfo usbCamInfo, double fov, StreamDivisor divisor) { this(cameraName, usbCamInfo, fov, new ArrayList<>(), 0, divisor, false); } - public Camera(String cameraName, double fov, List pipelines, int videoModeIndex, StreamDivisor divisor, boolean isDriver) { - this(cameraName, CameraManager.AllUsbCameraInfosByName.get(cameraName), fov, pipelines, videoModeIndex, divisor, isDriver); + public USBCamera(String cameraName, double fov, List pipelines, int videoModeIndex, StreamDivisor divisor, boolean isDriver) { + this(cameraName, CameraManager.allUsbCameraInfosByName.get(cameraName), fov, pipelines, videoModeIndex, divisor, isDriver); } - public Camera(String cameraName, double fov, int videoModeIndex, StreamDivisor divisor, boolean isDriver) { + public USBCamera(String cameraName, double fov, int videoModeIndex, StreamDivisor divisor, boolean isDriver) { this(cameraName, fov, new ArrayList<>(), videoModeIndex, divisor, isDriver); } - public Camera(String cameraName, UsbCameraInfo usbCamInfo, double fov, List pipelines, int videoModeIndex, StreamDivisor divisor, boolean isDriver) { + public USBCamera(String cameraName, UsbCameraInfo usbCamInfo, double fov, List pipelines, int videoModeIndex, StreamDivisor divisor, boolean isDriver) { FOV = fov; name = cameraName; @@ -99,13 +99,13 @@ public class Camera { } } var initTimeMs = (System.nanoTime() - initTimeout) / 1e6; - System.out.printf("Camera initialized in %.2fms\n", initTimeMs); + System.out.printf("USBCamera initialized in %.2fms\n", initTimeMs); } var trueVideoModes = UsbCam.enumerateVideoModes(); availableVideoModes = Arrays.stream(trueVideoModes).filter(v -> v.fps >= MINIMUM_FPS && v.width >= MINIMUM_WIDTH && v.height >= MINIMUM_HEIGHT && ALLOWED_PIXEL_FORMATS.contains(v.pixelFormat)).toArray(VideoMode[]::new); if (availableVideoModes.length == 0) { - System.err.println("Camera not supported!"); + System.err.println("USBCamera not supported!"); throw new RuntimeException(new CameraException(CameraException.CameraExceptionType.BAD_CAMERA)); } if (videoModeIndex <= availableVideoModes.length - 1) { @@ -283,7 +283,7 @@ public class Camera { try { UsbCam.setExposureManual(exposure); } catch (VideoException e) { - System.err.println("Camera Does not support exposure change"); + System.err.println("USBCamera Does not support exposure change"); } } @@ -311,9 +311,9 @@ public class Camera { //Deletes old camera nt table NetworkTableInstance.getDefault().getTable("/chameleon-vision/" + this.nickname).getInstance().deleteAllEntries(); nickname = newNickname; - if (CameraManager.AllVisionProcessesByName.containsKey(this.name)) { + if (CameraManager.allVisionProcessesByName.containsKey(this.name)) { NetworkTable newNT = NetworkTableInstance.getDefault().getTable("/chameleon-vision/" + this.nickname); - CameraManager.AllVisionProcessesByName.get(this.name).resetNT(newNT); + CameraManager.allVisionProcessesByName.get(this.name).resetNT(newNT); } } diff --git a/Main/src/main/java/com/chameleonvision/vision/process/CameraProcess.java b/Main/src/main/java/com/chameleonvision/vision/process/CameraProcess.java index 0f9405cf3..398274a1a 100644 --- a/Main/src/main/java/com/chameleonvision/vision/process/CameraProcess.java +++ b/Main/src/main/java/com/chameleonvision/vision/process/CameraProcess.java @@ -1,77 +1,31 @@ package com.chameleonvision.vision.process; -import com.chameleonvision.vision.camera.Camera; -import com.chameleonvision.vision.camera.StreamDivisor; -import org.opencv.core.CvType; +import com.chameleonvision.vision.Pipeline; +import com.chameleonvision.vision.camera.CamVideoMode; +import com.chameleonvision.vision.camera.CameraValues; import org.opencv.core.Mat; -import org.opencv.core.Size; -import org.opencv.imgproc.Imgproc; -public class CameraProcess implements Runnable { +import java.util.List; - private final Camera camera; - private final int maxFPS; - private final Object inputFrameLock = new Object(); - private final Object outputFrameLock = new Object(); - private Mat inputFrame; - private Mat outputFrame; - private long timestamp; - private StreamDivisor divisor; +public interface CameraProcess extends Runnable { - CameraProcess(Camera camera) { - this.camera = camera; - maxFPS = camera.getVideoMode().fps; - updateFrameSize(); - } + long getLatestFrame(Mat outputFrame); - public void updateFrameSize() { - var camVals = camera.getCamVals(); - divisor = camera.getStreamDivisor(); - var newWidth = camVals.ImageWidth / divisor.value; - var newHeight = camVals.ImageHeight / divisor.value; - synchronized (inputFrameLock) { - inputFrame = new Mat(newWidth, newHeight, CvType.CV_8UC3); - } - synchronized (outputFrameLock) { - outputFrame = new Mat(newWidth, newHeight, CvType.CV_8UC3); - } - } + void updateFrame(Mat inputFrame); - void updateFrame(Mat inputFrame) { - synchronized (inputFrameLock) { - inputFrame.copyTo(this.inputFrame); - } - } + void updateFrameSize(); - long getLatestFrame(Mat outputFrame) { - synchronized (outputFrameLock) { - this.outputFrame.copyTo(outputFrame); - return timestamp; - } - } + String getCamName(); + CameraValues getCamVals(); + boolean getDriverMode(); + void setDriverMode(boolean isDriverMode); + List getPipelines(); + Pipeline getCurrentPipeline(); + int getCurrentPipelineIndex(); + void setExposure(int exposure); + void setBrightness(int brightness); + CamVideoMode getVideoMode(); + String getNickname(); + void setCurrentPipelineIndex(int ntPipelineIndex); - @Override - public void run() { - while (!Thread.interrupted()) { - synchronized (outputFrameLock) { - timestamp = camera.grabFrame(outputFrame); - } - synchronized (inputFrameLock) { - if (divisor.value != 1) { - var camVals = camera.getCamVals(); - var newWidth = camVals.ImageWidth / divisor.value; - var newHeight = camVals.ImageHeight / divisor.value; - Size newSize = new Size(newWidth, newHeight); - Imgproc.resize(inputFrame, inputFrame, newSize); - } - camera.putFrame(inputFrame); - } - var msToWait = (long) 1000 / maxFPS; - try { - Thread.sleep(msToWait); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } } diff --git a/Main/src/main/java/com/chameleonvision/vision/process/USBCameraProcess.java b/Main/src/main/java/com/chameleonvision/vision/process/USBCameraProcess.java new file mode 100644 index 000000000..3491c893a --- /dev/null +++ b/Main/src/main/java/com/chameleonvision/vision/process/USBCameraProcess.java @@ -0,0 +1,144 @@ +package com.chameleonvision.vision.process; + +import com.chameleonvision.vision.Pipeline; +import com.chameleonvision.vision.camera.CamVideoMode; +import com.chameleonvision.vision.camera.CameraValues; +import com.chameleonvision.vision.camera.USBCamera; +import com.chameleonvision.vision.camera.StreamDivisor; +import org.opencv.core.CvType; +import org.opencv.core.Mat; +import org.opencv.core.Size; +import org.opencv.imgproc.Imgproc; + +import java.util.List; + +public class USBCameraProcess implements CameraProcess { + + private final USBCamera usbCamera; + private final int maxFPS; + private final Object inputFrameLock = new Object(); + private final Object outputFrameLock = new Object(); + private Mat inputFrame; + private Mat outputFrame; + private long timestamp; + private StreamDivisor divisor; + + public USBCameraProcess(USBCamera usbCamera) { + this.usbCamera = usbCamera; + maxFPS = usbCamera.getVideoMode().fps; + updateFrameSize(); + } + + public void updateFrameSize() { + var camVals = usbCamera.getCamVals(); + divisor = usbCamera.getStreamDivisor(); + var newWidth = camVals.ImageWidth / divisor.value; + var newHeight = camVals.ImageHeight / divisor.value; + synchronized (inputFrameLock) { + inputFrame = new Mat(newWidth, newHeight, CvType.CV_8UC3); + } + synchronized (outputFrameLock) { + outputFrame = new Mat(newWidth, newHeight, CvType.CV_8UC3); + } + } + + public void updateFrame(Mat inputFrame) { + synchronized (inputFrameLock) { + inputFrame.copyTo(this.inputFrame); + } + } + + public long getLatestFrame(Mat outputFrame) { + synchronized (outputFrameLock) { + this.outputFrame.copyTo(outputFrame); + return timestamp; + } + } + + @Override + public void run() { + while (!Thread.interrupted()) { + synchronized (outputFrameLock) { + timestamp = usbCamera.grabFrame(outputFrame); + } + synchronized (inputFrameLock) { + if (divisor.value != 1) { + var camVals = usbCamera.getCamVals(); + var newWidth = camVals.ImageWidth / divisor.value; + var newHeight = camVals.ImageHeight / divisor.value; + Size newSize = new Size(newWidth, newHeight); + Imgproc.resize(inputFrame, inputFrame, newSize); + } + usbCamera.putFrame(inputFrame); + } + var msToWait = (long) 1000 / maxFPS; + try { + Thread.sleep(msToWait); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + // USBCamera stuff + + @Override + public String getCamName() { + return usbCamera.name; + } + + @Override + public CameraValues getCamVals() { + return usbCamera.getCamVals(); + } + + @Override + public boolean getDriverMode() { + return usbCamera.getDriverMode(); + } + + @Override + public void setDriverMode(boolean isDriverMode) { + usbCamera.setDriverMode(isDriverMode); + } + + @Override + public List getPipelines() { + return usbCamera.getPipelines(); + } + + @Override + public Pipeline getCurrentPipeline() { + return usbCamera.getCurrentPipeline(); + } + + @Override + public int getCurrentPipelineIndex() { + return usbCamera.getCurrentPipelineIndex(); + } + + @Override + public void setExposure(int exposure) { + usbCamera.setExposure(exposure); + } + + @Override + public void setBrightness(int brightness) { + usbCamera.setBrightness(brightness); + } + + @Override + public CamVideoMode getVideoMode() { + return usbCamera.getVideoMode(); + } + + @Override + public String getNickname() { + return usbCamera.getNickname(); + } + + @Override + public void setCurrentPipelineIndex(int wantedIndex) { + usbCamera.setCurrentPipelineIndex(wantedIndex); + } +} diff --git a/Main/src/main/java/com/chameleonvision/vision/process/VisionProcess.java b/Main/src/main/java/com/chameleonvision/vision/process/VisionProcess.java index 6e00b6477..ce7ac6e04 100644 --- a/Main/src/main/java/com/chameleonvision/vision/process/VisionProcess.java +++ b/Main/src/main/java/com/chameleonvision/vision/process/VisionProcess.java @@ -1,10 +1,8 @@ package com.chameleonvision.vision.process; import com.chameleonvision.settings.SettingsManager; -import com.chameleonvision.vision.CalibrationMode; import com.chameleonvision.vision.Orientation; import com.chameleonvision.vision.Pipeline; -import com.chameleonvision.vision.camera.Camera; import com.chameleonvision.web.ServerHandler; import edu.wpi.cscore.VideoException; import edu.wpi.first.networktables.*; @@ -17,7 +15,6 @@ import java.util.List; public class VisionProcess implements Runnable { - private final Camera camera; private final String cameraName; public final CameraProcess cameraProcess; // NetworkTables @@ -45,36 +42,36 @@ public class VisionProcess implements Runnable { private Scalar BoxRectColor = new Scalar(0, 0, 233); private long timeStamp = 0; - public VisionProcess(Camera processCam) { - camera = processCam; - this.cameraName = camera.name; + public VisionProcess(CameraProcess cameraProcess) { - initNT(NetworkTableInstance.getDefault().getTable("/chameleon-vision/"+processCam.getNickname())); + // USBCamera settings + cvProcess = new CVProcess(cameraProcess.getCamVals()); + this.cameraProcess = cameraProcess; // new USBCameraProcess(cameraProcess); - // camera settings - cvProcess = new CVProcess(camera.getCamVals()); - cameraProcess = new CameraProcess(camera); + this.cameraName = cameraProcess.getCamName(); + + initNT(NetworkTableInstance.getDefault().getTable("/chameleon-vision/" + cameraProcess.getNickname())); } private void driverModeListener(EntryNotification entryNotification) { - camera.setDriverMode(entryNotification.value.getBoolean()); + cameraProcess.setDriverMode(entryNotification.value.getBoolean()); } private void pipelineListener(EntryNotification entryNotification) { var ntPipelineIndex = (int) entryNotification.value.getDouble(); - if (ntPipelineIndex >= camera.getPipelines().size()) { - ntPipelineEntry.setNumber(camera.getCurrentPipelineIndex()); + if (ntPipelineIndex >= cameraProcess.getPipelines().size()) { + ntPipelineEntry.setNumber(cameraProcess.getCurrentPipelineIndex()); } else { - var pipeline = camera.getCurrentPipeline(); - camera.setCurrentPipelineIndex(ntPipelineIndex); + var pipeline = cameraProcess.getCurrentPipeline(); + cameraProcess.setCurrentPipelineIndex(ntPipelineIndex); try { - camera.setExposure(pipeline.exposure); + cameraProcess.setExposure(pipeline.exposure); } catch (VideoException e) { System.err.println(e.toString()); } - camera.setBrightness(pipeline.brightness); - if (SettingsManager.GeneralSettings.currentCamera.equals(cameraName)) { - SettingsManager.GeneralSettings.currentPipeline = ntPipelineIndex; + cameraProcess.setBrightness(pipeline.brightness); + if (SettingsManager.generalSettings.currentCamera.equals(cameraName)) { + SettingsManager.generalSettings.currentPipeline = ntPipelineIndex; HashMap pipeChange = new HashMap<>(); pipeChange.put("currentPipeline", ntPipelineIndex); ServerHandler.broadcastMessage(pipeChange); @@ -123,7 +120,7 @@ public class VisionProcess implements Runnable { if (currentPipeline.orientation.equals(Orientation.Inverted)) { Core.flip(inputImage, inputImage, -1); } - if (camera.getDriverMode()) { + if (cameraProcess.getDriverMode()) { inputImage.copyTo(outputImage); return pipelineResult; } @@ -150,9 +147,9 @@ public class VisionProcess implements Runnable { pipelineResult.IsValid = true; switch (currentPipeline.calibrationMode) { case None: - ///use the center of the camera to find the pitch and yaw difference - pipelineResult.CalibratedX = camera.getCamVals().CenterX; - pipelineResult.CalibratedY = camera.getCamVals().CenterY; + ///use the center of the USBCamera to find the pitch and yaw difference + pipelineResult.CalibratedX = cameraProcess.getCamVals().CenterX; + pipelineResult.CalibratedY = cameraProcess.getCamVals().CenterY; break; case Single: // use the static point as a calibration method instead of the center @@ -165,7 +162,7 @@ public class VisionProcess implements Runnable { pipelineResult.CalibratedY = (finalRect.center.x * currentPipeline.m) + currentPipeline.b; break; } -// var camVals = camera.getCamVals(); +// var camVals = cameraProcess.getCamVals(); // if (currentPipeline.isCalibrated) { // pipelineResult.CalibratedX = (finalRect.center.y - currentPipeline.b) / currentPipeline.m; // pipelineResult.CalibratedY = (finalRect.center.x * currentPipeline.m) + currentPipeline.b; @@ -173,8 +170,8 @@ public class VisionProcess implements Runnable { // pipelineResult.CalibratedX = camVals.CenterX; // pipelineResult.CalibratedY = camVals.CenterY; // } - pipelineResult.Pitch = camera.getCamVals().CalculatePitch(finalRect.center.y, pipelineResult.CalibratedY); - pipelineResult.Yaw = camera.getCamVals().CalculateYaw(finalRect.center.x, pipelineResult.CalibratedX); + pipelineResult.Pitch = cameraProcess.getCamVals().CalculatePitch(finalRect.center.y, pipelineResult.CalibratedY); + pipelineResult.Yaw = cameraProcess.getCamVals().CalculateYaw(finalRect.center.x, pipelineResult.CalibratedX); pipelineResult.Area = finalRect.size.area(); drawContour(outputImage, finalRect); } @@ -193,7 +190,7 @@ public class VisionProcess implements Runnable { double processTimeMs; double fps = 0; double uiFps = 0; - int maxFps = camera.getVideoMode().fps; + int maxFps = cameraProcess.getVideoMode().fps; new Thread(cameraProcess).start(); @@ -201,10 +198,11 @@ public class VisionProcess implements Runnable { while (!Thread.interrupted()) { startTime = System.nanoTime(); - if ((startTime - lastFrameEndNanosec) * 1e-6 >= 1000.0 / maxFps + 3) { // 3 additional fps to allow for overhead + if ((startTime - lastFrameEndNanosec) * 1e-6 >= 1000.0 / (maxFps + 3)) { // 3 additional fps to allow for overhead foundContours.clear(); filteredContours.clear(); groupedContours.clear(); + deSpeckledContours.clear(); // update FPS for ui only every 0.5 seconds if ((startTime - fpsLastTime) * 1e-6 >= 500) { @@ -216,7 +214,7 @@ public class VisionProcess implements Runnable { fpsLastTime = System.nanoTime(); } - currentPipeline = camera.getCurrentPipeline(); + currentPipeline = cameraProcess.getCurrentPipeline(); // start fps counter right before grabbing input frame timeStamp = cameraProcess.getLatestFrame(cameraInputMat); if (cameraInputMat.cols() == 0 && cameraInputMat.rows() == 0) { @@ -226,7 +224,7 @@ public class VisionProcess implements Runnable { // get vision data var pipelineResult = runVisionProcess(cameraInputMat, streamOutputMat); updateNetworkTables(pipelineResult); - if (cameraName.equals(SettingsManager.GeneralSettings.currentCamera)) { + if (cameraName.equals(SettingsManager.generalSettings.currentCamera)) { HashMap WebSend = new HashMap<>(); HashMap point = new HashMap<>(); HashMap calculated = new HashMap<>(); @@ -293,6 +291,6 @@ public class VisionProcess implements Runnable { ntDriveModeListenerID = ntDriverModeEntry.addListener(this::driverModeListener, EntryListenerFlags.kUpdate); ntPipelineListenerID = ntPipelineEntry.addListener(this::pipelineListener, EntryListenerFlags.kUpdate); ntDriverModeEntry.setBoolean(false); - ntPipelineEntry.setNumber(camera.getCurrentPipelineIndex()); + ntPipelineEntry.setNumber(cameraProcess.getCurrentPipelineIndex()); } } diff --git a/Main/src/main/java/com/chameleonvision/web/ServerHandler.java b/Main/src/main/java/com/chameleonvision/web/ServerHandler.java index 214ca6f5b..9a60c716f 100644 --- a/Main/src/main/java/com/chameleonvision/web/ServerHandler.java +++ b/Main/src/main/java/com/chameleonvision/web/ServerHandler.java @@ -1,23 +1,19 @@ package com.chameleonvision.web; -import com.chameleonvision.settings.GeneralSettings; import com.chameleonvision.vision.*; -import com.chameleonvision.vision.camera.Camera; +import com.chameleonvision.vision.camera.USBCamera; import com.chameleonvision.vision.camera.CameraException; import com.chameleonvision.settings.SettingsManager; import com.chameleonvision.vision.camera.CameraManager; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; -import edu.wpi.cscore.VideoException; import io.javalin.websocket.*; import org.apache.commons.lang3.ArrayUtils; import org.msgpack.jackson.dataformat.MessagePackFactory; -import java.io.IOException; import java.lang.reflect.Field; -import java.lang.reflect.ParameterizedType; import java.nio.ByteBuffer; import java.util.*; @@ -49,7 +45,7 @@ public class ServerHandler { switch (entry.getKey()) { case "generalSettings": { for (HashMap.Entry e : ((HashMap) entry.getValue()).entrySet()) { - setField(SettingsManager.GeneralSettings, e.getKey(), e.getValue()); + setField(SettingsManager.generalSettings, e.getKey(), e.getValue()); } SettingsManager.saveSettings(); sendFullSettings(); @@ -182,8 +178,8 @@ public class ServerHandler { private void setField(Object obj, String fieldName, Object value) { try { - if (obj instanceof Camera) { - var cam = (Camera)obj; + if (obj instanceof USBCamera) { + var cam = (USBCamera)obj; if (fieldName.equals("driverBrightness")) { cam.setDriverBrightness((Integer)value); } else if (fieldName.equals("driverExposure")) { @@ -234,12 +230,12 @@ public class ServerHandler { private static HashMap getOrdinalSettings() { HashMap tmp = new HashMap<>(); - tmp.put("teamNumber", SettingsManager.GeneralSettings.teamNumber); - tmp.put("connectionType", SettingsManager.GeneralSettings.connectionType.ordinal()); - tmp.put("ip", SettingsManager.GeneralSettings.ip); - tmp.put("gateway", SettingsManager.GeneralSettings.gateway); - tmp.put("netmask", SettingsManager.GeneralSettings.netmask); - tmp.put("hostname", SettingsManager.GeneralSettings.hostname); + tmp.put("teamNumber", SettingsManager.generalSettings.teamNumber); + tmp.put("connectionType", SettingsManager.generalSettings.connectionType.ordinal()); + tmp.put("ip", SettingsManager.generalSettings.ip); + tmp.put("gateway", SettingsManager.generalSettings.gateway); + tmp.put("netmask", SettingsManager.generalSettings.netmask); + tmp.put("hostname", SettingsManager.generalSettings.hostname); return tmp; }