diff --git a/Main/chameleon-vision.iml b/Main/chameleon-vision.iml
index 487436a6c..d886581e1 100644
--- a/Main/chameleon-vision.iml
+++ b/Main/chameleon-vision.iml
@@ -41,9 +41,9 @@
-
-
-
+
+
+
diff --git a/Main/src/main/java/com/chameleonvision/Main.java b/Main/src/main/java/com/chameleonvision/Main.java
index 7e2046a19..06b65b327 100644
--- a/Main/src/main/java/com/chameleonvision/Main.java
+++ b/Main/src/main/java/com/chameleonvision/Main.java
@@ -16,18 +16,19 @@ import java.util.function.Consumer;
public class Main {
- private static final String PORT_KEY = "--port"; // expects integer
private static final String NT_SERVERMODE_KEY = "--nt-servermode"; // no args for this setting
private static final String NT_CLIENTMODESERVER_KEY = "--nt-client-server"; // expects String representing an IP address (hostnames will be rejected!)
private static final String NETWORK_MANAGE_KEY = "--unmanage-network"; // no args for this setting
- private static final String IGNORE_ROOT = "--ignore-root"; // no args for this setting
+ private static final String IGNORE_ROOT_KEY = "--ignore-root"; // no args for this setting
+ private static final String TEST_MODE_KEY = "--cv-development";
- private static final int DEFAULT_PORT = 8888;
+ private static final int DEFAULT_PORT = 5800;
private static boolean ntServerMode = false;
private static boolean manageNetwork = true;
private static boolean ignoreRoot = false;
private static String ntClientModeServer = null;
+ private static boolean testMode = false;
private static class NTLogger implements Consumer {
@@ -51,7 +52,6 @@ public class Main {
// this switch handles arguments with a value. Add any settings with a value here.
switch (key) {
- case PORT_KEY:
case NT_CLIENTMODESERVER_KEY:
var potentialValue = args[i + 1];
// ensures this "value" isnt null, blank, nor another argument
@@ -62,21 +62,14 @@ public class Main {
break;
case NT_SERVERMODE_KEY:
case NETWORK_MANAGE_KEY:
- case IGNORE_ROOT:
+ case IGNORE_ROOT_KEY:
+ case TEST_MODE_KEY:
// nothing
+ break;
}
// this switch actually handles the arguments.
switch (key) {
- case PORT_KEY:
- System.out.println("INFO - The \"--port\" argument is currently disabled.");
-// try {
-// if (value == null) throw new Exception("Bad or No argument value");
-// webserverPort = Integer.parseInt(value);
-// } catch (Exception ex) {
-// System.err.printf("Argument for port was invalid, starting server at port %d\n", DEFAULT_PORT);
-// }
- break;
case NT_SERVERMODE_KEY:
ntServerMode = true;
break;
@@ -97,8 +90,12 @@ public class Main {
case NETWORK_MANAGE_KEY:
manageNetwork = false;
break;
- case IGNORE_ROOT:
+ case IGNORE_ROOT_KEY:
ignoreRoot = true;
+ break;
+ case TEST_MODE_KEY:
+ testMode = true;
+ break;
}
}
}
@@ -130,30 +127,34 @@ public class Main {
CameraServerCvJNI.forceLoad();
} catch (UnsatisfiedLinkError | IOException e) {
if(Platform.getCurrentPlatform().isWindows())
- System.err.println("Try to download the VC++ Redistributable, see announcements in discord");
+ 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 (CameraManager.initializeCameras()) {
- SettingsManager.initialize();
- NetworkManager.initialize(manageNetwork);
- CameraManager.initializeThreads();
- if (ntServerMode) {
- System.out.println("Starting NT Server");
- NetworkTableInstance.getDefault().startServer();
- } else {
- NetworkTableInstance.getDefault().addLogger(new NTLogger(), 0, 255); // to hide error messages
- if (ntClientModeServer != null) {
- NetworkTableInstance.getDefault().startClient(ntClientModeServer);
- } else {
- NetworkTableInstance.getDefault().startClientTeam(SettingsManager.generalSettings.teamNumber);
- }
- }
- int webserverPort = DEFAULT_PORT;
- System.out.printf("Starting Webserver at port %d\n", webserverPort);
- Server.main(webserverPort);
+ if (testMode) {
+ // todo: boot in to the new classabstraction stuff
} else {
- System.err.println("No cameras connected!");
+ if (CameraManager.initializeCameras()) {
+ SettingsManager.initialize();
+ NetworkManager.initialize(manageNetwork);
+ CameraManager.initializeThreads();
+ if (ntServerMode) {
+ System.out.println("Starting NT Server");
+ NetworkTableInstance.getDefault().startServer();
+ } else {
+ NetworkTableInstance.getDefault().addLogger(new NTLogger(), 0, 255); // to hide error messages
+ if (ntClientModeServer != null) {
+ NetworkTableInstance.getDefault().startClient(ntClientModeServer);
+ } else {
+ NetworkTableInstance.getDefault().startClientTeam(SettingsManager.generalSettings.teamNumber);
+ }
+ }
+
+ System.out.printf("Starting Webserver at port %d\n", DEFAULT_PORT);
+ Server.main(DEFAULT_PORT);
+ } else {
+ System.err.println("No cameras connected!");
+ }
}
}
}
diff --git a/Main/src/main/java/com/chameleonvision/classabstraction/VisionManager.java b/Main/src/main/java/com/chameleonvision/classabstraction/VisionManager.java
index e2a7ee2f3..33ab13bc9 100644
--- a/Main/src/main/java/com/chameleonvision/classabstraction/VisionManager.java
+++ b/Main/src/main/java/com/chameleonvision/classabstraction/VisionManager.java
@@ -16,7 +16,6 @@ import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
@@ -28,7 +27,6 @@ public class VisionManager {
public static final LinkedHashMap UsbCameraInfosByCameraName = new LinkedHashMap<>();
public static final LinkedHashMap VisionProcessesByCameraName = new LinkedHashMap<>();
-
public static boolean initializeSources() {
int suffix = 0;
for (UsbCameraInfo info : UsbCamera.enumerateUsbCameras()) {
@@ -48,19 +46,26 @@ public class VisionManager {
return false;
}
- FileHelper.CheckPath(CamConfigPath);
- UsbCameraInfosByCameraName.forEach((cameraName, cameraInfo) -> {
- Path cameraConfigPath = Paths.get(CamConfigPath.toString(), String.format("%s.json", cameraName));
- File cameraConfigFile = new File(cameraConfigPath.toString());
- if (cameraConfigFile.exists() && cameraConfigFile.length() != 0) {
-// try {
-// Gson gson = new GsonBuilder().registerTypeAdapter(USBCameraProcess.class, new CameraDeserializer());
-// }
- }
- });
+// FileHelper.CheckPath(CamConfigPath);
+// UsbCameraInfosByCameraName.forEach((cameraName, cameraInfo) -> {
+// Path cameraConfigPath = Paths.get(CamConfigPath.toString(), String.format("%s.json", cameraName));
+// File cameraConfigFile = new File(cameraConfigPath.toString());
+// if (cameraConfigFile.exists() && cameraConfigFile.length() != 0) {
+//// try {
+//// Gson gson = new GsonBuilder().registerTypeAdapter(USBCameraProcess.class, new CameraDeserializer());
+//// }
+// }
+// })
+ // TODO: implement new camera JSON loads
return true;
}
+ public void PipelineSerializer(List list, Path path) throws IOException {
+ File pipelineFile = new File(path.toString());
+ ObjectMapper objectMapper = new ObjectMapper().enableDefaultTyping();
+ objectMapper.writeValue(pipelineFile,list);
+ }
+
public static void initializeProcesses() {
diff --git a/Main/src/main/java/com/chameleonvision/classabstraction/VisionProcess.java b/Main/src/main/java/com/chameleonvision/classabstraction/VisionProcess.java
index eb54fcf7c..ded690973 100644
--- a/Main/src/main/java/com/chameleonvision/classabstraction/VisionProcess.java
+++ b/Main/src/main/java/com/chameleonvision/classabstraction/VisionProcess.java
@@ -2,8 +2,10 @@ package com.chameleonvision.classabstraction;
import com.chameleonvision.classabstraction.camera.CameraProcess;
import com.chameleonvision.classabstraction.pipeline.CVPipeline;
+import com.chameleonvision.classabstraction.pipeline.CVPipelineResult;
import com.chameleonvision.classabstraction.pipeline.CVPipelineSettings;
import com.chameleonvision.classabstraction.pipeline.DriverVisionPipeline;
+import org.opencv.core.Mat;
import java.util.ArrayList;
import java.util.List;
@@ -14,6 +16,8 @@ public class VisionProcess {
private final List pipelines = new ArrayList<>();
private CVPipeline currentPipeline;
+ private final CameraFrameRunnable cameraFrameRunnable;
+
private final CVPipelineSettings driverVisionSettings = new CVPipelineSettings();
public VisionProcess(CameraProcess cameraProcess) {
@@ -21,6 +25,8 @@ public class VisionProcess {
pipelines.add(new DriverVisionPipeline(() -> driverVisionSettings));
setPipeline(pipelines.get(0));
+
+ cameraFrameRunnable = new CameraFrameRunnable();
}
public void setPipeline(int pipelineIndex) {
@@ -38,4 +44,42 @@ public class VisionProcess {
public CVPipeline getCurrentPipeline() {
return currentPipeline;
}
+
+ protected class CameraFrameRunnable implements Runnable {
+ private Mat cameraFrame = new Mat();
+ private long timestampMicros;
+
+ private final Object frameLock = new Object();
+
+ @Override
+ public void run() {
+ while(Thread.interrupted()) {
+ var camData = cameraProcess.getFrame();
+ synchronized (frameLock) {
+ cameraFrame = camData.getLeft();
+ }
+ timestampMicros = camData.getRight();
+ }
+ }
+
+ public Mat getFrame() {
+ return cameraFrame;
+ }
+
+ public long getTimestampMicros() {
+ return timestampMicros;
+ }
+ }
+
+ private class VisionThread implements Runnable {
+
+ private CVPipelineResult result;
+
+ @Override
+ public void run() {
+ while(!Thread.interrupted()) {
+ result = currentPipeline.runPipeline(cameraFrameRunnable.getFrame());
+ }
+ }
+ }
}
diff --git a/Main/src/main/java/com/chameleonvision/classabstraction/camera/CameraProcess.java b/Main/src/main/java/com/chameleonvision/classabstraction/camera/CameraProcess.java
index bab9235fd..f37aa7f37 100644
--- a/Main/src/main/java/com/chameleonvision/classabstraction/camera/CameraProcess.java
+++ b/Main/src/main/java/com/chameleonvision/classabstraction/camera/CameraProcess.java
@@ -8,10 +8,9 @@ public interface CameraProcess {
/**
* Get the next camera frame
- * @param frame the frame to copy the image into
* @return a Pair of the captured image and how long it took to grab the frame (in uS)
*/
- Pair getFrame(Mat frame);
+ Pair getFrame();
/**
* Set the exposure of the camera
diff --git a/Main/src/main/java/com/chameleonvision/classabstraction/camera/CameraStreamer.java b/Main/src/main/java/com/chameleonvision/classabstraction/camera/CameraStreamer.java
index 2f98f37c8..63dbc9078 100644
--- a/Main/src/main/java/com/chameleonvision/classabstraction/camera/CameraStreamer.java
+++ b/Main/src/main/java/com/chameleonvision/classabstraction/camera/CameraStreamer.java
@@ -1,6 +1,5 @@
package com.chameleonvision.classabstraction.camera;
-import com.chameleonvision.vision.camera.CameraManager;
import com.chameleonvision.vision.camera.StreamDivisor;
import com.chameleonvision.web.ServerHandler;
import edu.wpi.cscore.CvSource;
@@ -11,7 +10,6 @@ import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
public class CameraStreamer {
-
private final CameraProcess cameraProcess;
private final String name;
private StreamDivisor divisor = StreamDivisor.NONE;
@@ -27,7 +25,6 @@ public class CameraStreamer {
cameraProcess.getProperties().staticProperties.imageHeight / divisor.value);
}
-
public void setDivisor(StreamDivisor newDivisor) {
this.divisor = newDivisor;
var camValues = cameraProcess.getProperties();
@@ -42,9 +39,7 @@ public class CameraStreamer {
ServerHandler.sendFullSettings();
}
- public void runStream() {
- var newFrame = cameraProcess.getFrame(streamBuffer);
- var image = newFrame.getLeft();
+ public void runStream(Mat image) {
if (divisor.value != 1) {
var camVal = cameraProcess.getProperties().staticProperties;
var newWidth = camVal.imageWidth / divisor.value;
diff --git a/Main/src/main/java/com/chameleonvision/classabstraction/camera/USBCameraProcess.java b/Main/src/main/java/com/chameleonvision/classabstraction/camera/USBCameraProcess.java
index f24b15e3d..1afadb6c1 100644
--- a/Main/src/main/java/com/chameleonvision/classabstraction/camera/USBCameraProcess.java
+++ b/Main/src/main/java/com/chameleonvision/classabstraction/camera/USBCameraProcess.java
@@ -28,13 +28,12 @@ public class USBCameraProcess implements CameraProcess {
}
@Override
- public Pair getFrame(Mat frame) {
+ public Pair getFrame() {
Long deltaTime;
synchronized (cvSink) {
deltaTime = cvSink.grabFrame(imageBuffer) * 1000L;
- imageBuffer.copyTo(frame);
}
- return Pair.of(frame, deltaTime);
+ return Pair.of(imageBuffer, deltaTime);
}
@Override
diff --git a/Main/src/main/java/com/chameleonvision/classabstraction/pipeline/CVPipelineResult.java b/Main/src/main/java/com/chameleonvision/classabstraction/pipeline/CVPipelineResult.java
index 3ffe26d9d..484bf20b1 100644
--- a/Main/src/main/java/com/chameleonvision/classabstraction/pipeline/CVPipelineResult.java
+++ b/Main/src/main/java/com/chameleonvision/classabstraction/pipeline/CVPipelineResult.java
@@ -8,10 +8,12 @@ public abstract class CVPipelineResult {
public final List targets;
public final boolean hasTarget;
public final Mat outputMat = new Mat();
+ public final long processTime;
- public CVPipelineResult(List targets, Mat outputMat) {
+ public CVPipelineResult(List targets, Mat outputMat, long processTime) {
this.targets = targets;
hasTarget = targets != null && !targets.isEmpty();
outputMat.copyTo(this.outputMat);
+ this.processTime = processTime;
}
}
diff --git a/Main/src/main/java/com/chameleonvision/vision/process/VisionProcess.java b/Main/src/main/java/com/chameleonvision/vision/process/VisionProcess.java
index 30d460ce3..a329b82ce 100644
--- a/Main/src/main/java/com/chameleonvision/vision/process/VisionProcess.java
+++ b/Main/src/main/java/com/chameleonvision/vision/process/VisionProcess.java
@@ -1,6 +1,7 @@
package com.chameleonvision.vision.process;
import com.chameleonvision.classabstraction.pipeline.CVPipeline2d;
+import com.chameleonvision.classabstraction.pipeline.CVPipeline2dSettings;
import com.chameleonvision.classabstraction.pipeline.DriverVisionPipeline;
import com.chameleonvision.settings.SettingsManager;
import com.chameleonvision.vision.Orientation;