Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,6 @@ public enum CameraQuirk {
ArduOV9782,
/** Camera has odd exposure range, and supports gain control */
See3Cam_24CUG,
/** Thrifty OV9281 */
ThriftyOV9281Controls,
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,9 @@ public class QuirkyCamera {
CameraQuirk.ArduOV9782Controls),
// Innomaker OV9281
new QuirkyCamera(
0x0c45, 0x636d, "USB Camera", "Innomaker OV9281", CameraQuirk.InnoOV9281Controls));
0x0c45, 0x636d, "USB Camera", "Innomaker OV9281", CameraQuirk.InnoOV9281Controls),
// Thrifty OV9281
new QuirkyCamera(0x1BCF, 0x28C5, CameraQuirk.ThriftyOV9281Controls, CameraQuirk.Gain));

public static final QuirkyCamera DefaultCamera = new QuirkyCamera(0, 0, "");
public static final QuirkyCamera ZeroCopyPiCamera =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/

package org.photonvision.vision.camera.USBCameras;

import org.photonvision.common.configuration.CameraConfiguration;
import org.wpilib.util.PixelFormat;
import org.wpilib.vision.camera.UsbCamera;

public class ThriftyOV9281CameraSettables extends GenericUSBCameraSettables {

public ThriftyOV9281CameraSettables(CameraConfiguration configuration, UsbCamera camera) {
super(configuration, camera);
}

@Override
protected void setUpExposureProperties() {
super.setUpExposureProperties();

// Fix the exposure lower and upper limits.
// The minimum usable exposure is above the UI default of 20, so

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if there's a way to choose saner defaults based on camera model, or to use real units like milliseconds here

// the user is expected to increase exposure until the camera can
// pick up an image correctly.
this.minExposure = 1;
this.maxExposure = 2400;
}

@Override
public void onCameraConnected() {
super.onCameraConnected();

// Filter out YUYV modes. The Sunplus SPCA2688 ISP's MJPEG encoder
// breaks permanently if a YUYV↔MJPEG format switch occurs.
// Only MJPEG modes (120fps) are usable; YUYV modes are 5-30fps anyway.
int originalSize = videoModes.size();
videoModes.removeIf(m -> m.pixelFormat != PixelFormat.MJPEG);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OnCameraConnected is the first time video modes can be enumerated but perhaps the code that actually grabs video modes should be the thing to care here instead? Having stables mutate camera state feels like an anti pattern

if (videoModes.size() < originalSize) {
logger.info("Filtered to " + videoModes.size() + " MJPEG-only modes (YUYV removed)");
}
}

@Override
public void setAllCamDefaults() {
// Disable continuous autofocus BEFORE super tries to set focus_absolute
softSet("focus_automatic_continuous", 0);
super.setAllCamDefaults();
logger.info("Setting All Cam Defaults :: ThriftyOV9281");
softSet("focus_absolute", 0);
}

@Override
public void setAutoExposureImpl(boolean cameraAutoExposure) {
logger.debug("Setting auto exposure :: ThriftyOV9281 :: " + cameraAutoExposure);
if (autoExposureProp != null) {
autoExposureProp.set(
cameraAutoExposure ? PROP_AUTO_EXPOSURE_ENABLED : PROP_AUTO_EXPOSURE_DISABLED);
}
if (!cameraAutoExposure) {
setExposureRaw(this.lastExposureRaw);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ protected GenericUSBCameraSettables createSettables(
settables = new InnoOV9281CameraSettables(config, camera);
} else if (quirks.hasQuirk(CameraQuirk.See3Cam_24CUG)) {
settables = new See3Cam24CUGSettables(config, camera);
} else if (quirks.hasQuirk(CameraQuirk.ThriftyOV9281Controls)) {
logger.debug("Using Thrifty OV9281 Settables");
settables = new ThriftyOV9281CameraSettables(config, camera);
} else {
logger.debug("Using Generic USB Cam Settables");
settables = new GenericUSBCameraSettables(config, camera);
Expand Down
Loading