diff --git a/photon-client/src/types/SettingTypes.ts b/photon-client/src/types/SettingTypes.ts
index cd3ac8883e..4f17096c1f 100644
--- a/photon-client/src/types/SettingTypes.ts
+++ b/photon-client/src/types/SettingTypes.ts
@@ -148,6 +148,7 @@ export interface CameraCalibrationResult {
export enum ValidQuirks {
AWBGain = "AWBGain",
AdjustableFocus = "AdjustableFocus",
+ InnoOV9281Controls = "InnoOV9281Controls",
ArduOV9281Controls = "ArduOV9281Controls",
ArduOV2311Controls = "ArduOV2311Controls",
ArduOV9782Controls = "ArduOV9782Controls",
diff --git a/photon-core/src/main/java/org/photonvision/vision/camera/CameraQuirk.java b/photon-core/src/main/java/org/photonvision/vision/camera/CameraQuirk.java
index 22253f8986..9258c53b42 100644
--- a/photon-core/src/main/java/org/photonvision/vision/camera/CameraQuirk.java
+++ b/photon-core/src/main/java/org/photonvision/vision/camera/CameraQuirk.java
@@ -37,11 +37,16 @@ public enum CameraQuirk {
/** Camera is an arducam. This means it shares VID/PID with other arducams (ew) */
ArduCamCamera,
/**
- * Camera is an arducam ov9281 which has a funky exposure issue where it is defined in v4l as
+ * Camera is an arducam USB ov9281 which has a funky exposure issue where it is defined in v4l as
* 1-5000 instead of 1-75
*/
ArduOV9281Controls,
/** Dummy quirk to tell OV2311 from OV9281 */
ArduOV2311Controls,
ArduOV9782Controls,
+ /**
+ * Camera is innomaker USB OV9281 which also has incorrect v4l exposure times Real range is more
+ * like 0-500
+ */
+ InnoOV9281Controls,
}
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 ecb3b56b89..ab3dea261e 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
@@ -74,6 +74,12 @@ public boolean isVendorCamera() {
return false;
}
+ @Override
+ public void remakeSettables() {
+ // Nothing to do, settables for this type of VisionSource should never be remade.
+ return;
+ }
+
@Override
public boolean hasLEDs() {
return false; // Assume USB cameras do not have photonvision-controlled LEDs
diff --git a/photon-core/src/main/java/org/photonvision/vision/camera/LibcameraGpuSource.java b/photon-core/src/main/java/org/photonvision/vision/camera/LibcameraGpuSource.java
index 6783f61e3c..8db27a5d73 100644
--- a/photon-core/src/main/java/org/photonvision/vision/camera/LibcameraGpuSource.java
+++ b/photon-core/src/main/java/org/photonvision/vision/camera/LibcameraGpuSource.java
@@ -58,6 +58,12 @@ public VisionSourceSettables getSettables() {
return settables;
}
+ @Override
+ public void remakeSettables() {
+ // Nothing to do, settables for this type of VisionSource should never be remade.
+ return;
+ }
+
/**
* On the OV5649 the actual FPS we want to request from the GPU can be higher than the FPS that we
* can do after processing. On the IMX219 these FPSes match pretty closely, except for the
diff --git a/photon-core/src/main/java/org/photonvision/vision/camera/QuirkyCamera.java b/photon-core/src/main/java/org/photonvision/vision/camera/QuirkyCamera.java
index f21b0e560a..2eb1982fd9 100644
--- a/photon-core/src/main/java/org/photonvision/vision/camera/QuirkyCamera.java
+++ b/photon-core/src/main/java/org/photonvision/vision/camera/QuirkyCamera.java
@@ -80,7 +80,10 @@ public class QuirkyCamera {
"OV9782",
"OV9782",
CameraQuirk.ArduCamCamera,
- CameraQuirk.ArduOV9782Controls));
+ CameraQuirk.ArduOV9782Controls),
+ // Innomaker OV9281
+ new QuirkyCamera(
+ 0x0c45, 0x636d, "USB Camera", "USB Camera", CameraQuirk.InnoOV9281Controls));
public static final QuirkyCamera DefaultCamera = new QuirkyCamera(0, 0, "");
public static final QuirkyCamera ZeroCopyPiCamera =
diff --git a/photon-core/src/main/java/org/photonvision/vision/camera/TestSource.java b/photon-core/src/main/java/org/photonvision/vision/camera/TestSource.java
index deef4b69a8..38b8b56afc 100644
--- a/photon-core/src/main/java/org/photonvision/vision/camera/TestSource.java
+++ b/photon-core/src/main/java/org/photonvision/vision/camera/TestSource.java
@@ -38,6 +38,12 @@ public TestSource(CameraConfiguration config) {
QuirkyCamera.getQuirkyCamera(config.usbVID, config.usbVID, config.baseName);
}
+ @Override
+ public void remakeSettables() {
+ // Nothing to do, settables for this type of VisionSource should never be remade.
+ return;
+ }
+
@Override
public FrameProvider getFrameProvider() {
return new FrameProvider() {
diff --git a/photon-core/src/main/java/org/photonvision/vision/camera/USBCameras/InnoOV9281CameraSettables.java b/photon-core/src/main/java/org/photonvision/vision/camera/USBCameras/InnoOV9281CameraSettables.java
new file mode 100644
index 0000000000..3cb710e5aa
--- /dev/null
+++ b/photon-core/src/main/java/org/photonvision/vision/camera/USBCameras/InnoOV9281CameraSettables.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Photon Vision.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package org.photonvision.vision.camera.USBCameras;
+
+import edu.wpi.first.cscore.UsbCamera;
+import org.photonvision.common.configuration.CameraConfiguration;
+
+public class InnoOV9281CameraSettables extends GenericUSBCameraSettables {
+ public InnoOV9281CameraSettables(CameraConfiguration configuration, UsbCamera camera) {
+ super(configuration, camera);
+ }
+
+ @Override
+ protected void setUpExposureProperties() {
+ super.setUpExposureProperties();
+
+ // Property limits are incorrect
+ this.minExposure = 1;
+ this.maxExposure = 500;
+ }
+}
diff --git a/photon-core/src/main/java/org/photonvision/vision/camera/USBCameras/USBCameraSource.java b/photon-core/src/main/java/org/photonvision/vision/camera/USBCameras/USBCameraSource.java
index 56cb8b699f..433c5d7666 100644
--- a/photon-core/src/main/java/org/photonvision/vision/camera/USBCameras/USBCameraSource.java
+++ b/photon-core/src/main/java/org/photonvision/vision/camera/USBCameras/USBCameraSource.java
@@ -94,7 +94,6 @@ public USBCameraSource(CameraConfiguration config) {
} else {
// Functional camera, set up the frame provider and configure defaults
usbFrameProvider = new USBFrameProvider(cvSink, settables);
- settables.setUpExposureProperties();
settables.setAllCamDefaults();
}
}
@@ -128,18 +127,33 @@ private GenericUSBCameraSettables createSettables(CameraConfiguration config, Us
settables = new ArduOV2311CameraSettables(config, camera);
} else if (quirks.hasQuirk(CameraQuirk.ArduOV9281Controls)) {
logger.debug("Using Arducam OV9281 Settables");
- settables = new ArduOV9281CameraSettables(config, camera);
+ settables = new InnoOV9281CameraSettables(config, camera);
} else if (quirks.hasQuirk(CameraQuirk.ArduOV9782Controls)) {
logger.debug("Using Arducam OV9782 Settables");
settables = new ArduOV9782CameraSettables(config, camera);
+ } else if (quirks.hasQuirk(CameraQuirk.InnoOV9281Controls)) {
+ settables = new InnoOV9281CameraSettables(config, camera);
} else {
logger.debug("Using Generic USB Cam Settables");
settables = new GenericUSBCameraSettables(config, camera);
}
+ settables.setUpExposureProperties();
+
return settables;
}
+ /**
+ * Must be called after createSettables Using the current config/camera and modified quirks, make
+ * a new settables
+ */
+ public void remakeSettables() {
+ var oldConfig = this.cameraConfiguration;
+ var oldCamera = this.camera;
+
+ this.settables = createSettables(oldConfig, oldCamera);
+ }
+
private void printCameraProperaties() {
VideoProperty[] cameraProperties = null;
try {
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 4941a0b072..02c66393b7 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
@@ -621,6 +621,7 @@ public void addCalibrationToConfig(CameraCalibrationCoefficients newCalibration)
*/
public void changeCameraQuirks(HashMap quirksToChange) {
visionSource.getCameraConfiguration().cameraQuirks.updateQuirks(quirksToChange);
+ visionSource.remakeSettables();
saveAndBroadcastAll();
}
}
diff --git a/photon-core/src/main/java/org/photonvision/vision/processes/VisionSource.java b/photon-core/src/main/java/org/photonvision/vision/processes/VisionSource.java
index dd0ff14f8e..618d4fa144 100644
--- a/photon-core/src/main/java/org/photonvision/vision/processes/VisionSource.java
+++ b/photon-core/src/main/java/org/photonvision/vision/processes/VisionSource.java
@@ -38,4 +38,6 @@ public CameraConfiguration getCameraConfiguration() {
public abstract boolean isVendorCamera();
public abstract boolean hasLEDs();
+
+ public abstract void remakeSettables();
}
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 330d6968d8..ccb7473739 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
@@ -73,6 +73,11 @@ public boolean isVendorCamera() {
public boolean hasLEDs() {
return false;
}
+
+ @Override
+ public void remakeSettables() {
+ return;
+ }
}
private static class TestSettables extends VisionSourceSettables {