mirror of
https://github.com/PhotonVision/photonvision
synced 2026-07-03 03:01:40 +00:00
Reduce initial connection bandwidth (#1200)
Reduces bandwidth requirements by being much lazier about how much calibration data is sent to the UI.
This commit is contained in:
@@ -31,7 +31,7 @@ import org.photonvision.common.util.SerializationUtils;
|
||||
import org.photonvision.jni.RknnDetectorJNI;
|
||||
import org.photonvision.mrcal.MrCalJNILoader;
|
||||
import org.photonvision.raspi.LibCameraJNILoader;
|
||||
import org.photonvision.vision.calibration.CameraCalibrationCoefficients;
|
||||
import org.photonvision.vision.calibration.UICameraCalibrationCoefficients;
|
||||
import org.photonvision.vision.camera.QuirkyCamera;
|
||||
import org.photonvision.vision.processes.VisionModule;
|
||||
import org.photonvision.vision.processes.VisionModuleManager;
|
||||
@@ -126,13 +126,6 @@ public class PhotonConfiguration {
|
||||
|
||||
settingsSubmap.put("networkSettings", netConfigMap);
|
||||
|
||||
map.put(
|
||||
"cameraSettings",
|
||||
VisionModuleManager.getInstance().getModules().stream()
|
||||
.map(VisionModule::toUICameraConfig)
|
||||
.map(SerializationUtils::objectToHashMap)
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
var lightingConfig = new UILightingConfig();
|
||||
lightingConfig.brightness = hardwareSettings.ledBrightnessPercentage;
|
||||
lightingConfig.supported = !hardwareConfig.ledPins.isEmpty();
|
||||
@@ -181,7 +174,7 @@ public class PhotonConfiguration {
|
||||
public HashMap<Integer, HashMap<String, Object>> videoFormatList;
|
||||
public int outputStreamPort;
|
||||
public int inputStreamPort;
|
||||
public List<CameraCalibrationCoefficients> calibrations;
|
||||
public List<UICameraCalibrationCoefficients> calibrations;
|
||||
public boolean isFovConfigurable = true;
|
||||
public QuirkyCamera cameraQuirks;
|
||||
public boolean isCSICamera;
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.photonvision.common.logging.LogGroup;
|
||||
import org.photonvision.common.logging.Logger;
|
||||
import org.photonvision.common.util.SerializationUtils;
|
||||
import org.photonvision.vision.pipeline.result.CVPipelineResult;
|
||||
import org.photonvision.vision.pipeline.result.CalibrationPipelineResult;
|
||||
|
||||
public class UIDataPublisher implements CVPipelineResultConsumer {
|
||||
private static final Logger logger = new Logger(UIDataPublisher.class, LogGroup.VisionModule);
|
||||
@@ -41,16 +42,22 @@ public class UIDataPublisher implements CVPipelineResultConsumer {
|
||||
public void accept(CVPipelineResult result) {
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
// only update the UI at 15hz
|
||||
// only update the UI at 10hz
|
||||
if (lastUIResultUpdateTime + 1000.0 / 10.0 > now) return;
|
||||
|
||||
var dataMap = new HashMap<String, Object>();
|
||||
dataMap.put("fps", result.fps);
|
||||
dataMap.put("latency", result.getLatencyMillis());
|
||||
var uiTargets = new ArrayList<HashMap<String, Object>>(result.targets.size());
|
||||
for (var t : result.targets) {
|
||||
uiTargets.add(t.toHashMap());
|
||||
|
||||
// We don't actually need to send targets during calibration and it can take up a lot (up to
|
||||
// 1.2Mbps for 60 snapshots) of target results with no pitch/yaw/etc set
|
||||
if (!(result instanceof CalibrationPipelineResult)) {
|
||||
for (var t : result.targets) {
|
||||
uiTargets.add(t.toHashMap());
|
||||
}
|
||||
}
|
||||
|
||||
dataMap.put("targets", uiTargets);
|
||||
dataMap.put("classNames", result.objectDetectionClassNames);
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import java.util.List;
|
||||
import org.opencv.core.Point;
|
||||
import org.opencv.core.Point3;
|
||||
|
||||
public final class BoardObservation {
|
||||
public final class BoardObservation implements Cloneable {
|
||||
// Expected feature 3d location in the camera frame
|
||||
@JsonProperty("locationInObjectSpace")
|
||||
public List<Point3> locationInObjectSpace;
|
||||
@@ -68,4 +68,33 @@ public final class BoardObservation {
|
||||
this.snapshotName = snapshotName;
|
||||
this.snapshotData = snapshotData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BoardObservation [locationInObjectSpace="
|
||||
+ locationInObjectSpace
|
||||
+ ", locationInImageSpace="
|
||||
+ locationInImageSpace
|
||||
+ ", reprojectionErrors="
|
||||
+ reprojectionErrors
|
||||
+ ", optimisedCameraToObject="
|
||||
+ optimisedCameraToObject
|
||||
+ ", includeObservationInCalibration="
|
||||
+ includeObservationInCalibration
|
||||
+ ", snapshotName="
|
||||
+ snapshotName
|
||||
+ ", snapshotData="
|
||||
+ snapshotData
|
||||
+ "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public BoardObservation clone() {
|
||||
try {
|
||||
return (BoardObservation) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
System.err.println("Guhhh clone buh");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,8 +191,8 @@ public class CameraCalibrationCoefficients implements Releasable {
|
||||
+ cameraIntrinsics
|
||||
+ ", distCoeffs="
|
||||
+ distCoeffs
|
||||
+ ", observations="
|
||||
+ observations
|
||||
+ ", observationslen="
|
||||
+ observations.size()
|
||||
+ ", calobjectWarp="
|
||||
+ Arrays.toString(calobjectWarp)
|
||||
+ ", intrinsicsArr="
|
||||
@@ -201,4 +201,16 @@ public class CameraCalibrationCoefficients implements Releasable {
|
||||
+ Arrays.toString(distCoeffsArr)
|
||||
+ "]";
|
||||
}
|
||||
|
||||
public UICameraCalibrationCoefficients cloneWithoutObservations() {
|
||||
return new UICameraCalibrationCoefficients(
|
||||
resolution,
|
||||
cameraIntrinsics,
|
||||
distCoeffs,
|
||||
calobjectWarp,
|
||||
observations,
|
||||
calobjectSize,
|
||||
calobjectSpacing,
|
||||
lensmodel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,4 +76,17 @@ public class JsonImageMat implements Releasable {
|
||||
public void release() {
|
||||
if (wrappedMat != null) wrappedMat.release();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "JsonImageMat [rows="
|
||||
+ rows
|
||||
+ ", cols="
|
||||
+ cols
|
||||
+ ", type="
|
||||
+ type
|
||||
+ ", datalen="
|
||||
+ data.length()
|
||||
+ "]";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ public class JsonMatOfDouble implements Releasable {
|
||||
@JsonIgnore private Mat wrappedMat = null;
|
||||
@JsonIgnore private Matrix wpilibMat = null;
|
||||
|
||||
private MatOfDouble wrappedMatOfDouble;
|
||||
@JsonIgnore private MatOfDouble wrappedMatOfDouble;
|
||||
|
||||
public JsonMatOfDouble(int rows, int cols, double[] data) {
|
||||
this(rows, cols, CvType.CV_64FC1, data);
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.photonvision.vision.calibration;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import org.opencv.core.Size;
|
||||
|
||||
public class UICameraCalibrationCoefficients extends CameraCalibrationCoefficients {
|
||||
public int numSnapshots;
|
||||
public List<Double> meanErrors;
|
||||
|
||||
public UICameraCalibrationCoefficients(
|
||||
Size resolution,
|
||||
JsonMatOfDouble cameraIntrinsics,
|
||||
JsonMatOfDouble distCoeffs,
|
||||
double[] calobjectWarp,
|
||||
List<BoardObservation> observations,
|
||||
Size calobjectSize,
|
||||
double calobjectSpacing,
|
||||
CameraLensModel lensmodel) {
|
||||
// yeet observations, keep all else
|
||||
super(
|
||||
resolution,
|
||||
cameraIntrinsics,
|
||||
distCoeffs,
|
||||
calobjectWarp,
|
||||
List.of(),
|
||||
calobjectSize,
|
||||
calobjectSpacing,
|
||||
lensmodel);
|
||||
|
||||
this.numSnapshots = observations.size();
|
||||
this.meanErrors =
|
||||
observations.stream()
|
||||
.map(
|
||||
it2 ->
|
||||
it2.reprojectionErrors.stream()
|
||||
.mapToDouble(it -> Math.sqrt(it.x * it.x + it.y * it.y))
|
||||
.average()
|
||||
.orElse(0))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.Collectors;
|
||||
import org.opencv.core.Size;
|
||||
import org.photonvision.common.configuration.CameraConfiguration;
|
||||
import org.photonvision.common.configuration.ConfigManager;
|
||||
@@ -536,7 +537,10 @@ public class VisionModule {
|
||||
ret.outputStreamPort = this.outputStreamPort;
|
||||
ret.inputStreamPort = this.inputStreamPort;
|
||||
|
||||
ret.calibrations = visionSource.getSettables().getConfiguration().calibrations;
|
||||
ret.calibrations =
|
||||
visionSource.getSettables().getConfiguration().calibrations.stream()
|
||||
.map(CameraCalibrationCoefficients::cloneWithoutObservations)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
ret.isFovConfigurable =
|
||||
!(ConfigManager.getInstance().getConfig().getHardwareConfig().hasPresetFOV()
|
||||
|
||||
Reference in New Issue
Block a user