Skip to content

Commit

Permalink
Add awb switch
Browse files Browse the repository at this point in the history
  • Loading branch information
mcm001 committed Oct 19, 2024
1 parent 1a672a3 commit 0ef1c30
Show file tree
Hide file tree
Showing 17 changed files with 214 additions and 21 deletions.
19 changes: 19 additions & 0 deletions photon-client/src/components/dashboard/tabs/InputTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,25 @@ const interactiveCols = computed(() =>
tooltip="Controls blue automatic white balance gain, which affects how the camera captures colors in different conditions"
@input="(args) => useCameraSettingsStore().changeCurrentPipelineSetting({ cameraBlueGain: args }, false)"
/>

<pv-switch
v-model="useCameraSettingsStore().currentPipelineSettings.cameraAutoWhiteBalance"
class="pt-2"
label="Auto White Balance"
:switch-cols="interactiveCols"
tooltip="Enables or Disables camera automatic adjustment for current lighting conditions"
@input="(args) => useCameraSettingsStore().changeCurrentPipelineSetting({ cameraAutoWhiteBalance: args }, false)"
/>
<pv-slider
v-model="useCameraSettingsStore().currentPipelineSettings.whiteBalanceTemp"
v-if="!useCameraSettingsStore().currentPipelineSettings.cameraAutoWhiteBalance"
label="White Balance Temperature"
:min="useCameraSettingsStore().minWhiteBalanceTemp"
:max="useCameraSettingsStore().maxWhiteBalanceTemp"
:slider-cols="interactiveCols"
@input="(args) => useCameraSettingsStore().changeCurrentPipelineSetting({ whiteBalanceTemp: args }, false)"
/>

<pv-select
v-model="useCameraSettingsStore().currentPipelineSettings.inputImageRotationMode"
label="Orientation"
Expand Down
8 changes: 7 additions & 1 deletion photon-client/src/stores/settings/CameraSettingsStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,13 @@ export const useCameraSettingsStore = defineStore("cameraSettings", {
},
maxExposureRaw(): number {
return this.currentCameraSettings.maxExposureRaw;
}
},
minWhiteBalanceTemp(): number {
return this.currentCameraSettings.minWhiteBalanceTemp;
},
maxWhiteBalanceTemp(): number {
return this.currentCameraSettings.maxWhiteBalanceTemp;
},
},
actions: {
updateCameraSettingsFromWebsocket(data: WebsocketCameraSettingsUpdate[]) {
Expand Down
7 changes: 6 additions & 1 deletion photon-client/src/types/PipelineTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ export interface PipelineSettings {
hsvSaturation: WebsocketNumberPair | [number, number];
pipelineType: PipelineType;
contourIntersection: number;

cameraAutoWhiteBalance: boolean;
whiteBalanceTemp: number;
}
export type ConfigurablePipelineSettings = Partial<
Omit<
Expand Down Expand Up @@ -137,7 +140,9 @@ export const DefaultPipelineSettings: Omit<
cornerDetectionStrategy: 0,
cornerDetectionAccuracyPercentage: 10,
hsvSaturation: { first: 50, second: 255 },
contourIntersection: 1
contourIntersection: 1,
cameraAutoWhiteBalance: false,
whiteBalanceTemp: 4000,
};

export interface ReflectivePipelineSettings extends PipelineSettings {
Expand Down
7 changes: 6 additions & 1 deletion photon-client/src/types/SettingTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,9 @@ export interface CameraSettings {

minExposureRaw: number;
maxExposureRaw: number;

minWhiteBalanceTemp: number;
maxWhiteBalanceTemp: number;
}

export interface CameraSettingsChangeRequest {
Expand Down Expand Up @@ -299,7 +302,9 @@ export const PlaceholderCameraSettings: CameraSettings = {
},
isCSICamera: false,
minExposureRaw: 1,
maxExposureRaw: 100
maxExposureRaw: 100,
minWhiteBalanceTemp: 2000,
maxWhiteBalanceTemp: 10000,
};

export enum CalibrationBoardTypes {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,5 +181,7 @@ public static class UICameraConfiguration {
public boolean isCSICamera;
public double minExposureRaw;
public double maxExposureRaw;
public double minWhiteBalanceTemp;
public double maxWhiteBalanceTemp;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,34 @@ public Thread newThread(@NotNull Runnable r) {
}
}

private final ScheduledExecutorService timedTaskExecutorPool =
new ScheduledThreadPoolExecutor(2, new CaughtThreadFactory());
private final ScheduledThreadPoolExecutor timedTaskExecutorPool =
new ScheduledThreadPoolExecutor(2, new CaughtThreadFactory()) {
@SuppressWarnings("rawtypes")
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
// from
// https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html#afterExecute(java.lang.Runnable,%20java.lang.Throwable)
if (t == null && r instanceof Future<?>) {
if (!((Future<?>) r).isDone()) {
return;
}
try {
Object result = ((Future<?>) r).get();
if (result == null) return;
logger.error("Result from ScheduledThreadPoolExecutor! " + result);
} catch (CancellationException ce) {
t = ce;
} catch (ExecutionException ee) {
t = ee.getCause();
} catch (InterruptedException ie) {
Thread.currentThread().interrupt(); // ignore/reset
}
}
if (t != null) {
logger.error("Error from ScheduledThreadPoolExecutor!", t);
}
}
};
private final ConcurrentHashMap<String, Future<?>> activeTasks = new ConcurrentHashMap<>();

public void addTask(String identifier, Runnable runnable, long millisInterval) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public enum CameraQuirk {
/** Cap at 100FPS for high-bandwidth cameras */
FPSCap100,
/** Separate red/blue gain controls available */
AWBGain,
AwbRedBlueGain,
/** Will not work with photonvision - Logitec C270 at least */
CompletelyBroken,
/** Has adjustable focus and autofocus switch */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,5 +138,22 @@ public double getMinExposureRaw() {
public double getMaxExposureRaw() {
return 100f;
}

@Override
public void setAutoWhiteBalance(boolean autowb) {}

@Override
public void setWhiteBalanceTemp(double temp) {}


@Override
public double getMaxWhiteBalanceTemp() {
return 1;
}

@Override
public double getMinWhiteBalanceTemp() {
return 2;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -260,4 +260,24 @@ public double getMinExposureRaw() {
public double getMaxExposureRaw() {
return this.maxExposure;
}

@Override
public void setAutoWhiteBalance(boolean autowb) {
throw new RuntimeException("Libcamera doesn't support AWB temp (yet)");
}

@Override
public void setWhiteBalanceTemp(double temp) {
throw new RuntimeException("Libcamera doesn't support AWB temp -- use red/blue gain instead");
}

@Override
public double getMaxWhiteBalanceTemp() {
return 1;
}

@Override
public double getMinWhiteBalanceTemp() {
return 2;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ public class QuirkyCamera {
// PS3Eye
new QuirkyCamera(
0x1415, 0x2000, CameraQuirk.Gain, CameraQuirk.FPSCap100, CameraQuirk.PsEyeControls),
// OBS hack
new QuirkyCamera(-1, -1, CameraQuirk.CompletelyBroken),
// Logitech C925-e
new QuirkyCamera(0x85B, 0x46D, CameraQuirk.AdjustableFocus),
// Generic arducam. Since OV2311 can't be differentiated
Expand Down Expand Up @@ -97,7 +99,7 @@ public class QuirkyCamera {
-1,
"unicam",
CameraQuirk.Gain,
CameraQuirk.AWBGain); // PiCam (using libpicam GPU Driver on raspberry pi)
CameraQuirk.AwbRedBlueGain); // PiCam (using libcamera GPU Driver on raspberry pi)

@JsonProperty("baseName")
public final String baseName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class ArduOV9782CameraSettables extends GenericUSBCameraSettables {
public ArduOV9782CameraSettables(CameraConfiguration configuration, UsbCamera camera) {
super(configuration, camera);
// Arbitrary, worked well in Chris's basement
whiteBalanceTemperature = 5300;
lastWhiteBalanceTemp = 5300;

// According to Chris' pi, running an older kernel at least
this.minExposure = 1;
Expand All @@ -37,7 +37,7 @@ public void setAllCamDefaults() {
softSet("exposure_metering_mode", 0);
softSet("exposure_dynamic_framerate", 0);
softSet("white_balance_automatic", 0);
softSet("white_balance_temperature", whiteBalanceTemperature);
softSet("white_balance_temperature", lastWhiteBalanceTemp);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,18 @@ public class GenericUSBCameraSettables extends VisionSourceSettables {

protected VideoProperty exposureAbsProp = null;
protected VideoProperty autoExposureProp = null;
protected VideoProperty wbTempProp = null;

protected double minExposure = 1;
protected double maxExposure = 80000;

protected double minWhiteBalanceTemp = 1;
protected double maxWhiteBalanceTemp = 4000;
protected int lastWhiteBalanceTemp = 4000;

protected static final int PROP_AUTO_EXPOSURE_ENABLED = 3;
protected static final int PROP_AUTO_EXPOSURE_DISABLED = 1;

protected int whiteBalanceTemperature = 4000;

protected UsbCamera camera;
protected CameraConfiguration configuration;

Expand All @@ -71,6 +74,10 @@ public GenericUSBCameraSettables(CameraConfiguration configuration, UsbCamera ca
setVideoMode(videoModes.get(0)); // fixes double FPS set
}
}

wbTempProp = findProperty("white_balance_temperature", "WhiteBalance").get();
this.minWhiteBalanceTemp = wbTempProp.getMin();
this.maxWhiteBalanceTemp = wbTempProp.getMax();
}

protected void setUpExposureProperties() {
Expand Down Expand Up @@ -102,6 +109,50 @@ public void setAllCamDefaults() {
softSet("focus_absolute", 0); // Focus into infinity
}

@Override
public void setWhiteBalanceTemp(double tempNumber) {
try {
int temp = (int) Math.round(tempNumber);

softSet("white_balance_auto_preset", 2);
softSet("white_balance_automatic", 0);

int propVal = (int) MathUtil.clamp(temp, minWhiteBalanceTemp, maxWhiteBalanceTemp);

logger.debug(
"Setting property "
+ wbTempProp.getName()
+ " to "
+ propVal
+ " (user requested "
+ temp
+ " degrees)");

wbTempProp.set(propVal);

this.lastWhiteBalanceTemp = temp;

} catch (VideoException e) {
logger.error("Failed to set camera exposure!", e);
}
}

@Override
public void setAutoWhiteBalance(boolean autoWB) {
logger.debug("Setting auto white balance to " + autoWB);

if (autoWB) {
// Seems to be a rpi-specific property?
softSet("white_balance_auto_preset", 1); // Auto white-balance enabled
softSet("white_balance_automatic", 1);
} else {
softSet("white_balance_auto_preset", 2); // Auto white-balance disabled
softSet("white_balance_automatic", 0);

wbTempProp.set(this.lastWhiteBalanceTemp);
}
}

public void setAutoExposure(boolean cameraAutoExposure) {
logger.debug("Setting auto exposure to " + cameraAutoExposure);

Expand All @@ -110,9 +161,6 @@ public void setAutoExposure(boolean cameraAutoExposure) {
softSet("auto_exposure_bias", 0);
softSet("iso_sensitivity_auto", 0); // Disable auto ISO adjustment
softSet("iso_sensitivity", 0); // Manual ISO adjustment
softSet("white_balance_auto_preset", 2); // Auto white-balance disabled
softSet("white_balance_automatic", 0);
softSet("white_balance_temperature", whiteBalanceTemperature);
autoExposureProp.set(PROP_AUTO_EXPOSURE_DISABLED);

// Most cameras leave exposure time absolute at the last value from their AE
Expand All @@ -125,8 +173,6 @@ public void setAutoExposure(boolean cameraAutoExposure) {
softSet("auto_exposure_bias", 12);
softSet("iso_sensitivity_auto", 1);
softSet("iso_sensitivity", 1); // Manual ISO adjustment by default
softSet("white_balance_auto_preset", 1); // Auto white-balance enabled
softSet("white_balance_automatic", 1);
autoExposureProp.set(PROP_AUTO_EXPOSURE_ENABLED);
}
}
Expand Down Expand Up @@ -302,4 +348,15 @@ protected Optional<VideoProperty> findProperty(String... options) {

return Optional.ofNullable(retProp);
}


@Override
public double getMaxWhiteBalanceTemp() {
return wbTempProp.getMax();
}

@Override
public double getMinWhiteBalanceTemp() {
return wbTempProp.getMin();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import org.photonvision.vision.processes.VisionSourceSettables;

public class USBFrameProvider extends CpuImageProcessor {
private static final Logger logger = new Logger(USBFrameProvider.class, LogGroup.Camera);
private final Logger logger;

private final CvSink cvSink;

Expand All @@ -33,6 +33,8 @@ public class USBFrameProvider extends CpuImageProcessor {

@SuppressWarnings("SpellCheckingInspection")
public USBFrameProvider(CvSink sink, VisionSourceSettables visionSettables) {
logger = new Logger(USBFrameProvider.class, sink.getName(), LogGroup.Camera);

cvSink = sink;
cvSink.setEnabled(true);
this.settables = visionSettables;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ public class CVPipelineSettings implements Cloneable {
public boolean inputShouldShow = false;
public boolean outputShouldShow = true;

public boolean cameraAutoWhiteBalance = false;
public double whiteBalanceTemp = 4000;

@Override
public boolean equals(Object o) {
if (this == o) return true;
Expand Down
Loading

0 comments on commit 0ef1c30

Please sign in to comment.