Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Camera Index Assignment. #1031

Merged
merged 9 commits into from
Dec 1, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

package org.photonvision.vision.camera;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
Expand Down Expand Up @@ -108,8 +110,20 @@ public static QuirkyCamera getQuirkyCamera(int usbVid, int usbPid, String baseNa
for (var qc : quirkyCameras) {
boolean hasBaseName = !qc.baseName.isEmpty();
boolean matchesBaseName = qc.baseName.equals(baseName) || !hasBaseName;
// If we have a quirkycamera we need to copy the quirks from our predefined object and create
// a quirkycamera object with the baseName.
if (qc.usbVid == usbVid && qc.usbPid == usbPid && matchesBaseName) {
return qc;
List<CameraQuirk> quirks = new ArrayList<CameraQuirk>();
for (var q : CameraQuirk.values()) {
if (qc.hasQuirk(q)) quirks.add(q);
}
QuirkyCamera c =
new QuirkyCamera(
usbVid,
usbPid,
baseName,
Arrays.copyOf(quirks.toArray(), quirks.size(), CameraQuirk[].class));
return c;
}
}
return new QuirkyCamera(usbVid, usbPid, baseName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@
import org.photonvision.common.configuration.ConfigManager;
import org.photonvision.common.logging.LogGroup;
import org.photonvision.common.logging.Logger;
import org.photonvision.common.util.TestUtils;
import org.photonvision.vision.frame.FrameProvider;
import org.photonvision.vision.frame.provider.FileFrameProvider;
import org.photonvision.vision.frame.provider.USBFrameProvider;
import org.photonvision.vision.processes.VisionSource;
import org.photonvision.vision.processes.VisionSourceSettables;
Expand All @@ -37,10 +39,10 @@ public class USBCameraSource extends VisionSource {
private final Logger logger;
private final UsbCamera camera;
private final USBCameraSettables usbCameraSettables;
private final USBFrameProvider usbFrameProvider;
private FrameProvider usbFrameProvider;
private final CvSink cvSink;

public final QuirkyCamera cameraQuirks;
private QuirkyCamera cameraQuirks;

public USBCameraSource(CameraConfiguration config) {
super(config);
Expand Down Expand Up @@ -77,6 +79,22 @@ 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);

cameraQuirks = QuirkyCamera.getQuirkyCamera(pid, vid, config.baseName);

if (unitTest)
usbFrameProvider =
new FileFrameProvider(
TestUtils.getWPIImagePath(
TestUtils.WPI2019Image.kCargoStraightDark72in_HighRes, false),
TestUtils.WPI2019Image.FOV);
}

void disableAutoFocus() {
if (cameraQuirks.hasQuirk(CameraQuirk.AdjustableFocus)) {
try {
Expand All @@ -88,6 +106,10 @@ void disableAutoFocus() {
}
}

public QuirkyCamera getCameraQuirks() {
return this.cameraQuirks;
}

@Override
public FrameProvider getFrameProvider() {
return usbFrameProvider;
Expand All @@ -103,7 +125,7 @@ protected USBCameraSettables(CameraConfiguration configuration) {
super(configuration);
getAllVideoModes();
if (!cameraQuirks.hasQuirk(CameraQuirk.StickyFPS))
setVideoMode(videoModes.get(0)); // fixes double FPS set
if (!videoModes.isEmpty()) setVideoMode(videoModes.get(0)); // fixes double FPS set
}

public void setAutoExposure(boolean cameraAutoExposure) {
Expand Down Expand Up @@ -343,11 +365,27 @@ public boolean isVendorCamera() {
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
USBCameraSource that = (USBCameraSource) o;
return cameraQuirks.equals(that.cameraQuirks);
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
USBCameraSource other = (USBCameraSource) obj;
if (camera == null) {
if (other.camera != null) return false;
} else if (!camera.equals(other.camera)) return false;
if (usbCameraSettables == null) {
if (other.usbCameraSettables != null) return false;
} else if (!usbCameraSettables.equals(other.usbCameraSettables)) return false;
if (usbFrameProvider == null) {
if (other.usbFrameProvider != null) return false;
} else if (!usbFrameProvider.equals(other.usbFrameProvider)) return false;
if (cvSink == null) {
if (other.cvSink != null) return false;
} else if (!cvSink.equals(other.cvSink)) return false;
if (cameraQuirks == null) {
if (other.cameraQuirks != null) return false;
} else if (!cameraQuirks.equals(other.cameraQuirks)) return false;
return true;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public VisionModule(PipelineManager pipelineManager, VisionSource visionSource,

// Find quirks for the current camera
if (visionSource instanceof USBCameraSource) {
cameraQuirks = ((USBCameraSource) visionSource).cameraQuirks;
cameraQuirks = ((USBCameraSource) visionSource).getCameraQuirks();
} else if (visionSource instanceof LibcameraGpuSource) {
cameraQuirks = QuirkyCamera.ZeroCopyPiCamera;
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ private static List<VisionSource> loadVisionSourcesFromCamConfigs(
cameraSources.add(piCamSrc);
} else {
var newCam = new USBCameraSource(configuration);
if (!newCam.cameraQuirks.hasQuirk(CameraQuirk.CompletelyBroken)
if (!newCam.getCameraQuirks().hasQuirk(CameraQuirk.CompletelyBroken)
&& !newCam.getSettables().videoModes.isEmpty()) {
cameraSources.add(newCam);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public void setBlueGain(int blue) {}
public abstract VideoMode getCurrentVideoMode();

public void setVideoModeInternal(int index) {
setVideoMode(getAllVideoModes().get(index));
if (!getAllVideoModes().isEmpty()) setVideoMode(getAllVideoModes().get(index));
}

public void setVideoMode(VideoMode mode) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.photonvision.common.configuration.ConfigManager;
import org.photonvision.common.dataflow.CVPipelineResultConsumer;
import org.photonvision.common.util.TestUtils;
import org.photonvision.vision.camera.USBCameraSource;
import org.photonvision.vision.frame.FrameProvider;
import org.photonvision.vision.frame.FrameStaticProperties;
import org.photonvision.vision.frame.provider.FileFrameProvider;
Expand Down Expand Up @@ -165,7 +166,16 @@ public void testMultipleStreamIndex() {
TestUtils.WPI2019Image.FOV);
var testSource3 = new TestSource(ffp3, conf3);

var modules = vmm.addSources(List.of(testSource, testSource2, testSource3));
// Arducam OV9281 UC844 raspberry pi test.
var conf4 = new CameraConfiguration("Left", "dev/video1");
USBCameraSource usbSimulation = new USBCameraSource(conf4, 0x6366, 0x0c45, true);

var conf5 = new CameraConfiguration("Right", "dev/video2");
USBCameraSource usbSimulation2 = new USBCameraSource(conf5, 0x6366, 0x0c45, true);

var modules =
vmm.addSources(
List.of(testSource, testSource2, testSource3, usbSimulation, usbSimulation2));

System.out.println(
Arrays.toString(
Expand All @@ -176,9 +186,15 @@ public void testMultipleStreamIndex() {
modules.stream()
.map(it -> it.visionSource.getCameraConfiguration().streamIndex)
.collect(Collectors.toList());

assertTrue(usbSimulation.equals(usbSimulation));
assertTrue(!usbSimulation.equals(usbSimulation2));

assertTrue(idxs.contains(0));
assertTrue(idxs.contains(1));
assertTrue(idxs.contains(2));
assertTrue(idxs.contains(3));
assertTrue(idxs.contains(4));
}

private static void printTestResults(CVPipelineResult pipelineResult) {
Expand Down