diff --git a/build.gradle b/build.gradle
index 5444787b4..8a4ad5d43 100644
--- a/build.gradle
+++ b/build.gradle
@@ -12,6 +12,9 @@ allprojects {
maven {
url = 'https://frcmaven.wpi.edu:443/artifactory/development'
}
+ maven {
+ url = 'https://frcmaven.wpi.edu:443/artifactory/release'
+ }
}
}
diff --git a/common.gradle b/common.gradle
index 70d90b232..d96ddce41 100644
--- a/common.gradle
+++ b/common.gradle
@@ -6,7 +6,7 @@ sourceCompatibility = 11
// Common version config
ext {
- wpilibVersion = '2020.3.2-99-g9f4de91'
+ wpilibVersion = '2021.1.2'
joglVersion = '2.4.0-rc-20200307'
openCVVersion = '3.4.7-2'
}
@@ -90,4 +90,4 @@ jacocoTestReport {
)
}))
}
-}
\ No newline at end of file
+}
diff --git a/photon-client/src/views/PipelineView.vue b/photon-client/src/views/PipelineView.vue
index 6c486f96d..9d69b8efa 100644
--- a/photon-client/src/views/PipelineView.vue
+++ b/photon-client/src/views/PipelineView.vue
@@ -34,7 +34,7 @@
:text-color="fpsTooLow ? 'white' : 'grey'"
>
{{ Math.round($store.state.pipelineResults.fps) }} FPS –
- {{ Math.round($store.state.pipelineResults.latency) }} ms latency
+ {{ Math.min(Math.round($store.state.pipelineResults.latency), 100) }} ms latency
HSV thresholds are too broad; narrow them for better performance
stop viewing the color stream for better performance
diff --git a/photon-core/build.gradle b/photon-core/build.gradle
index 44674159d..6ccefe1b2 100644
--- a/photon-core/build.gradle
+++ b/photon-core/build.gradle
@@ -12,6 +12,12 @@ dependencies {
implementation 'org.msgpack:msgpack-core:0.8.20'
implementation 'org.msgpack:jackson-dataformat-msgpack:0.8.20'
+ // Wpiutil
+ compile "edu.wpi.first.wpiutil:wpiutil-jni:$wpilibVersion:linuxaarch64bionic"
+ compile "edu.wpi.first.wpiutil:wpiutil-jni:$wpilibVersion:linuxraspbian"
+ compile "edu.wpi.first.wpiutil:wpiutil-jni:$wpilibVersion:linuxx86-64"
+ compile "edu.wpi.first.wpiutil:wpiutil-jni:$wpilibVersion:windowsx86-64"
+
// JOGL stuff (currently we only distribute for aarch64, which is Pi 4)
implementation "org.jogamp.gluegen:gluegen-rt:$joglVersion"
implementation "org.jogamp.jogl:jogl-all:$joglVersion"
diff --git a/photon-core/src/main/java/org/photonvision/common/dataflow/websocket/UIDataPublisher.java b/photon-core/src/main/java/org/photonvision/common/dataflow/websocket/UIDataPublisher.java
index 1101bbb43..0a9de0444 100644
--- a/photon-core/src/main/java/org/photonvision/common/dataflow/websocket/UIDataPublisher.java
+++ b/photon-core/src/main/java/org/photonvision/common/dataflow/websocket/UIDataPublisher.java
@@ -38,16 +38,17 @@ public class UIDataPublisher implements CVPipelineResultConsumer {
@Override
public void accept(CVPipelineResult result) {
- var now = System.currentTimeMillis();
+ long now = System.currentTimeMillis();
+
+ var dataMap = new HashMap();
+ dataMap.put("latency", result.getLatencyMillis());
// only update the UI at 15hz
if (lastUIResultUpdateTime + 1000.0 / 10.0 > now) return;
var uiMap = new HashMap>();
- var dataMap = new HashMap();
dataMap.put("fps", result.fps);
- dataMap.put("latency", result.getLatencyMillis());
var targets = result.targets;
diff --git a/photon-core/src/main/java/org/photonvision/common/util/math/MathUtils.java b/photon-core/src/main/java/org/photonvision/common/util/math/MathUtils.java
index 689494c23..dc925afde 100644
--- a/photon-core/src/main/java/org/photonvision/common/util/math/MathUtils.java
+++ b/photon-core/src/main/java/org/photonvision/common/util/math/MathUtils.java
@@ -17,6 +17,7 @@
package org.photonvision.common.util.math;
+import edu.wpi.first.wpiutil.WPIUtilJNI;
import org.apache.commons.math3.util.FastMath;
public class MathUtils {
@@ -72,4 +73,8 @@ public class MathUtils {
public static double lerp(double startValue, double endValue, double t) {
return startValue + (endValue - startValue) * t;
}
+
+ public static long wpiNanoTime() {
+ return microsToNanos(WPIUtilJNI.now());
+ }
}
diff --git a/photon-core/src/main/java/org/photonvision/vision/frame/Frame.java b/photon-core/src/main/java/org/photonvision/vision/frame/Frame.java
index 1b4baa61d..fd029b483 100644
--- a/photon-core/src/main/java/org/photonvision/vision/frame/Frame.java
+++ b/photon-core/src/main/java/org/photonvision/vision/frame/Frame.java
@@ -18,6 +18,7 @@
package org.photonvision.vision.frame;
import edu.wpi.first.wpilibj.geometry.Rotation2d;
+import org.photonvision.common.util.math.MathUtils;
import org.photonvision.vision.opencv.CVMat;
import org.photonvision.vision.opencv.Releasable;
@@ -33,13 +34,14 @@ public class Frame implements Releasable {
}
public Frame(CVMat image, FrameStaticProperties frameStaticProperties) {
- this(image, System.nanoTime(), frameStaticProperties);
+ this(image, MathUtils.wpiNanoTime(), frameStaticProperties);
}
public Frame() {
- timestampNanos = 0;
- image = new CVMat();
- frameStaticProperties = new FrameStaticProperties(0, 0, 0, new Rotation2d(), null);
+ this(
+ new CVMat(),
+ MathUtils.wpiNanoTime(),
+ new FrameStaticProperties(0, 0, 0, new Rotation2d(), null));
}
public void copyTo(Frame destFrame) {
diff --git a/photon-core/src/main/java/org/photonvision/vision/frame/provider/AcceleratedPicamFrameProvider.java b/photon-core/src/main/java/org/photonvision/vision/frame/provider/AcceleratedPicamFrameProvider.java
index f4fe2b1c9..efdf12ffb 100644
--- a/photon-core/src/main/java/org/photonvision/vision/frame/provider/AcceleratedPicamFrameProvider.java
+++ b/photon-core/src/main/java/org/photonvision/vision/frame/provider/AcceleratedPicamFrameProvider.java
@@ -18,6 +18,7 @@
package org.photonvision.vision.frame.provider;
import org.opencv.core.Mat;
+import org.photonvision.common.util.math.MathUtils;
import org.photonvision.raspi.PicamJNI;
import org.photonvision.vision.frame.Frame;
import org.photonvision.vision.frame.FrameProvider;
@@ -47,6 +48,8 @@ public class AcceleratedPicamFrameProvider implements FrameProvider {
long matHandle = PicamJNI.grabFrame(false);
mat = new CVMat(new Mat(matHandle));
return new Frame(
- mat, System.nanoTime() - PicamJNI.getFrameLatency(), settables.getFrameStaticProperties());
+ mat,
+ MathUtils.wpiNanoTime() - PicamJNI.getFrameLatency(),
+ settables.getFrameStaticProperties());
}
}
diff --git a/photon-core/src/main/java/org/photonvision/vision/frame/provider/USBFrameProvider.java b/photon-core/src/main/java/org/photonvision/vision/frame/provider/USBFrameProvider.java
index a5274c31f..c93c740d9 100644
--- a/photon-core/src/main/java/org/photonvision/vision/frame/provider/USBFrameProvider.java
+++ b/photon-core/src/main/java/org/photonvision/vision/frame/provider/USBFrameProvider.java
@@ -25,9 +25,6 @@ import org.photonvision.vision.opencv.CVMat;
import org.photonvision.vision.processes.VisionSourceSettables;
public class USBFrameProvider implements FrameProvider {
- private static final long unixEpochToNanoEpoch =
- System.nanoTime()
- - MathUtils.millisToNanos(System.currentTimeMillis()); // Units are nanoseconds
private final CvSink cvSink;
@SuppressWarnings("SpellCheckingInspection")
@@ -43,13 +40,16 @@ public class USBFrameProvider implements FrameProvider {
@Override
public Frame get() {
var mat = new CVMat(); // We do this so that we don't fill a Mat in use by another thread
+ // This is from wpi::Now, or WPIUtilJNI.now()
long time =
cvSink.grabFrame(
mat.getMat()); // Units are microseconds, epoch is the same as the Unix epoch
- return new Frame(
- mat,
- MathUtils.microsToNanos(time) + unixEpochToNanoEpoch,
- settables.getFrameStaticProperties());
+
+ // Sometimes CSCore gives us a zero frametime.
+ if (time <= 1e-6) {
+ time = MathUtils.wpiNanoTime();
+ }
+ return new Frame(mat, MathUtils.microsToNanos(time), settables.getFrameStaticProperties());
}
@Override
diff --git a/photon-core/src/main/java/org/photonvision/vision/pipeline/CVPipeline.java b/photon-core/src/main/java/org/photonvision/vision/pipeline/CVPipeline.java
index 60acf30df..53b035ce2 100644
--- a/photon-core/src/main/java/org/photonvision/vision/pipeline/CVPipeline.java
+++ b/photon-core/src/main/java/org/photonvision/vision/pipeline/CVPipeline.java
@@ -18,7 +18,6 @@
package org.photonvision.vision.pipeline;
import java.util.List;
-import org.photonvision.common.util.math.MathUtils;
import org.photonvision.vision.camera.QuirkyCamera;
import org.photonvision.vision.frame.Frame;
import org.photonvision.vision.frame.FrameStaticProperties;
@@ -62,9 +61,7 @@ public abstract class CVPipeline();
hsvPipeResult.output = frame.image.getMat();
- hsvPipeResult.nanosElapsed = System.nanoTime() - frame.timestampNanos;
+ hsvPipeResult.nanosElapsed = MathUtils.wpiNanoTime() - frame.timestampNanos;
sumPipeNanosElapsed = pipeProfileNanos[1] = hsvPipeResult.nanosElapsed;
}
@@ -223,7 +223,7 @@ public class ReflectivePipeline extends CVPipeline targets;
@@ -46,8 +47,8 @@ public class CVPipelineResult implements Releasable {
}
public CVPipelineResult(
- double processingMillis, double fps, List targets, Frame outputFrame) {
- this(processingMillis, fps, targets, outputFrame, null);
+ double processingNanos, double fps, List targets, Frame outputFrame) {
+ this(processingNanos, fps, targets, outputFrame, null);
}
public boolean hasTargets() {
@@ -62,11 +63,21 @@ public class CVPipelineResult implements Releasable {
if (inputFrame != null) inputFrame.release();
}
+ /**
+ * Get the latency between now (wpi::Now) and the time at which the image was captured. FOOTGUN:
+ * the latency is relative to the time at which this method is called. Waiting to call this method
+ * will change the latency this method returns.
+ */
public double getLatencyMillis() {
- return latencyMillis;
+ var now = MathUtils.wpiNanoTime();
+ return MathUtils.nanosToMillis(now - imageCaptureTimestampNanos);
}
- public void setLatencyMillis(double latencyMillis) {
- this.latencyMillis = latencyMillis;
+ public long getImageCaptureTimestampNanos() {
+ return imageCaptureTimestampNanos;
+ }
+
+ public void setImageCaptureTimestampNanos(long imageCaptureTimestampNanos) {
+ this.imageCaptureTimestampNanos = imageCaptureTimestampNanos;
}
}
diff --git a/photon-core/src/main/java/org/photonvision/vision/pipeline/result/DriverModePipelineResult.java b/photon-core/src/main/java/org/photonvision/vision/pipeline/result/DriverModePipelineResult.java
index 8e31a871e..609a3f448 100644
--- a/photon-core/src/main/java/org/photonvision/vision/pipeline/result/DriverModePipelineResult.java
+++ b/photon-core/src/main/java/org/photonvision/vision/pipeline/result/DriverModePipelineResult.java
@@ -21,7 +21,7 @@ import java.util.List;
import org.photonvision.vision.frame.Frame;
public class DriverModePipelineResult extends CVPipelineResult {
- public DriverModePipelineResult(double latencyMillis, double fps, Frame outputFrame) {
- super(latencyMillis, fps, List.of(), outputFrame);
+ public DriverModePipelineResult(double latencyNanos, double fps, Frame outputFrame) {
+ super(latencyNanos, fps, List.of(), outputFrame);
}
}
diff --git a/photon-core/src/test/java/org/photonvision/common/ShapeBenchmarkTest.java b/photon-core/src/test/java/org/photonvision/common/ShapeBenchmarkTest.java
index a13cf9a7d..daca840a0 100644
--- a/photon-core/src/test/java/org/photonvision/common/ShapeBenchmarkTest.java
+++ b/photon-core/src/test/java/org/photonvision/common/ShapeBenchmarkTest.java
@@ -174,7 +174,7 @@ public class ShapeBenchmarkTest {
pipelineResult.release();
processingTimes.add(pipelineResult.processingMillis);
latencyTimes.add(pipelineResult.getLatencyMillis());
- } while (System.currentTimeMillis() - benchmarkStartMillis < secondsToRun * 1000);
+ } while (System.currentTimeMillis() - benchmarkStartMillis < secondsToRun * 1000L);
System.out.println("Benchmark complete.");
var processingMin = Collections.min(processingTimes);