diff --git a/photon-client/src/types/PipelineTypes.ts b/photon-client/src/types/PipelineTypes.ts index 55298cae5c..4aa0d3c92d 100644 --- a/photon-client/src/types/PipelineTypes.ts +++ b/photon-client/src/types/PipelineTypes.ts @@ -65,8 +65,8 @@ export interface PipelineSettings { outputShowMultipleTargets: boolean; contourSortMode: number; cameraExposureRaw: number; - cameraMinexposureRaw: number; - cameraMaxexposureRaw: number; + cameraMinExposureRaw: number; + cameraMaxExposureRaw: number; offsetSinglePoint: { x: number; y: number }; cameraBrightness: number; offsetDualPointAArea: number; diff --git a/photon-core/src/main/java/org/photonvision/vision/camera/FileVisionSource.java b/photon-core/src/main/java/org/photonvision/vision/camera/FileVisionSource.java index 3a8928dc1e..ecb3b56b89 100644 --- a/photon-core/src/main/java/org/photonvision/vision/camera/FileVisionSource.java +++ b/photon-core/src/main/java/org/photonvision/vision/camera/FileVisionSource.java @@ -98,7 +98,7 @@ private static class FileSourceSettables extends VisionSourceSettables { } @Override - public void setexposureRaw(double exposureRaw) {} + public void setExposureRaw(double exposureRaw) {} public void setAutoExposure(boolean cameraAutoExposure) {} @@ -124,12 +124,12 @@ public HashMap getAllVideoModes() { } @Override - public double getMinexposureRaw() { + public double getMinExposureRaw() { return 1f; } @Override - public double getMaxexposureRaw() { + public double getMaxExposureRaw() { return 100f; } } diff --git a/photon-core/src/main/java/org/photonvision/vision/camera/LibcameraGpuSettables.java b/photon-core/src/main/java/org/photonvision/vision/camera/LibcameraGpuSettables.java index 2d95100c35..309a2fca86 100644 --- a/photon-core/src/main/java/org/photonvision/vision/camera/LibcameraGpuSettables.java +++ b/photon-core/src/main/java/org/photonvision/vision/camera/LibcameraGpuSettables.java @@ -123,7 +123,7 @@ public void setAutoExposure(boolean cameraAutoExposure) { } @Override - public void setexposureRaw(double exposureRaw) { + public void setExposureRaw(double exposureRaw) { if (exposureRaw < 0.0 || lastAutoExposureActive) { // Auto-exposure is active right now, don't set anything. return; @@ -227,7 +227,7 @@ protected void setVideoModeInternal(VideoMode videoMode) { // We don't store last settings on the native side, and when you change video mode these get // reset on MMAL's end - setexposureRaw(lastManualExposure); + setExposureRaw(lastManualExposure); setAutoExposure(lastAutoExposureActive); setBrightness(lastBrightness); setGain(lastGain); @@ -248,12 +248,12 @@ public LibCameraJNI.SensorModel getModel() { } @Override - public double getMinexposureRaw() { + public double getMinExposureRaw() { return this.minExposure; } @Override - public double getMaxexposureRaw() { + public double getMaxExposureRaw() { return this.maxExposure; } } diff --git a/photon-core/src/main/java/org/photonvision/vision/camera/USBCameraSource.java b/photon-core/src/main/java/org/photonvision/vision/camera/USBCameraSource.java index 9ab1d6f634..3f8e3d7464 100644 --- a/photon-core/src/main/java/org/photonvision/vision/camera/USBCameraSource.java +++ b/photon-core/src/main/java/org/photonvision/vision/camera/USBCameraSource.java @@ -41,8 +41,8 @@ public class USBCameraSource extends VisionSource { private final Logger logger; private final UsbCamera camera; - private final USBCameraSettables usbCameraSettables; - private FrameProvider usbFrameProvider; + protected USBCameraSettables usbCameraSettables; + protected FrameProvider usbFrameProvider; private final CvSink cvSink; private VideoProperty exposureAbsProp = null; @@ -116,7 +116,7 @@ public USBCameraSource(CameraConfiguration config) { // Functional camera, set up the frame provider and configure defaults usbFrameProvider = new USBFrameProvider(cvSink, usbCameraSettables); setAllCamDefaults(); - exposureAbsProp = expProp.get(); + exposureAbsProp = expProp.get(); autoExposureProp = autoExpProp.get(); this.minExposure = exposureAbsProp.getMin(); @@ -141,22 +141,6 @@ public USBCameraSource(CameraConfiguration config) { } } - /** - * Mostly just used for unit tests to better simulate a usb camera without a camera being present. - */ - public USBCameraSource(CameraConfiguration config, int pid, int vid, boolean unitTest) { - this(config); - - getCameraConfiguration().cameraQuirks = QuirkyCamera.getQuirkyCamera(pid, vid, config.baseName); - - if (unitTest) - usbFrameProvider = - new FileFrameProvider( - TestUtils.getWPIImagePath( - TestUtils.WPI2019Image.kCargoStraightDark72in_HighRes, false), - TestUtils.WPI2019Image.FOV); - } - /** * Returns the first property with a name in the list. Useful to find gandolf property that goes * by many names in different os/releases/whatever @@ -183,7 +167,7 @@ private Optional findProperty(String... options) { retProp = null; } - return Optional.of(retProp); + return Optional.ofNullable(retProp); } /** @@ -207,29 +191,36 @@ private void softSet(String property, int value) { } private void printCameraProperaties() { - VideoProperty[] cameraProperties = camera.enumerateProperties(); - String cameraPropertiesStr = "Cam Properties Dump:\n"; - - for (int i = 0; i < cameraProperties.length; i++) { - cameraPropertiesStr += - "Name: " - + cameraProperties[i].getName() - + ", Kind: " - + cameraProperties[i].getKind() - + ", Value: " - + cameraProperties[i].getKind().getValue() - + ", Min: " - + cameraProperties[i].getMin() - + ", Max: " - + cameraProperties[i].getMax() - + ", Dflt: " - + cameraProperties[i].getDefault() - + ", Step: " - + cameraProperties[i].getStep() - + "\n"; + + VideoProperty[] cameraProperties = null; + try { + cameraProperties = camera.enumerateProperties(); + } catch (VideoException e){ + logger.error("Failed to list camera properties!", e); } - logger.debug(cameraPropertiesStr); + if(cameraProperties != null){ + String cameraPropertiesStr = "Cam Properties Dump:\n"; + for (int i = 0; i < cameraProperties.length; i++) { + cameraPropertiesStr += + "Name: " + + cameraProperties[i].getName() + + ", Kind: " + + cameraProperties[i].getKind() + + ", Value: " + + cameraProperties[i].getKind().getValue() + + ", Min: " + + cameraProperties[i].getMin() + + ", Max: " + + cameraProperties[i].getMax() + + ", Dflt: " + + cameraProperties[i].getDefault() + + ", Step: " + + cameraProperties[i].getStep() + + "\n"; + } + logger.debug(cameraPropertiesStr); + } } private void setAllCamDefaults() { @@ -261,13 +252,13 @@ public VisionSourceSettables getSettables() { public class USBCameraSettables extends VisionSourceSettables { // We need to remember the last exposure set when exiting // auto exposure mode so we can restore it - private double lastexposureRaw = -1; + private double lastExposureRaw = -1; // Some cameras need logic where we re-apply brightness after // changing exposure private int lastBrightness = -1; - protected USBCameraSettables(CameraConfiguration configuration) { + public USBCameraSettables(CameraConfiguration configuration) { super(configuration); getAllVideoModes(); if (!configuration.cameraQuirks.hasQuirk(CameraQuirk.StickyFPS)) @@ -275,6 +266,7 @@ protected USBCameraSettables(CameraConfiguration configuration) { } public void setAutoExposure(boolean cameraAutoExposure) { + logger.debug("Setting auto exposure to " + cameraAutoExposure); if (!cameraAutoExposure) { @@ -289,7 +281,7 @@ public void setAutoExposure(boolean cameraAutoExposure) { // Most cameras leave exposure time absolute at the last value from their AE algorithm. // Set it back to the exposure slider value - setexposureRaw(this.lastexposureRaw); + setExposureRaw(this.lastExposureRaw); } else { // Pick a bunch of reasonable setting to make the picture nice-for-humans @@ -303,17 +295,17 @@ public void setAutoExposure(boolean cameraAutoExposure) { } @Override - public double getMinexposureRaw() { + public double getMinExposureRaw() { return minExposure; } @Override - public double getMaxexposureRaw() { + public double getMaxExposureRaw() { return maxExposure; } @Override - public void setexposureRaw(double exposureRaw) { + public void setExposureRaw(double exposureRaw) { if (exposureRaw >= 0.0) { try { autoExposureProp.set(PROP_AUTO_EXPOSURE_DISABLED); @@ -336,7 +328,7 @@ public void setexposureRaw(double exposureRaw) { exposureAbsProp.set(propVal); - this.lastexposureRaw = exposureRaw; + this.lastExposureRaw = exposureRaw; if (getCameraConfiguration().cameraQuirks.hasQuirk(CameraQuirk.LifeCamExposure)) { // Lifecam requires setting brightness again after exposure diff --git a/photon-core/src/main/java/org/photonvision/vision/pipeline/CVPipelineSettings.java b/photon-core/src/main/java/org/photonvision/vision/pipeline/CVPipelineSettings.java index 0879ceeb1a..915e08e18c 100644 --- a/photon-core/src/main/java/org/photonvision/vision/pipeline/CVPipelineSettings.java +++ b/photon-core/src/main/java/org/photonvision/vision/pipeline/CVPipelineSettings.java @@ -43,8 +43,8 @@ public class CVPipelineSettings implements Cloneable { public boolean cameraAutoExposure = false; // manual exposure only used if cameraAutoExposure is false public double cameraExposureRaw = 20; - public double cameraMinexposureRaw = 1; - public double cameraMaxexposureRaw = 100; + public double cameraMinExposureRaw = 1; + public double cameraMaxExposureRaw = 100; public int cameraBrightness = 50; // Currently only used by a few cameras (notably the zero-copy Pi Camera driver) with the Gain // quirk @@ -65,8 +65,8 @@ public boolean equals(Object o) { CVPipelineSettings that = (CVPipelineSettings) o; return pipelineIndex == that.pipelineIndex && Double.compare(that.cameraExposureRaw, cameraExposureRaw) == 0 - && Double.compare(that.cameraMinexposureRaw, cameraMinexposureRaw) == 0 - && Double.compare(that.cameraMaxexposureRaw, cameraMaxexposureRaw) == 0 + && Double.compare(that.cameraMinExposureRaw, cameraMinExposureRaw) == 0 + && Double.compare(that.cameraMaxExposureRaw, cameraMaxExposureRaw) == 0 && Double.compare(that.cameraBrightness, cameraBrightness) == 0 && Double.compare(that.cameraGain, cameraGain) == 0 && Double.compare(that.cameraRedGain, cameraRedGain) == 0 @@ -89,8 +89,8 @@ public int hashCode() { inputImageRotationMode, pipelineNickname, cameraExposureRaw, - cameraMinexposureRaw, - cameraMaxexposureRaw, + cameraMinExposureRaw, + cameraMaxExposureRaw, cameraBrightness, cameraGain, cameraRedGain, diff --git a/photon-core/src/main/java/org/photonvision/vision/processes/VisionModule.java b/photon-core/src/main/java/org/photonvision/vision/processes/VisionModule.java index ba7e0f99b7..4941a0b072 100644 --- a/photon-core/src/main/java/org/photonvision/vision/processes/VisionModule.java +++ b/photon-core/src/main/java/org/photonvision/vision/processes/VisionModule.java @@ -415,7 +415,7 @@ boolean setPipeline(int index) { pipelineSettings.cameraExposureRaw = 10; // reasonable default } - visionSource.getSettables().setexposureRaw(pipelineSettings.cameraExposureRaw); + visionSource.getSettables().setExposureRaw(pipelineSettings.cameraExposureRaw); try { visionSource.getSettables().setAutoExposure(pipelineSettings.cameraAutoExposure); } catch (VideoException e) { @@ -511,8 +511,8 @@ public PhotonConfiguration.UICameraConfiguration toUICameraConfig() { ret.currentPipelineIndex = pipelineManager.getRequestedIndex(); ret.pipelineNicknames = pipelineManager.getPipelineNicknames(); ret.cameraQuirks = visionSource.getSettables().getConfiguration().cameraQuirks; - ret.maxExposureRaw = visionSource.getSettables().getMaxexposureRaw(); - ret.minExposureRaw = visionSource.getSettables().getMinexposureRaw(); + ret.maxExposureRaw = visionSource.getSettables().getMaxExposureRaw(); + ret.minExposureRaw = visionSource.getSettables().getMinExposureRaw(); // TODO refactor into helper method var temp = new HashMap>(); diff --git a/photon-core/src/main/java/org/photonvision/vision/processes/VisionSourceSettables.java b/photon-core/src/main/java/org/photonvision/vision/processes/VisionSourceSettables.java index cc88f8389c..56db6214f9 100644 --- a/photon-core/src/main/java/org/photonvision/vision/processes/VisionSourceSettables.java +++ b/photon-core/src/main/java/org/photonvision/vision/processes/VisionSourceSettables.java @@ -42,11 +42,11 @@ public CameraConfiguration getConfiguration() { return configuration; } - public abstract void setexposureRaw(double exposureRaw); + public abstract void setExposureRaw(double exposureRaw); - public abstract double getMinexposureRaw(); + public abstract double getMinExposureRaw(); - public abstract double getMaxexposureRaw(); + public abstract double getMaxExposureRaw(); public abstract void setAutoExposure(boolean cameraAutoExposure); diff --git a/photon-core/src/test/java/org/photonvision/vision/QuirkyCameraTest.java b/photon-core/src/test/java/org/photonvision/vision/QuirkyCameraTest.java index 7305f21c4a..9b00566842 100644 --- a/photon-core/src/test/java/org/photonvision/vision/QuirkyCameraTest.java +++ b/photon-core/src/test/java/org/photonvision/vision/QuirkyCameraTest.java @@ -29,11 +29,12 @@ public void ps3EyeTest() { HashMap ps3EyeQuirks = new HashMap<>(); ps3EyeQuirks.put(CameraQuirk.Gain, true); ps3EyeQuirks.put(CameraQuirk.FPSCap100, true); + ps3EyeQuirks.put(CameraQuirk.OneZeroAutoExposure, true); for (var q : CameraQuirk.values()) { ps3EyeQuirks.putIfAbsent(q, false); } - QuirkyCamera psEye = QuirkyCamera.getQuirkyCamera(0x2000, 0x1415); + QuirkyCamera psEye = QuirkyCamera.getQuirkyCamera(0x1415, 0x2000); Assertions.assertEquals(psEye.quirks, ps3EyeQuirks); } diff --git a/photon-core/src/test/java/org/photonvision/vision/processes/MockUsbCameraSource.java b/photon-core/src/test/java/org/photonvision/vision/processes/MockUsbCameraSource.java new file mode 100644 index 0000000000..953bff5a8c --- /dev/null +++ b/photon-core/src/test/java/org/photonvision/vision/processes/MockUsbCameraSource.java @@ -0,0 +1,52 @@ +package org.photonvision.vision.processes; + +import org.photonvision.common.configuration.CameraConfiguration; +import org.photonvision.common.util.TestUtils; +import org.photonvision.vision.camera.QuirkyCamera; +import org.photonvision.vision.camera.USBCameraSource; +import org.photonvision.vision.frame.provider.FileFrameProvider; + +public class MockUsbCameraSource extends USBCameraSource{ + + /** + * Used for unit tests to better simulate a usb camera without a camera being present. + */ + public MockUsbCameraSource(CameraConfiguration config, int pid, int vid) { + super(config); + + getCameraConfiguration().cameraQuirks = QuirkyCamera.getQuirkyCamera(pid, vid, config.baseName); + + /** + * File used as frame provider + */ + usbFrameProvider = + new FileFrameProvider( + TestUtils.getWPIImagePath( + TestUtils.WPI2019Image.kCargoStraightDark72in_HighRes, false), + TestUtils.WPI2019Image.FOV); + + usbCameraSettables = new MockUsbCameraSettables(config); + + } + + private class MockUsbCameraSettables extends USBCameraSettables{ + + public MockUsbCameraSettables(CameraConfiguration config){ + super(config); + } + + /** + * Hardware-specific implementation - do nothing in test + */ + @Override + public void setExposureRaw(double exposureRaw){} + + /** + * Hardware-specific implementation - do nothing in test + */ + @Override + public void setAutoExposure(boolean cameraAutoExposure) {}; + + } + +} diff --git a/photon-core/src/test/java/org/photonvision/vision/processes/VisionModuleManagerTest.java b/photon-core/src/test/java/org/photonvision/vision/processes/VisionModuleManagerTest.java index f82fd6ff48..e416ab14a5 100644 --- a/photon-core/src/test/java/org/photonvision/vision/processes/VisionModuleManagerTest.java +++ b/photon-core/src/test/java/org/photonvision/vision/processes/VisionModuleManagerTest.java @@ -81,7 +81,7 @@ protected TestSettables(CameraConfiguration configuration) { } @Override - public void setexposureRaw(double exposure) {} + public void setExposureRaw(double exposure) {} @Override public void setBrightness(int brightness) {} @@ -110,12 +110,12 @@ public HashMap getAllVideoModes() { public void setAutoExposure(boolean cameraAutoExposure) {} @Override - public double getMinexposureRaw() { + public double getMinExposureRaw() { return 1; } @Override - public double getMaxexposureRaw() { + public double getMaxExposureRaw() { return 1234; } } @@ -186,10 +186,11 @@ public void testMultipleStreamIndex() { // Arducam OV9281 UC844 raspberry pi test. var conf4 = new CameraConfiguration("Left", "dev/video1"); - USBCameraSource usbSimulation = new USBCameraSource(conf4, 0x6366, 0x0c45, true); + USBCameraSource usbSimulation = new MockUsbCameraSource(conf4, 0x6366, 0x0c45); + var conf5 = new CameraConfiguration("Right", "dev/video2"); - USBCameraSource usbSimulation2 = new USBCameraSource(conf5, 0x6366, 0x0c45, true); + USBCameraSource usbSimulation2 = new MockUsbCameraSource(conf5, 0x6366, 0x0c45); var modules = vmm.addSources( diff --git a/photon-lib/src/main/native/include/photon/simulation/SimCameraProperties.h b/photon-lib/src/main/native/include/photon/simulation/SimCameraProperties.h index 4ec796aa5c..e673154061 100644 --- a/photon-lib/src/main/native/include/photon/simulation/SimCameraProperties.h +++ b/photon-lib/src/main/native/include/photon/simulation/SimCameraProperties.h @@ -96,12 +96,12 @@ class SimCameraProperties { units::radian_t{std::numbers::pi / 2.0}}) .Radians()}}, frc::Translation3d{ - 1_m, frc::Rotation3d{0_rad, - (GetPixelPitch(0) + - frc::Rotation2d{ - units::radian_t{std::numbers::pi / 2.0}}) - .Radians(), - 0_rad}}, + 1_m, + frc::Rotation3d{0_rad, + (GetPixelPitch(0) + frc::Rotation2d{units::radian_t{ + std::numbers::pi / 2.0}}) + .Radians(), + 0_rad}}, frc::Translation3d{ 1_m, frc::Rotation3d{0_rad, (GetPixelPitch(height) +