diff --git a/photon-client/src/store/index.js b/photon-client/src/store/index.js index 9a462a262..a4673b7c3 100644 --- a/photon-client/src/store/index.js +++ b/photon-client/src/store/index.js @@ -55,7 +55,8 @@ export default new Vuex.Store({ // Settings that apply to all pipeline types cameraExposure: 1, cameraBrightness: 2, - cameraGain: 3, + cameraRedGain: 3, + cameraBlueGain: 4, inputImageRotationMode: 0, cameraVideoModeIndex: 0, streamingFrameDivisor: 0, diff --git a/photon-client/src/views/CamerasView.vue b/photon-client/src/views/CamerasView.vue index 793b61cb3..70ee74f82 100644 --- a/photon-client/src/views/CamerasView.vue +++ b/photon-client/src/views/CamerasView.vue @@ -196,13 +196,24 @@ @input="e => handlePipelineUpdate('cameraBrightness', e)" /> + diff --git a/photon-client/src/views/PipelineViews/InputTab.vue b/photon-client/src/views/PipelineViews/InputTab.vue index 8b98e8e3a..c01adc079 100644 --- a/photon-client/src/views/PipelineViews/InputTab.vue +++ b/photon-client/src/views/PipelineViews/InputTab.vue @@ -22,15 +22,26 @@ @rollback="e => rollback('cameraBrightness', e)" /> + lastAwbGains = new Pair(18, 18); public PicamSettables(CameraConfiguration configuration) { super(configuration); @@ -137,21 +139,38 @@ public class ZeroCopyPicamSource extends VisionSource { public void setExposure(double exposure) { lastExposure = exposure; var failure = PicamJNI.setExposure((int) Math.round(exposure)); - if (failure) logger.warn("Couldn't set Pi camera exposure"); + if (failure) logger.warn("Couldn't set Pi Camera exposure"); } @Override public void setBrightness(int brightness) { lastBrightness = brightness; var failure = PicamJNI.setBrightness(brightness); - if (failure) logger.warn("Couldn't set Pi camera brightness"); + if (failure) logger.warn("Couldn't set Pi Camera brightness"); } @Override public void setGain(int gain) { lastGain = gain; var failure = PicamJNI.setGain(gain); - if (failure) logger.warn("Couldn't set Pi camera gain"); + if (failure) logger.warn("Couldn't set Pi Camera gain"); + } + + @Override + public void setRedGain(int red) { + lastAwbGains = Pair.of(red, lastAwbGains.getSecond()); + setAwbGain(lastAwbGains.getFirst(), lastAwbGains.getSecond()); + } + + @Override + public void setBlueGain(int blue) { + lastAwbGains = Pair.of(lastAwbGains.getFirst(), blue); + setAwbGain(lastAwbGains.getFirst(), lastAwbGains.getSecond()); + } + + public void setAwbGain(int red, int blue) { + var failure = PicamJNI.setAwbGain(red, blue); + if (failure) logger.warn("Couldn't set Pi Camera AWB gains"); } @Override @@ -165,17 +184,18 @@ public class ZeroCopyPicamSource extends VisionSource { var failure = PicamJNI.destroyCamera(); if (failure) throw new RuntimeException( - "Couldn't destroy a zero copy Pi camera while switching video modes"); + "Couldn't destroy a zero copy Pi Camera while switching video modes"); failure = PicamJNI.createCamera(mode.width, mode.height, mode.fpsActual); if (failure) throw new RuntimeException( - "Couldn't create a zero copy Pi camera while switching video modes"); + "Couldn't create a zero copy Pi Camera while switching video modes"); // We don't store last settings on the native side, and when you change video mode these get // reset on MMAL's end setExposure(lastExposure); setBrightness(lastBrightness); setGain(lastGain); + setAwbGain(lastAwbGains.getFirst(), lastAwbGains.getSecond()); currentVideoMode = mode; } 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 82fa44f00..0f7594f8c 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 @@ -41,7 +41,12 @@ public class CVPipelineSettings implements Cloneable { public String pipelineNickname = "New Pipeline"; public double cameraExposure = 50; public int cameraBrightness = 50; + // Currently only used by a few cameras (notably the zero-copy Pi Camera driver) with the Gain + // quirk public int cameraGain = 50; + // Currently only used by the zero-copy Pi Camera driver + public int cameraRedGain = 50; + public int cameraBlueGain = 50; public int cameraVideoModeIndex = 0; public FrameDivisor streamingFrameDivisor = FrameDivisor.NONE; public boolean ledMode = false; @@ -57,6 +62,8 @@ public class CVPipelineSettings implements Cloneable { && Double.compare(that.cameraExposure, cameraExposure) == 0 && Double.compare(that.cameraBrightness, cameraBrightness) == 0 && Double.compare(that.cameraGain, cameraGain) == 0 + && Double.compare(that.cameraRedGain, cameraRedGain) == 0 + && Double.compare(that.cameraBlueGain, cameraBlueGain) == 0 && cameraVideoModeIndex == that.cameraVideoModeIndex && ledMode == that.ledMode && pipelineType == that.pipelineType @@ -79,6 +86,8 @@ public class CVPipelineSettings implements Cloneable { cameraExposure, cameraBrightness, cameraGain, + cameraRedGain, + cameraBlueGain, cameraVideoModeIndex, streamingFrameDivisor, ledMode, 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 3b3787a86..ad09a29a9 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 @@ -107,6 +107,13 @@ public class VisionModule { if (it.cameraGain == -1) it.cameraGain = 20; // Sane default }); } + if (cameraQuirks.hasQuirk(CameraQuirk.PiCam)) { + pipelineManager.userPipelineSettings.forEach( + it -> { + if (it.cameraRedGain == -1) it.cameraRedGain = 16; // Sane defaults + if (it.cameraBlueGain == -1) it.cameraBlueGain = 16; + }); + } this.pipelineManager = pipelineManager; this.visionSource = visionSource; @@ -345,6 +352,10 @@ public class VisionModule { if (!cameraQuirks.hasQuirk(CameraQuirk.Gain)) { settings.cameraGain = -1; } + if (!cameraQuirks.hasQuirk(CameraQuirk.PiCam)) { + settings.cameraRedGain = -1; + settings.cameraBlueGain = -1; + } setPipeline(PipelineManager.CAL_3D_INDEX); } @@ -391,6 +402,16 @@ public class VisionModule { } else { config.cameraGain = -1; } + if (cameraQuirks.hasQuirk(CameraQuirk.PiCam)) { + // If the AWB gains are disabled for some reason, re-enable it + if (config.cameraRedGain == -1) config.cameraRedGain = 16; + if (config.cameraBlueGain == -1) config.cameraBlueGain = 16; + visionSource.getSettables().setRedGain(Math.max(0, config.cameraRedGain)); + visionSource.getSettables().setBlueGain(Math.max(0, config.cameraBlueGain)); + } else { + config.cameraRedGain = -1; + config.cameraBlueGain = -1; + } setVisionLEDs(config.ledMode); 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 fefa604ab..e4ff0b403 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 @@ -48,6 +48,11 @@ public abstract class VisionSourceSettables { public abstract void setBrightness(int brightness); public abstract void setGain(int gain); + // Pretty uncommon so instead of abstract this is just a no-op by default + // Overriden by cameras with AWB gain support + public void setRedGain(int red) {} + + public void setBlueGain(int blue) {} public abstract VideoMode getCurrentVideoMode(); diff --git a/photon-server/src/main/resources/nativelibraries/libpicam.so b/photon-server/src/main/resources/nativelibraries/libpicam.so index 245cfc7cd..9612f8d7e 100755 Binary files a/photon-server/src/main/resources/nativelibraries/libpicam.so and b/photon-server/src/main/resources/nativelibraries/libpicam.so differ