From 7ef05e6077853d6dc9171ac0e0aaa77e10347a72 Mon Sep 17 00:00:00 2001 From: Omer Date: Fri, 1 Nov 2019 11:38:58 +0200 Subject: [PATCH] Added driver mode exposure and brightness --- .../chameleonvision/vision/camera/Camera.java | 76 ++++++++++++++----- .../vision/camera/CameraDeserializer.java | 49 +++++++----- .../vision/camera/CameraSerializer.java | 5 +- .../vision/process/VisionProcess.java | 64 +++++++--------- 4 files changed, 118 insertions(+), 76 deletions(-) diff --git a/Main/src/main/java/com/chameleonvision/vision/camera/Camera.java b/Main/src/main/java/com/chameleonvision/vision/camera/Camera.java index a9721ab49..b5ee7d7a7 100644 --- a/Main/src/main/java/com/chameleonvision/vision/camera/Camera.java +++ b/Main/src/main/java/com/chameleonvision/vision/camera/Camera.java @@ -4,6 +4,7 @@ import com.chameleonvision.Main; import com.chameleonvision.settings.Platform; import com.chameleonvision.settings.SettingsManager; import com.chameleonvision.vision.Pipeline; +import com.chameleonvision.web.Server; import com.chameleonvision.web.ServerHandler; import edu.wpi.cscore.*; import edu.wpi.first.cameraserver.CameraServer; @@ -12,10 +13,7 @@ import edu.wpi.first.networktables.NetworkTableInstance; import org.opencv.core.Mat; import java.nio.channels.Pipe; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -23,12 +21,15 @@ public class Camera { private static final double DEFAULT_FOV = 60.8; private static final StreamDivisor DEFAULT_STREAMDIVISOR = StreamDivisor.none; + private static final int DEFAULT_EXPOSURE = 50; + private static final int DEFAULT_BRIGHTNESS = 50; private static final int MINIMUM_FPS = 30; private static final int MINIMUM_WIDTH = 320; private static final int MINIMUM_HEIGHT = 200; private static final int MAX_INIT_MS = 1500; private static final List ALLOWED_PIXEL_FORMATS = Arrays.asList(VideoMode.PixelFormat.kYUYV, VideoMode.PixelFormat.kMJPEG); + public final String name; public final String path; @@ -48,6 +49,11 @@ public class Camera { private int currentPipelineIndex; private List pipelines; + //Driver mode camera settings + public int driverExposure; + public int driverBrightness; + public boolean isDriver; + public Camera(String cameraName) { this(cameraName, DEFAULT_FOV); } @@ -61,18 +67,18 @@ public class Camera { } public Camera(String cameraName, UsbCameraInfo usbCamInfo, double fov, StreamDivisor divisor) { - this(cameraName, usbCamInfo, fov, new ArrayList<>(), 0, divisor); + this(cameraName, usbCamInfo, fov, new ArrayList<>(), 0, divisor, DEFAULT_EXPOSURE, DEFAULT_BRIGHTNESS); } - public Camera(String cameraName, double fov, List pipelines, int videoModeIndex, StreamDivisor divisor) { - this(cameraName, CameraManager.AllUsbCameraInfosByName.get(cameraName), fov, pipelines, videoModeIndex, divisor); + public Camera(String cameraName, double fov, List pipelines, int videoModeIndex, StreamDivisor divisor, int driverExposure, int driverBrightness) { + this(cameraName, CameraManager.AllUsbCameraInfosByName.get(cameraName), fov, pipelines, videoModeIndex, divisor, driverExposure, driverBrightness); } - public Camera(String cameraName, double fov, int videoModeIndex, StreamDivisor divisor) { - this(cameraName, fov, new ArrayList<>(), videoModeIndex, divisor); + public Camera(String cameraName, double fov, int videoModeIndex, StreamDivisor divisor, int driverExposure, int driverBrightness) { + this(cameraName, fov, new ArrayList<>(), videoModeIndex, divisor, driverExposure, driverBrightness); } - public Camera(String cameraName, UsbCameraInfo usbCamInfo, double fov, List pipelines, int videoModeIndex, StreamDivisor divisor) { + public Camera(String cameraName, UsbCameraInfo usbCamInfo, double fov, List pipelines, int videoModeIndex, StreamDivisor divisor, int driverExposure, int driverBrightness) { FOV = fov; name = cameraName; @@ -115,6 +121,9 @@ public class Camera { cvSink = cs.getVideo(UsbCam); cvSource = cs.putVideo(name, camVals.ImageWidth, camVals.ImageHeight); + isDriver = false; + this.driverBrightness=driverBrightness; + this.driverExposure=driverExposure; } VideoMode[] getAvailableVideoModes() { @@ -217,22 +226,55 @@ public class Camera { camVals = new CameraValues(this); } + public void setDriverMode(boolean state) + { + Map data = new HashMap<>(); + isDriver=state; + if(isDriver){ + UsbCam.setBrightness(driverBrightness); + UsbCam.setBrightness(driverBrightness); + try{UsbCam.setExposureManual(driverExposure);} + catch (VideoException e) + { + System.out.println("Exposure change isnt supported"); + } + data.put("brightness",getBrightness()); + data.put("exposure",driverExposure); + } + else{ + UsbCam.setBrightness(getCurrentPipeline().brightness); + UsbCam.setBrightness(getCurrentPipeline().brightness); + try{UsbCam.setExposureManual(getCurrentPipeline().exposure);} + catch (VideoException e) + { + System.out.println("Exposure change isnt supported"); + } + data.put("brightness",getBrightness()); + data.put("exposure",getCurrentPipeline().exposure); + } + ServerHandler.broadcastMessage(data); + } + public int getBrightness() { - return getCurrentPipeline().brightness; + return UsbCam.getBrightness(); } public void setBrightness(int brightness) { - getCurrentPipeline().brightness = brightness; + if (isDriver) + driverBrightness=brightness; + else + getCurrentPipeline().brightness = brightness; UsbCam.setBrightness(brightness); } public void setExposure(int exposure) { - getCurrentPipeline().exposure = exposure; + if (isDriver) + driverExposure=exposure; + else + getCurrentPipeline().exposure = exposure; try { UsbCam.setExposureManual(exposure); - } - catch (VideoException e) - { + } catch (VideoException e) { System.err.println("Camera Does not support exposure change"); } } @@ -259,7 +301,7 @@ public class Camera { public void setNickname(String newNickname) { //Deletes old camera nt table - NetworkTableInstance.getDefault().getTable("/chameleon-vision/" + this.nickname).getInstance().deleteAllEntries(); + NetworkTableInstance.getDefault().getTable("/chameleon-vision/" + this.nickname).getInstance().deleteAllEntries(); nickname = newNickname; if (CameraManager.AllVisionProcessesByName.containsKey(this.name)) { NetworkTable newNT = NetworkTableInstance.getDefault().getTable("/chameleon-vision/" + this.nickname); 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 50ac7cb09..4d370f32e 100644 --- a/Main/src/main/java/com/chameleonvision/vision/camera/CameraDeserializer.java +++ b/Main/src/main/java/com/chameleonvision/vision/camera/CameraDeserializer.java @@ -17,26 +17,37 @@ import java.util.List; public class CameraDeserializer implements JsonDeserializer { @Override public Camera deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException { - var jsonObj = jsonElement.getAsJsonObject(); - var camFOV = jsonObj.get("FOV").getAsDouble(); - var camName = jsonObj.get("name").getAsString(); - var camNickname = jsonObj.get("nickname").getAsString(); - var videoModeIndex = jsonObj.get("resolution").getAsInt(); - var divisor = StreamDivisor.values()[jsonObj.get("streamDivisor").getAsInt()]; - - var pipelines = jsonObj.get("pipelines"); - List actualPipelines = new ArrayList<>(); - ObjectMapper mapper = new ObjectMapper(); - TypeFactory typeFactory = mapper.getTypeFactory(); - JavaType arrayType = typeFactory.constructCollectionType(List.class, Pipeline.class); try { - actualPipelines = mapper.readValue(pipelines.toString(), arrayType); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } + var jsonObj = jsonElement.getAsJsonObject(); + var camFOV = jsonObj.get("FOV").getAsDouble(); + var camName = jsonObj.get("name").getAsString(); + var camNickname = jsonObj.get("nickname").getAsString(); + var videoModeIndex = jsonObj.get("resolution").getAsInt(); + var driverExposure = jsonObj.get("driverExposure").getAsInt(); + var driverBrightness = jsonObj.get("driverBrightness").getAsInt(); + var divisor = StreamDivisor.values()[jsonObj.get("streamDivisor").getAsInt()]; - var newCamera = actualPipelines != null ? new Camera(camName, camFOV, actualPipelines, videoModeIndex, divisor) : new Camera(camName, camFOV, videoModeIndex, divisor); - newCamera.setNickname(camNickname != null ? camNickname : ""); - return newCamera; + var pipelines = jsonObj.get("pipelines"); + List actualPipelines = new ArrayList<>(); + ObjectMapper mapper = new ObjectMapper(); + TypeFactory typeFactory = mapper.getTypeFactory(); + JavaType arrayType = typeFactory.constructCollectionType(List.class, Pipeline.class); + try { + actualPipelines = mapper.readValue(pipelines.toString(), arrayType); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + + var newCamera = actualPipelines != null ? new Camera(camName, camFOV, actualPipelines, videoModeIndex, divisor, driverExposure, driverBrightness) : new Camera(camName, camFOV, videoModeIndex, divisor, driverExposure, driverBrightness); + newCamera.setNickname(camNickname != null ? camNickname : ""); + return newCamera; + } + catch (NullPointerException e) + { + System.err.println("Error while reading json, value doesnt exist!"); + System.err.println("Try to delete the camera settings in settings/cameras/YOURCAMERA.json"); + e.printStackTrace(); + return null; + } } } 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 e5e949070..893c2ba08 100644 --- a/Main/src/main/java/com/chameleonvision/vision/camera/CameraSerializer.java +++ b/Main/src/main/java/com/chameleonvision/vision/camera/CameraSerializer.java @@ -12,13 +12,12 @@ public class CameraSerializer implements JsonSerializer { obj.addProperty("name", camera.name); obj.addProperty("nickname", camera.getNickname()); obj.addProperty("streamDivisor", camera.getStreamDivisor().ordinal()); - var pipelines = context.serialize(camera.getPipelines()); obj.add("pipelines", pipelines); - obj.addProperty("resolution", camera.getVideoModeIndex()); obj.add("camVideoMode", context.serialize(camera.getVideoMode())); - + obj.add("driverExposure",context.serialize(camera.driverExposure)); + obj.add("driverBrightness",context.serialize(camera.driverBrightness)); return obj; } } 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 1ed5d91a6..0606d11a9 100644 --- a/Main/src/main/java/com/chameleonvision/vision/process/VisionProcess.java +++ b/Main/src/main/java/com/chameleonvision/vision/process/VisionProcess.java @@ -49,9 +49,6 @@ public class VisionProcess implements Runnable { camera = processCam; this.cameraName = camera.name; - // NetworkTables -// NetworkTable ntTable = NetworkTableInstance.getDefault().getTable("/chameleon-vision/" + cameraName); -// NetworkTable ntTable = camera.getNtTable(); initNT(NetworkTableInstance.getDefault().getTable("/chameleon-vision/"+processCam.getNickname())); // camera settings @@ -60,14 +57,7 @@ public class VisionProcess implements Runnable { } private void driverModeListener(EntryNotification entryNotification) { - if (entryNotification.value.getBoolean()) { - camera.setExposure(25); - camera.setBrightness(15); - } else { - Pipeline pipeline = camera.getCurrentPipeline(); - camera.setExposure(pipeline.exposure); - camera.setBrightness(pipeline.brightness); - } + camera.setDriverMode(entryNotification.value.getBoolean()); } private void pipelineListener(EntryNotification entryNotification) { @@ -158,22 +148,22 @@ public class VisionProcess implements Runnable { var finalRect = cvProcess.sortTargetsToOne(groupedContours, currentPipeline.sortMode); pipelineResult.RawPoint = finalRect; 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; - break; - case Single: - // use the static point as a calibration method instead of the center - pipelineResult.CalibratedX = currentPipeline.point.get(0).doubleValue(); - pipelineResult.CalibratedY = currentPipeline.point.get(1).doubleValue(); - break; - case Dual: - // use the calculated line to find the difference in length between the point and the line - pipelineResult.CalibratedX = (finalRect.center.y - currentPipeline.b) / currentPipeline.m; - pipelineResult.CalibratedY = (finalRect.center.x * currentPipeline.m) + currentPipeline.b; - break; + 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; + break; + case Single: + // use the static point as a calibration method instead of the center + pipelineResult.CalibratedX = currentPipeline.point.get(0).doubleValue(); + pipelineResult.CalibratedY = currentPipeline.point.get(1).doubleValue(); + break; + case Dual: + // use the calculated line to find the difference in length between the point and the line + pipelineResult.CalibratedX = (finalRect.center.y - currentPipeline.b) / currentPipeline.m; + pipelineResult.CalibratedY = (finalRect.center.x * currentPipeline.m) + currentPipeline.b; + break; } pipelineResult.Pitch = camera.getCamVals().CalculatePitch(finalRect.center.y, pipelineResult.CalibratedY); pipelineResult.Yaw = camera.getCamVals().CalculateYaw(finalRect.center.x, pipelineResult.CalibratedX); @@ -248,7 +238,7 @@ public class VisionProcess implements Runnable { point.put("calculated", calculated); point.put("rawPoint", center); WebSend.put("point", point); - ServerHandler.broadcastMessage(WebSend); +// ServerHandler.broadcastMessage(WebSend); } cameraProcess.updateFrame(streamOutputMat); @@ -265,26 +255,26 @@ public class VisionProcess implements Runnable { } } -} + } + /** - * Removes the old value change listeners - * calls {@link #initNT} - * @param newTable passed to {@link #initNT} + * Removes the old value change listeners + * calls {@link #initNT} * + * @param newTable passed to {@link #initNT} */ - public void resetNT(NetworkTable newTable) - { + public void resetNT(NetworkTable newTable) { ntDriverModeEntry.removeListener(ntDriveModeListenerID); ntPipelineEntry.removeListener(ntPipelineListenerID); initNT(newTable); } /** - * Rebases the writing location for the vision process - pipeline output + * Rebases the writing location for the vision process - pipeline output + * * @param newTable the new writing location */ - private void initNT(NetworkTable newTable) - { + private void initNT(NetworkTable newTable) { ntPipelineEntry = newTable.getEntry("pipeline"); ntDriverModeEntry = newTable.getEntry("driver_mode"); ntPitchEntry = newTable.getEntry("pitch");