diff --git a/photon-core/src/main/java/org/photonvision/common/configuration/CameraConfiguration.java b/photon-core/src/main/java/org/photonvision/common/configuration/CameraConfiguration.java index 145110de27..211f3cb8d2 100644 --- a/photon-core/src/main/java/org/photonvision/common/configuration/CameraConfiguration.java +++ b/photon-core/src/main/java/org/photonvision/common/configuration/CameraConfiguration.java @@ -1,16 +1,18 @@ /* * 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 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. + * 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 . + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package org.photonvision.common.configuration; diff --git a/photon-core/src/main/java/org/photonvision/vision/processes/VisionSourceManager.java b/photon-core/src/main/java/org/photonvision/vision/processes/VisionSourceManager.java index 496d6c01ae..f71bd9d926 100644 --- a/photon-core/src/main/java/org/photonvision/vision/processes/VisionSourceManager.java +++ b/photon-core/src/main/java/org/photonvision/vision/processes/VisionSourceManager.java @@ -30,6 +30,7 @@ import org.photonvision.common.dataflow.DataChangeService; import org.photonvision.common.dataflow.events.OutgoingUIEvent; import org.photonvision.common.hardware.Platform; +import org.photonvision.common.hardware.Platform.OSType; import org.photonvision.common.logging.LogGroup; import org.photonvision.common.logging.Logger; import org.photonvision.common.util.TimedTaskManager; @@ -128,20 +129,26 @@ protected List tryMatchCamImpl() { return tryMatchCamImpl(null); } + protected List tryMatchCamImpl(ArrayList cameraInfos) { + return tryMatchCamImpl(cameraInfos, Platform.getCurrentPlatform()); + } + /** * @param cameraInfos Used to feed camera info for unit tests. * @return New VisionSources. */ - protected List tryMatchCamImpl(ArrayList cameraInfos) { + protected List tryMatchCamImpl( + ArrayList cameraInfos, Platform platform) { boolean createSources = true; List connectedCameras; if (cameraInfos == null) { // Detect USB cameras using CSCore - connectedCameras = new ArrayList<>(filterAllowedDevices(getConnectedUSBCameras())); + connectedCameras = new ArrayList<>(filterAllowedDevices(getConnectedUSBCameras(), platform)); // Detect CSI cameras using libcamera - connectedCameras.addAll(new ArrayList<>(filterAllowedDevices(getConnectedCSICameras()))); + connectedCameras.addAll( + new ArrayList<>(filterAllowedDevices(getConnectedCSICameras(), platform))); } else { - connectedCameras = new ArrayList<>(filterAllowedDevices(cameraInfos)); + connectedCameras = new ArrayList<>(filterAllowedDevices(cameraInfos, platform)); createSources = false; // Dont create sources if we are using supplied camerainfo for unit tests. } @@ -317,8 +324,7 @@ public List matchCameras( matchCamerasByStrategy( detectedCameraList, unloadedConfigs, - new CameraMatchingOptions(false, true, true, true, - CameraType.UsbCamera))); + new CameraMatchingOptions(false, true, true, true, CameraType.UsbCamera))); } logger.info("Matching USB cameras by usb port & USB VID/PID..."); @@ -522,7 +528,7 @@ public void setIgnoredCamerasRegex(String ignoredCamerasRegex) { * @param allDevices * @return list of devices with blacklisted or ignore devices removed. */ - private List filterAllowedDevices(List allDevices) { + private List filterAllowedDevices(List allDevices, Platform platform) { List filteredDevices = new ArrayList<>(); for (var device : allDevices) { if (deviceBlacklist.contains(device.name)) { @@ -531,9 +537,13 @@ private List filterAllowedDevices(List allDevices) { } else if (device.name.matches(ignoredCamerasRegex)) { logger.trace("Skipping ignored device: \"" + device.name + "\" at \"" + device.path); } else if (device.getIsV4lCsiCamera()) { - } else if (device.otherPaths.length == 0 && !Platform.isWindows() && device.cameraType == CameraType.UsbCamera) { - logger.trace("Skipping device with no other paths: \"" + device.name + "\" at \"" + device.path); - // If cscore hasnt passed this other paths aka a path by id or a path as in usb port then we cant guarantee it is a valid camera. + } else if (device.otherPaths.length == 0 + && platform.osType == OSType.LINUX + && device.cameraType == CameraType.UsbCamera) { + logger.trace( + "Skipping device with no other paths: \"" + device.name + "\" at \"" + device.path); + // If cscore hasnt passed this other paths aka a path by id or a path as in usb port then we + // cant guarantee it is a valid camera. } else { filteredDevices.add(device); logger.trace( @@ -547,7 +557,6 @@ private static List loadVisionSourcesFromCamConfigs( List camConfigs, boolean createSources) { var cameraSources = new ArrayList(); for (var configuration : camConfigs) { - // In unit tests, create dummy if (!createSources) { cameraSources.add(new TestSource(configuration)); @@ -566,10 +575,8 @@ private static List loadVisionSourcesFromCamConfigs( && !newCam.getSettables().videoModes.isEmpty()) { cameraSources.add(newCam); } - } logger.debug("Creating VisionSource for " + configuration.toShortString()); - } return cameraSources; } diff --git a/photon-core/src/test/java/org/photonvision/vision/processes/VisionSourceManagerTest.java b/photon-core/src/test/java/org/photonvision/vision/processes/VisionSourceManagerTest.java index 7f4755376a..db8a3969ba 100644 --- a/photon-core/src/test/java/org/photonvision/vision/processes/VisionSourceManagerTest.java +++ b/photon-core/src/test/java/org/photonvision/vision/processes/VisionSourceManagerTest.java @@ -17,14 +17,14 @@ package org.photonvision.vision.processes; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.Test; import org.photonvision.common.configuration.CameraConfiguration; import org.photonvision.common.configuration.ConfigManager; +import org.photonvision.common.hardware.Platform; import org.photonvision.common.logging.LogGroup; import org.photonvision.common.logging.LogLevel; import org.photonvision.common.logging.Logger; @@ -500,6 +500,43 @@ public void testCSICameraMatching() { } } + @Test + public void testNoOtherPaths() { + Logger.setLevel(LogGroup.Camera, LogLevel.DEBUG); + + // List of known cameras + var cameraInfos = new ArrayList(); + + var inst = new VisionSourceManager(); + ConfigManager.getInstance().clearConfig(); + ConfigManager.getInstance().load(); + ConfigManager.getInstance().getConfig().getNetworkConfig().matchCamerasOnlyByPath = false; + + // Match empty camera infos + inst.tryMatchCamImpl(cameraInfos); + + CameraInfo info1 = + new CameraInfo(0, "/dev/video0", "Arducam OV2311 USB Camera", new String[] {}, 3141, 25446); + + cameraInfos.add(info1); + + // Match two "new" cameras + var ret1 = inst.tryMatchCamImpl(cameraInfos, Platform.LINUX_64); + + // Our cameras should be "known" + assertFalse(inst.knownCameras.contains(info1)); + assertEquals(0, inst.knownCameras.size()); + assertEquals(null, ret1); + + // Match two "new" cameras + var ret2 = inst.tryMatchCamImpl(cameraInfos, Platform.WINDOWS_64); + + // Our cameras should be "known" + assertTrue(inst.knownCameras.contains(info1)); + assertEquals(1, inst.knownCameras.size()); + assertEquals(1, ret2.size()); + } + @Test public void testIdenticalCameras() { Logger.setLevel(LogGroup.Camera, LogLevel.DEBUG); diff --git a/photon-targeting/src/main/java/org/photonvision/common/hardware/Platform.java b/photon-targeting/src/main/java/org/photonvision/common/hardware/Platform.java index e2d0155609..fdb51c2792 100644 --- a/photon-targeting/src/main/java/org/photonvision/common/hardware/Platform.java +++ b/photon-targeting/src/main/java/org/photonvision/common/hardware/Platform.java @@ -54,7 +54,7 @@ public enum Platform { LINUX_ARM32("Linux ARM32", "linuxarm32", false, OSType.LINUX, false), // ODROID XU4, C1+ UNKNOWN("Unsupported Platform", "", false, OSType.UNKNOWN, false); - private enum OSType { + public enum OSType { WINDOWS, LINUX, MACOS, @@ -123,7 +123,7 @@ public static boolean isSupported() { private static final String UnknownPlatformString = String.format("Unknown Platform. OS: %s, Architecture: %s", OS_NAME, OS_ARCH); - private static Platform getCurrentPlatform() { + public static Platform getCurrentPlatform() { if (RuntimeDetector.isWindows()) { if (RuntimeDetector.is32BitIntel()) { return WINDOWS_32;