mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-20 00:51:41 +00:00
Camera de/serialization, folder management
This commit is contained in:
@@ -15,6 +15,8 @@ import edu.wpi.first.networktables.NetworkTableInstance;
|
||||
import java.io.IOException;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static com.chameleonvision.settings.Platform.CurrentPlatform;
|
||||
|
||||
public class Main {
|
||||
|
||||
private static final String NT_SERVERMODE_KEY = "--nt-servermode"; // no args for this setting
|
||||
@@ -44,8 +46,6 @@ public class Main {
|
||||
}
|
||||
}
|
||||
|
||||
private static final Platform CurrentPlatform = Platform.getCurrentPlatform();
|
||||
|
||||
private static void handleArgs(String[] args) {
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
var key = args[i].toLowerCase();
|
||||
@@ -127,13 +127,13 @@ public class Main {
|
||||
CameraServerJNI.forceLoad();
|
||||
CameraServerCvJNI.forceLoad();
|
||||
} catch (UnsatisfiedLinkError | IOException e) {
|
||||
if(Platform.getCurrentPlatform().isWindows())
|
||||
if(CurrentPlatform.isWindows()) {
|
||||
System.err.println("Try to download the VC++ Redistributable, https://aka.ms/vs/16/release/vc_redist.x64.exe");
|
||||
}
|
||||
throw new RuntimeException("Failed to load JNI Libraries!");
|
||||
}
|
||||
|
||||
if (testMode) {
|
||||
// todo: boot in to the new classabstraction stuff
|
||||
boolean visionSourcesOk = VisionManager.initializeSources();
|
||||
if (!visionSourcesOk) {
|
||||
System.out.println("No cameras connected!");
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.chameleonvision.classabstraction;
|
||||
|
||||
import com.chameleonvision.settings.SettingsManager;
|
||||
import com.chameleonvision.util.FileHelper;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import edu.wpi.cscore.UsbCamera;
|
||||
import edu.wpi.cscore.UsbCameraInfo;
|
||||
import org.opencv.videoio.VideoCapture;
|
||||
@@ -46,19 +48,39 @@ public class VisionManager {
|
||||
UsbCameraInfosByCameraName.forEach((cameraName, cameraInfo) -> {
|
||||
Path cameraConfigFolder = Paths.get(CamConfigPath.toString(), String.format("%s\\", cameraName));
|
||||
Path cameraConfigPath = Paths.get(cameraConfigFolder.toString(), String.format("%s.json", cameraName));
|
||||
Path cameraPipelinesPath = Paths.get(cameraConfigFolder.toString(), "pipelines.json");
|
||||
Path cameraDrivermodePath = Paths.get(cameraConfigFolder.toString(), "drivermode.json");
|
||||
|
||||
if (Files.exists(cameraConfigFolder)) {
|
||||
if (Files.exists(cameraConfigPath)) {
|
||||
File cameraConfigFile = new File(cameraConfigPath.toString());
|
||||
try {
|
||||
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
boolean cameraFolderExists = Files.exists(cameraConfigFolder);
|
||||
|
||||
if (!cameraFolderExists) {
|
||||
Files.createDirectory(cameraConfigFolder);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
boolean cameraConfigExists = cameraFolderExists && Files.exists(cameraConfigPath);
|
||||
|
||||
if (Files.exists(cameraConfigFolder)) {
|
||||
if (Files.exists(cameraConfigPath)) {
|
||||
File cameraConfigFile = new File(cameraConfigPath.toString());
|
||||
if (cameraConfigFile.length() != 0) {
|
||||
try {
|
||||
Gson gson = new GsonBuilder().create();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Files.createFile(cameraConfigPath);
|
||||
}
|
||||
} else {
|
||||
Files.createDirectory(cameraConfigFolder);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
// FileHelper.CheckPath(CamConfigPath);
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package com.chameleonvision.classabstraction.camera;
|
||||
|
||||
import com.chameleonvision.Main;
|
||||
import com.chameleonvision.settings.Platform;
|
||||
import edu.wpi.cscore.UsbCamera;
|
||||
import edu.wpi.cscore.UsbCameraInfo;
|
||||
import edu.wpi.cscore.VideoMode;
|
||||
import org.apache.commons.math3.util.FastMath;
|
||||
|
||||
@@ -25,12 +28,36 @@ public class CameraProperties {
|
||||
private static final Predicate<VideoMode> kPixelFormatPredicate = (videoMode -> ALLOWED_PIXEL_FORMATS.contains(videoMode.pixelFormat));
|
||||
|
||||
public CameraStaticProperties staticProperties;
|
||||
public final String name;
|
||||
public final String path;
|
||||
public final double FOV;
|
||||
public final List<VideoMode> videoModes;
|
||||
|
||||
private String nickname;
|
||||
|
||||
public CameraProperties(UsbCamera baseCamera, double fov) {
|
||||
FOV = fov;
|
||||
videoModes = filterVideoModes(baseCamera.enumerateVideoModes());
|
||||
name = baseCamera.getName();
|
||||
|
||||
UsbCameraInfo baseCamInfo = baseCamera.getInfo();
|
||||
|
||||
if (Platform.CurrentPlatform.isWindows()) {
|
||||
path = baseCamInfo.path;
|
||||
} else {
|
||||
var truePath = Arrays.stream(baseCamInfo.otherPaths).filter(x -> x.contains("/dev/v4l/by-path")).findFirst();
|
||||
path = truePath.orElse(baseCamInfo.path);
|
||||
}
|
||||
|
||||
nickname = name;
|
||||
}
|
||||
|
||||
public void setNickname(String nickname) {
|
||||
this.nickname = nickname;
|
||||
}
|
||||
|
||||
public String getNickname() {
|
||||
return nickname;
|
||||
}
|
||||
|
||||
private List<VideoMode> filterVideoModes(VideoMode[] videoModes) {
|
||||
|
||||
@@ -13,7 +13,7 @@ public class USBCameraProcess implements CameraProcess {
|
||||
private final UsbCamera baseCamera;
|
||||
private final CvSink cvSink;
|
||||
private Mat imageBuffer = new Mat();
|
||||
public CameraProperties properties;
|
||||
private CameraProperties properties;
|
||||
|
||||
public USBCameraProcess(UsbCamera camera, CameraConfig config) {
|
||||
baseCamera = camera;
|
||||
|
||||
@@ -5,6 +5,5 @@ public class CameraConfig {
|
||||
public String Path;
|
||||
public String Name;
|
||||
public String Nickname;
|
||||
public com.chameleonvision.vision.camera.StreamDivisor StreamDivisor;
|
||||
// public
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.chameleonvision.classabstraction.config;
|
||||
|
||||
import com.chameleonvision.classabstraction.camera.CameraProperties;
|
||||
import com.chameleonvision.classabstraction.camera.USBCameraProcess;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class CameraSerializer extends StdSerializer<USBCameraProcess> {
|
||||
public CameraSerializer(Class<USBCameraProcess> t) {
|
||||
super(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(USBCameraProcess value, JsonGenerator gen, SerializerProvider provider) throws IOException {
|
||||
gen.writeStartObject();
|
||||
CameraProperties camProps = value.getProperties();
|
||||
gen.writeNumberField("FOV", camProps.FOV);
|
||||
gen.writeStringField("Name", camProps.name);
|
||||
gen.writeStringField("Path", camProps.path);
|
||||
gen.writeStringField("Nickname", camProps.getNickname());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.chameleonvision.classabstraction.config;
|
||||
|
||||
import com.chameleonvision.classabstraction.util.ProgramDirectoryUtilities;
|
||||
import com.chameleonvision.settings.GeneralSettings;
|
||||
import com.chameleonvision.util.FileHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ConfigManager {
|
||||
private ConfigManager() {}
|
||||
|
||||
private static final Path SettingsPath = Paths.get(ProgramDirectoryUtilities.getProgramDirectory(), "settings");
|
||||
private static final Path CamConfigPath = Paths.get(SettingsPath.toString(), "cameras");
|
||||
|
||||
public static GeneralSettings settings = new GeneralSettings();
|
||||
|
||||
public static void initializeSettings() {
|
||||
boolean settingsFolderExists = Files.exists(SettingsPath);
|
||||
|
||||
if (!settingsFolderExists) {
|
||||
try {
|
||||
Files.createDirectory(SettingsPath);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
Path settingsFilePath = Paths.get(SettingsPath.toString(), "settings.json");
|
||||
boolean settingsFileExists = Files.exists(settingsFilePath);
|
||||
|
||||
if (!settingsFileExists) {
|
||||
try {
|
||||
FileHelper.Serializer(settings, settingsFilePath);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
settings = FileHelper.DeSerializer(settingsFilePath, GeneralSettings.class);
|
||||
} catch (IOException e) {
|
||||
System.err.println("Failed to load settings.json, using defaults.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static List<CameraConfig> initializeCameraConfig(List<String> cameraNames) {
|
||||
|
||||
cameraNames.forEach((cameraName) -> {
|
||||
final Path cameraConfigFolder = Paths.get(CamConfigPath.toString(), String.format("%s\\", cameraName));
|
||||
final Path cameraConfigPath = Paths.get(cameraConfigFolder.toString(), String.format("%s.json", cameraName));
|
||||
final Path cameraPipelinesPath = Paths.get(cameraConfigFolder.toString(), "pipelines.json");
|
||||
final Path cameraDrivermodePath = Paths.get(cameraConfigFolder.toString(), "drivermode.json");
|
||||
|
||||
boolean cameraConfigFolderExists = Files.exists(cameraConfigFolder);
|
||||
|
||||
if (!cameraConfigFolderExists) {
|
||||
try {
|
||||
Files.createDirectory(cameraConfigFolder);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.chameleonvision.classabstraction.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
public class ProgramDirectoryUtilities
|
||||
{
|
||||
private static String getJarName()
|
||||
{
|
||||
return new File(ProgramDirectoryUtilities.class.getProtectionDomain()
|
||||
.getCodeSource()
|
||||
.getLocation()
|
||||
.getPath())
|
||||
.getName();
|
||||
}
|
||||
|
||||
private static boolean runningFromJAR()
|
||||
{
|
||||
String jarName = getJarName();
|
||||
return jarName.contains(".jar");
|
||||
}
|
||||
|
||||
public static String getProgramDirectory()
|
||||
{
|
||||
if (runningFromJAR())
|
||||
{
|
||||
return getCurrentJARDirectory();
|
||||
} else
|
||||
{
|
||||
return getCurrentProjectDirectory();
|
||||
}
|
||||
}
|
||||
|
||||
private static String getCurrentProjectDirectory()
|
||||
{
|
||||
return new File("").getAbsolutePath();
|
||||
}
|
||||
|
||||
private static String getCurrentJARDirectory()
|
||||
{
|
||||
try
|
||||
{
|
||||
return new File(ProgramDirectoryUtilities.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParent();
|
||||
} catch (URISyntaxException exception)
|
||||
{
|
||||
exception.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ public enum Platform {
|
||||
|
||||
private static final String OS_NAME = System.getProperty("os.name");
|
||||
private static final String OS_ARCH = System.getProperty("os.arch");
|
||||
public static final Platform CurrentPlatform = getCurrentPlatform();
|
||||
|
||||
public boolean isWindows() {
|
||||
return this == WINDOWS_64;
|
||||
@@ -70,7 +71,7 @@ public enum Platform {
|
||||
}
|
||||
}
|
||||
|
||||
public static Platform getCurrentPlatform() {
|
||||
private static Platform getCurrentPlatform() {
|
||||
if (OS_NAME.contains("Windows")) {
|
||||
if (OS_ARCH.equals("amd64")) return Platform.WINDOWS_64;
|
||||
}
|
||||
|
||||
@@ -27,18 +27,16 @@ public class FileHelper {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Serializer(Object object, Path path) throws IOException {
|
||||
File file = new File(path.toString());
|
||||
PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder().allowIfBaseType(Object.class).build();
|
||||
ObjectMapper objectMapper = JsonMapper.builder().activateDefaultTyping(ptv, ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT).build();
|
||||
objectMapper.writeValue(file,object);
|
||||
objectMapper.writeValue(new File(path.toString()), object);
|
||||
}
|
||||
|
||||
public static Object DeSerializer(Path path,Class<?> ref) throws IOException {
|
||||
File file = new File(path.toString());
|
||||
public static <T> T DeSerializer(Path path, Class<T> ref) throws IOException {
|
||||
PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder().allowIfBaseType(Object.class).build();
|
||||
ObjectMapper objectMapper = JsonMapper.builder().activateDefaultTyping(ptv, ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT).build();
|
||||
Object o = objectMapper.readValue(file, ref);
|
||||
return o;
|
||||
return objectMapper.readValue(new File(path.toString()), ref);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,11 +77,11 @@ public class USBCamera {
|
||||
FOV = fov;
|
||||
name = cameraName;
|
||||
|
||||
if (Platform.getCurrentPlatform().isWindows()) {
|
||||
if (Platform.CurrentPlatform.isWindows()) {
|
||||
path = usbCamInfo.path;
|
||||
} else {
|
||||
var truePath = Arrays.stream(usbCamInfo.otherPaths).filter(x -> x.contains("/dev/v4l/by-path")).findFirst();
|
||||
path = truePath.orElse(null);
|
||||
path = truePath.orElse(usbCamInfo.path);
|
||||
}
|
||||
|
||||
streamDivisor = divisor;
|
||||
@@ -90,7 +90,7 @@ public class USBCamera {
|
||||
this.pipelines = pipelines;
|
||||
|
||||
// set up video modes according to minimums
|
||||
if (Platform.getCurrentPlatform() == Platform.WINDOWS_64 && !UsbCam.isConnected()) {
|
||||
if (Platform.CurrentPlatform == Platform.WINDOWS_64 && !UsbCam.isConnected()) {
|
||||
System.out.print("Waiting on camera... ");
|
||||
long initTimeout = System.nanoTime();
|
||||
while (!UsbCam.isConnected()) {
|
||||
|
||||
Reference in New Issue
Block a user