From 4c4b76a70e31beb83bbcea8af5c0053984bbd623 Mon Sep 17 00:00:00 2001 From: Banks T Date: Fri, 4 Sep 2020 21:35:11 -0400 Subject: [PATCH] Stream threading (#110) * Condense pipeline settings classes * Add OutputStreamPipeline --- .../org/photonvision/vision/frame/Frame.java | 7 + .../pipeline/AdvancedPipelineSettings.java | 65 +++++-- .../vision/pipeline/ColoredShapePipeline.java | 12 +- .../ColoredShapePipelineSettings.java | 54 +----- .../vision/pipeline/OutputStreamPipeline.java | 130 ++++++++++++++ .../vision/pipeline/ReflectivePipeline.java | 160 +++++++++--------- .../pipeline/ReflectivePipelineSettings.java | 56 ------ .../pipeline/result/CVPipelineResult.java | 4 +- .../vision/processes/VisionModule.java | 75 +++++++- .../vision/pipeline/CirclePNPTest.java | 6 +- 10 files changed, 359 insertions(+), 210 deletions(-) create mode 100644 photon-server/src/main/java/org/photonvision/vision/pipeline/OutputStreamPipeline.java diff --git a/photon-server/src/main/java/org/photonvision/vision/frame/Frame.java b/photon-server/src/main/java/org/photonvision/vision/frame/Frame.java index 29899c5a8..2b47bb169 100644 --- a/photon-server/src/main/java/org/photonvision/vision/frame/Frame.java +++ b/photon-server/src/main/java/org/photonvision/vision/frame/Frame.java @@ -17,6 +17,7 @@ package org.photonvision.vision.frame; +import edu.wpi.first.wpilibj.geometry.Rotation2d; import org.opencv.core.Mat; import org.photonvision.vision.opencv.CVMat; import org.photonvision.vision.opencv.Releasable; @@ -36,6 +37,12 @@ public class Frame implements Releasable { this(image, System.nanoTime(), frameStaticProperties); } + public Frame() { + timestampNanos = 0; + image = new CVMat(new Mat()); + frameStaticProperties = new FrameStaticProperties(0, 0, 0, new Rotation2d(), null); + } + public void copyTo(Frame destFrame) { image.getMat().copyTo(destFrame.image.getMat()); } diff --git a/photon-server/src/main/java/org/photonvision/vision/pipeline/AdvancedPipelineSettings.java b/photon-server/src/main/java/org/photonvision/vision/pipeline/AdvancedPipelineSettings.java index 375adae60..061645fb9 100644 --- a/photon-server/src/main/java/org/photonvision/vision/pipeline/AdvancedPipelineSettings.java +++ b/photon-server/src/main/java/org/photonvision/vision/pipeline/AdvancedPipelineSettings.java @@ -21,8 +21,12 @@ import java.util.Objects; import org.opencv.core.Point; import org.photonvision.common.util.numbers.DoubleCouple; import org.photonvision.common.util.numbers.IntegerCouple; +import org.photonvision.vision.opencv.ContourGroupingMode; +import org.photonvision.vision.opencv.ContourIntersectionDirection; import org.photonvision.vision.opencv.ContourSortMode; +import org.photonvision.vision.pipe.impl.CornerDetectionPipe; import org.photonvision.vision.target.RobotOffsetPointMode; +import org.photonvision.vision.target.TargetModel; import org.photonvision.vision.target.TargetOffsetPointEdge; import org.photonvision.vision.target.TargetOrientation; @@ -71,10 +75,28 @@ public class AdvancedPipelineSettings extends CVPipelineSettings { public Point offsetDualPointB = new Point(); public double offsetDualPointBArea = 0; + // how many contours to attempt to group (Single, Dual) + public ContourGroupingMode contourGroupingMode = ContourGroupingMode.Single; + + // the direction in which contours must intersect to be considered intersecting + public ContourIntersectionDirection contourIntersection = ContourIntersectionDirection.Up; + + // 3d settings + public boolean solvePNPEnabled = false; + public TargetModel targetModel = TargetModel.get2020Target(); + + // Corner detection settings + public CornerDetectionPipe.DetectionStrategy cornerDetectionStrategy = + CornerDetectionPipe.DetectionStrategy.APPROX_POLY_DP_AND_EXTREME_CORNERS; + public boolean cornerDetectionUseConvexHulls = true; + public boolean cornerDetectionExactSideCount = false; + public int cornerDetectionSideCount = 4; + public double cornerDetectionAccuracyPercentage = 10; + @Override public boolean equals(Object o) { if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (!(o instanceof AdvancedPipelineSettings)) return false; if (!super.equals(o)) return false; AdvancedPipelineSettings that = (AdvancedPipelineSettings) o; return outputShouldDraw == that.outputShouldDraw @@ -82,23 +104,31 @@ public class AdvancedPipelineSettings extends CVPipelineSettings { && erode == that.erode && dilate == that.dilate && contourSpecklePercentage == that.contourSpecklePercentage - && Double.compare(that.offsetDualPointA.x, offsetDualPointA.x) == 0 - && Double.compare(that.offsetDualPointA.y, offsetDualPointA.y) == 0 && Double.compare(that.offsetDualPointAArea, offsetDualPointAArea) == 0 - && Double.compare(that.offsetDualPointB.x, offsetDualPointB.x) == 0 - && Double.compare(that.offsetDualPointB.y, offsetDualPointB.y) == 0 && Double.compare(that.offsetDualPointBArea, offsetDualPointBArea) == 0 - && hsvHue.equals(that.hsvHue) - && hsvSaturation.equals(that.hsvSaturation) - && hsvValue.equals(that.hsvValue) - && contourArea.equals(that.contourArea) - && contourRatio.equals(that.contourRatio) - && contourFullness.equals(that.contourFullness) + && solvePNPEnabled == that.solvePNPEnabled + && cornerDetectionUseConvexHulls == that.cornerDetectionUseConvexHulls + && cornerDetectionExactSideCount == that.cornerDetectionExactSideCount + && cornerDetectionSideCount == that.cornerDetectionSideCount + && Double.compare(that.cornerDetectionAccuracyPercentage, cornerDetectionAccuracyPercentage) + == 0 + && Objects.equals(hsvHue, that.hsvHue) + && Objects.equals(hsvSaturation, that.hsvSaturation) + && Objects.equals(hsvValue, that.hsvValue) + && Objects.equals(contourArea, that.contourArea) + && Objects.equals(contourRatio, that.contourRatio) + && Objects.equals(contourFullness, that.contourFullness) && contourSortMode == that.contourSortMode && contourTargetOffsetPointEdge == that.contourTargetOffsetPointEdge && contourTargetOrientation == that.contourTargetOrientation && offsetRobotOffsetMode == that.offsetRobotOffsetMode - && offsetSinglePoint.equals(that.offsetSinglePoint); + && Objects.equals(offsetSinglePoint, that.offsetSinglePoint) + && Objects.equals(offsetDualPointA, that.offsetDualPointA) + && Objects.equals(offsetDualPointB, that.offsetDualPointB) + && contourGroupingMode == that.contourGroupingMode + && contourIntersection == that.contourIntersection + && Objects.equals(targetModel, that.targetModel) + && cornerDetectionStrategy == that.cornerDetectionStrategy; } @Override @@ -124,6 +154,15 @@ public class AdvancedPipelineSettings extends CVPipelineSettings { offsetDualPointA, offsetDualPointAArea, offsetDualPointB, - offsetDualPointBArea); + offsetDualPointBArea, + contourGroupingMode, + contourIntersection, + solvePNPEnabled, + targetModel, + cornerDetectionStrategy, + cornerDetectionUseConvexHulls, + cornerDetectionExactSideCount, + cornerDetectionSideCount, + cornerDetectionAccuracyPercentage); } } diff --git a/photon-server/src/main/java/org/photonvision/vision/pipeline/ColoredShapePipeline.java b/photon-server/src/main/java/org/photonvision/vision/pipeline/ColoredShapePipeline.java index dce29cbc8..1c57739e9 100644 --- a/photon-server/src/main/java/org/photonvision/vision/pipeline/ColoredShapePipeline.java +++ b/photon-server/src/main/java/org/photonvision/vision/pipeline/ColoredShapePipeline.java @@ -158,7 +158,9 @@ public class ColoredShapePipeline var solvePNPParams = new SolvePNPPipe.SolvePNPPipeParams( - settings.cameraCalibration, settings.cameraPitch, settings.targetModel); + frameStaticProperties.cameraCalibration, + frameStaticProperties.cameraPitch, + settings.targetModel); solvePNPPipe.setParams(solvePNPParams); Draw2dTargetsPipe.Draw2dTargetsParams draw2DTargetsParams = @@ -178,10 +180,12 @@ public class ColoredShapePipeline frameStaticProperties); draw2dCrosshairPipe.setParams(draw2dCrosshairParams); - var draw3dContoursParams = + var draw3dTargetsParams = new Draw3dTargetsPipe.Draw3dContoursParams( - settings.outputShouldDraw, settings.cameraCalibration, settings.targetModel); - draw3dTargetsPipe.setParams(draw3dContoursParams); + settings.outputShouldDraw, + frameStaticProperties.cameraCalibration, + settings.targetModel); + draw3dTargetsPipe.setParams(draw3dTargetsParams); } @Override diff --git a/photon-server/src/main/java/org/photonvision/vision/pipeline/ColoredShapePipelineSettings.java b/photon-server/src/main/java/org/photonvision/vision/pipeline/ColoredShapePipelineSettings.java index e90a4f9a6..a52d2a47b 100644 --- a/photon-server/src/main/java/org/photonvision/vision/pipeline/ColoredShapePipelineSettings.java +++ b/photon-server/src/main/java/org/photonvision/vision/pipeline/ColoredShapePipelineSettings.java @@ -18,14 +18,8 @@ package org.photonvision.vision.pipeline; import com.fasterxml.jackson.annotation.JsonTypeName; -import edu.wpi.first.wpilibj.geometry.Rotation2d; import java.util.Objects; -import org.photonvision.vision.calibration.CameraCalibrationCoefficients; -import org.photonvision.vision.opencv.ContourGroupingMode; -import org.photonvision.vision.opencv.ContourIntersectionDirection; import org.photonvision.vision.opencv.ContourShape; -import org.photonvision.vision.pipe.impl.CornerDetectionPipe; -import org.photonvision.vision.target.TargetModel; @JsonTypeName("ColoredShapePipelineSettings") public class ColoredShapePipelineSettings extends AdvancedPipelineSettings { @@ -42,25 +36,6 @@ public class ColoredShapePipelineSettings extends AdvancedPipelineSettings { public int minDist = 10; public int maxCannyThresh = 90; public int accuracy = 20; - // how many contours to attempt to group (Single, Dual) - public ContourGroupingMode contourGroupingMode = ContourGroupingMode.Single; - - // the direction in which contours must intersect to be considered intersecting - public ContourIntersectionDirection contourIntersection = ContourIntersectionDirection.Up; - - // 3d settings - public boolean solvePNPEnabled = false; - public CameraCalibrationCoefficients cameraCalibration; - public TargetModel targetModel; - public Rotation2d cameraPitch = Rotation2d.fromDegrees(0.0); // TODO where should pitch live? - - // Corner detection settings - public CornerDetectionPipe.DetectionStrategy cornerDetectionStrategy = - CornerDetectionPipe.DetectionStrategy.APPROX_POLY_DP_AND_EXTREME_CORNERS; - public boolean cornerDetectionUseConvexHulls = true; - public boolean cornerDetectionExactSideCount = false; - public int cornerDetectionSideCount = 4; - public double cornerDetectionAccuracyPercentage = 10; public ColoredShapePipelineSettings() { super(); @@ -70,7 +45,7 @@ public class ColoredShapePipelineSettings extends AdvancedPipelineSettings { @Override public boolean equals(Object o) { if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (!(o instanceof ColoredShapePipelineSettings)) return false; if (!super.equals(o)) return false; ColoredShapePipelineSettings that = (ColoredShapePipelineSettings) o; return Double.compare(that.minArea, minArea) == 0 @@ -84,19 +59,7 @@ public class ColoredShapePipelineSettings extends AdvancedPipelineSettings { && minDist == that.minDist && maxCannyThresh == that.maxCannyThresh && accuracy == that.accuracy - && solvePNPEnabled == that.solvePNPEnabled - && cornerDetectionUseConvexHulls == that.cornerDetectionUseConvexHulls - && cornerDetectionExactSideCount == that.cornerDetectionExactSideCount - && cornerDetectionSideCount == that.cornerDetectionSideCount - && Double.compare(that.cornerDetectionAccuracyPercentage, cornerDetectionAccuracyPercentage) - == 0 - && desiredShape == that.desiredShape - && contourGroupingMode == that.contourGroupingMode - && contourIntersection == that.contourIntersection - && Objects.equals(cameraCalibration, that.cameraCalibration) - && Objects.equals(targetModel, that.targetModel) - && Objects.equals(cameraPitch, that.cameraPitch) - && cornerDetectionStrategy == that.cornerDetectionStrategy; + && desiredShape == that.desiredShape; } @Override @@ -114,17 +77,6 @@ public class ColoredShapePipelineSettings extends AdvancedPipelineSettings { maxRadius, minDist, maxCannyThresh, - accuracy, - contourGroupingMode, - contourIntersection, - solvePNPEnabled, - cameraCalibration, - targetModel, - cameraPitch, - cornerDetectionStrategy, - cornerDetectionUseConvexHulls, - cornerDetectionExactSideCount, - cornerDetectionSideCount, - cornerDetectionAccuracyPercentage); + accuracy); } } diff --git a/photon-server/src/main/java/org/photonvision/vision/pipeline/OutputStreamPipeline.java b/photon-server/src/main/java/org/photonvision/vision/pipeline/OutputStreamPipeline.java new file mode 100644 index 000000000..ed93ff6fb --- /dev/null +++ b/photon-server/src/main/java/org/photonvision/vision/pipeline/OutputStreamPipeline.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2020 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 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 . + */ + +package org.photonvision.vision.pipeline; + +import java.util.List; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.commons.lang3.tuple.Triple; +import org.photonvision.common.util.math.MathUtils; +import org.photonvision.vision.frame.Frame; +import org.photonvision.vision.frame.FrameStaticProperties; +import org.photonvision.vision.opencv.CVMat; +import org.photonvision.vision.opencv.DualOffsetValues; +import org.photonvision.vision.pipe.impl.Draw2dCrosshairPipe; +import org.photonvision.vision.pipe.impl.Draw2dTargetsPipe; +import org.photonvision.vision.pipe.impl.Draw3dTargetsPipe; +import org.photonvision.vision.pipe.impl.OutputMatPipe; +import org.photonvision.vision.pipeline.result.CVPipelineResult; +import org.photonvision.vision.target.TrackedTarget; + +/** +* This is a "fake" pipeline that is just used to move identical pipe sets out of real pipelines. It +* shall not get its settings saved, nor shall it be managed by PipelineManager +*/ +public class OutputStreamPipeline { + + private final OutputMatPipe outputMatPipe = new OutputMatPipe(); + private final Draw2dCrosshairPipe draw2dCrosshairPipe = new Draw2dCrosshairPipe(); + private final Draw2dTargetsPipe draw2dTargetsPipe = new Draw2dTargetsPipe(); + private final Draw3dTargetsPipe draw3dTargetsPipe = new Draw3dTargetsPipe(); + + private final long[] pipeProfileNanos = new long[10]; + + protected void setPipeParams( + FrameStaticProperties frameStaticProperties, AdvancedPipelineSettings settings) { + + var dualOffsetValues = + new DualOffsetValues( + settings.offsetDualPointA, + settings.offsetDualPointAArea, + settings.offsetDualPointB, + settings.offsetDualPointBArea); + + var draw2DTargetsParams = + new Draw2dTargetsPipe.Draw2dTargetsParams( + settings.outputShouldDraw, settings.outputShowMultipleTargets); + draw2dTargetsPipe.setParams(draw2DTargetsParams); + + var draw2dCrosshairParams = + new Draw2dCrosshairPipe.Draw2dCrosshairParams( + settings.outputShouldDraw, + settings.offsetRobotOffsetMode, + settings.offsetSinglePoint, + dualOffsetValues, + frameStaticProperties); + draw2dCrosshairPipe.setParams(draw2dCrosshairParams); + + var draw3dTargetsParams = + new Draw3dTargetsPipe.Draw3dContoursParams( + settings.outputShouldDraw, + frameStaticProperties.cameraCalibration, + settings.targetModel); + draw3dTargetsPipe.setParams(draw3dTargetsParams); + } + + public CVPipelineResult process( + Frame inputFrame, + Frame outputFrame, + AdvancedPipelineSettings settings, + List targetsToDraw, + double fpsToDraw) { + setPipeParams(inputFrame.frameStaticProperties, settings); + var inMat = inputFrame.image.getMat(); + var outMat = outputFrame.image.getMat(); + + long sumPipeNanosElapsed = 0L; + + // Convert single-channel HSV output mat to 3-channel BGR in preparation for streaming + var outputMatPipeResult = outputMatPipe.run(outMat); + sumPipeNanosElapsed += pipeProfileNanos[0] = outputMatPipeResult.nanosElapsed; + + // Draw 2D Crosshair on input and output + var draw2dCrosshairResultOnInput = draw2dCrosshairPipe.run(Pair.of(inMat, targetsToDraw)); + sumPipeNanosElapsed += pipeProfileNanos[1] = draw2dCrosshairResultOnInput.nanosElapsed; + + var draw2dCrosshairResultOnOutput = draw2dCrosshairPipe.run(Pair.of(inMat, targetsToDraw)); + sumPipeNanosElapsed += pipeProfileNanos[2] = draw2dCrosshairResultOnOutput.nanosElapsed; + + // Draw 2D contours on input and output + var draw2dTargetsOnInput = + draw2dTargetsPipe.run(Triple.of(inMat, targetsToDraw, (int) fpsToDraw)); + sumPipeNanosElapsed += pipeProfileNanos[3] = draw2dTargetsOnInput.nanosElapsed; + + var draw2dTargetsOnOutput = + draw2dTargetsPipe.run(Triple.of(outMat, targetsToDraw, (int) fpsToDraw)); + sumPipeNanosElapsed += pipeProfileNanos[4] = draw2dTargetsOnOutput.nanosElapsed; + + // Draw 3D Targets on input and output if necessary + if (settings.solvePNPEnabled) { + var drawOnInputResult = draw3dTargetsPipe.run(Pair.of(inMat, targetsToDraw)); + sumPipeNanosElapsed += pipeProfileNanos[5] = drawOnInputResult.nanosElapsed; + + var drawOnOutputResult = draw3dTargetsPipe.run(Pair.of(outMat, targetsToDraw)); + sumPipeNanosElapsed += pipeProfileNanos[6] = drawOnOutputResult.nanosElapsed; + } else { + pipeProfileNanos[5] = 0; + pipeProfileNanos[6] = 0; + } + + return new CVPipelineResult( + MathUtils.nanosToMillis(sumPipeNanosElapsed), + targetsToDraw, + new Frame(new CVMat(outMat), outputFrame.frameStaticProperties), + new Frame(new CVMat(inMat), inputFrame.frameStaticProperties)); + } +} diff --git a/photon-server/src/main/java/org/photonvision/vision/pipeline/ReflectivePipeline.java b/photon-server/src/main/java/org/photonvision/vision/pipeline/ReflectivePipeline.java index a6a073db2..04449de2d 100644 --- a/photon-server/src/main/java/org/photonvision/vision/pipeline/ReflectivePipeline.java +++ b/photon-server/src/main/java/org/photonvision/vision/pipeline/ReflectivePipeline.java @@ -18,8 +18,6 @@ package org.photonvision.vision.pipeline; import java.util.List; -import org.apache.commons.lang3.tuple.Pair; -import org.apache.commons.lang3.tuple.Triple; import org.opencv.core.Mat; import org.photonvision.common.util.math.MathUtils; import org.photonvision.vision.frame.Frame; @@ -48,11 +46,11 @@ public class ReflectivePipeline extends CVPipeline targets, Frame outputFrame) { diff --git a/photon-server/src/main/java/org/photonvision/vision/processes/VisionModule.java b/photon-server/src/main/java/org/photonvision/vision/processes/VisionModule.java index 61ab42994..3ae3ffe59 100644 --- a/photon-server/src/main/java/org/photonvision/vision/processes/VisionModule.java +++ b/photon-server/src/main/java/org/photonvision/vision/processes/VisionModule.java @@ -37,7 +37,10 @@ import org.photonvision.vision.calibration.CameraCalibrationCoefficients; import org.photonvision.vision.camera.CameraQuirk; import org.photonvision.vision.camera.QuirkyCamera; import org.photonvision.vision.camera.USBCameraSource; +import org.photonvision.vision.frame.Frame; import org.photonvision.vision.frame.consumer.MJPGFrameConsumer; +import org.photonvision.vision.pipeline.AdvancedPipelineSettings; +import org.photonvision.vision.pipeline.OutputStreamPipeline; import org.photonvision.vision.pipeline.ReflectivePipelineSettings; import org.photonvision.vision.pipeline.UICalibrationData; import org.photonvision.vision.pipeline.result.CVPipelineResult; @@ -58,6 +61,7 @@ public class VisionModule { protected final PipelineManager pipelineManager; protected final VisionSource visionSource; private final VisionRunner visionRunner; + private final StreamRunnable streamRunnable; private final LinkedList resultConsumers = new LinkedList<>(); private final LinkedList fpsLimitedResultConsumers = new LinkedList<>(); private final NTDataPublisher ntConsumer; @@ -84,6 +88,7 @@ public class VisionModule { this.visionSource.getFrameProvider(), this.pipelineManager::getCurrentUserPipeline, this::consumeResult); + this.streamRunnable = new StreamRunnable(new OutputStreamPipeline()); this.moduleIndex = index; // do this @@ -140,6 +145,58 @@ public class VisionModule { saveAndBroadcastAll(); } + private class StreamRunnable extends Thread { + private final OutputStreamPipeline outputStreamPipeline; + + private Frame inputFrame, outputFrame; + private AdvancedPipelineSettings settings = new AdvancedPipelineSettings(); + private List targets = new ArrayList<>(); + private double fps = 0; + + private boolean shouldRun = false; + + public StreamRunnable(OutputStreamPipeline outputStreamPipeline) { + this.outputStreamPipeline = outputStreamPipeline; + } + + public void updateData( + Frame inputFrame, + Frame outputFrame, + AdvancedPipelineSettings settings, + List targets, + double fps) { + this.inputFrame = inputFrame; + this.outputFrame = outputFrame; + this.settings = settings; + this.targets = targets; + this.fps = fps; + + shouldRun = + inputFrame != null + && !inputFrame.image.getMat().empty() + && outputFrame != null + && !outputFrame.image.getMat().empty(); + } + + @Override + public void run() { + while (true) { + if (shouldRun) { + var osr = outputStreamPipeline.process(inputFrame, outputFrame, settings, targets, fps); + consumeFpsLimitedResult(osr); + shouldRun = false; + } else { + // busy wait! hurray! + try { + Thread.sleep(1); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + } + void setDriverMode(boolean isDriverMode) { pipelineManager.setDriverMode(isDriverMode); setVisionLEDs(!isDriverMode); @@ -148,6 +205,7 @@ public class VisionModule { public void start() { visionRunner.startProcess(); + streamRunnable.start(); } public void setFovAndPitch(double fov, Rotation2d pitch) { @@ -347,9 +405,21 @@ public class VisionModule { private void consumeResult(CVPipelineResult result) { consumePipelineResult(result); - consumeFpsLimitedResult(result); - result.release(); + // total hack. kms + if (pipelineManager.getCurrentPipelineIndex() >= 0) { + var fps = 1000.0 / result.getLatencyMillis(); + streamRunnable.updateData( + result.inputFrame, + result.outputFrame, + (AdvancedPipelineSettings) pipelineManager.getCurrentPipelineSettings(), + result.targets, + fps); + // the streamRunnable manages releasing in this case + } else { + consumeFpsLimitedResult(result); + result.release(); + } } private void consumePipelineResult(CVPipelineResult result) { @@ -365,6 +435,7 @@ public class VisionModule { } lastFrameConsumeMillis = System.currentTimeMillis(); } + result.release(); } public void setTargetModel(TargetModel targetModel) { diff --git a/photon-server/src/test/java/org/photonvision/vision/pipeline/CirclePNPTest.java b/photon-server/src/test/java/org/photonvision/vision/pipeline/CirclePNPTest.java index e62f4e4d4..bad22ea8b 100644 --- a/photon-server/src/test/java/org/photonvision/vision/pipeline/CirclePNPTest.java +++ b/photon-server/src/test/java/org/photonvision/vision/pipeline/CirclePNPTest.java @@ -96,9 +96,7 @@ public class CirclePNPTest { pipeline.getSettings().solvePNPEnabled = true; pipeline.getSettings().cornerDetectionAccuracyPercentage = 4; pipeline.getSettings().cornerDetectionUseConvexHulls = true; - pipeline.getSettings().cameraCalibration = getCoeffs(LIFECAM_480P_CAL_FILE); pipeline.getSettings().targetModel = TargetModel.getCircleTarget(7); - pipeline.getSettings().cameraPitch = Rotation2d.fromDegrees(0.0); pipeline.getSettings().outputShouldDraw = true; pipeline.getSettings().outputShowMultipleTargets = false; pipeline.getSettings().contourGroupingMode = ContourGroupingMode.Single; @@ -111,7 +109,9 @@ public class CirclePNPTest { var frameProvider = new FileFrameProvider( TestUtils.getPowercellImagePath(TestUtils.PowercellTestImages.kPowercell_test_6, false), - TestUtils.WPI2020Image.FOV); + TestUtils.WPI2020Image.FOV, + new Rotation2d(), + TestUtils.get2020LifeCamCoeffs(true)); CVPipelineResult pipelineResult = pipeline.run(frameProvider.get()); printTestResults(pipelineResult);