Skip to content

Commit 6f3befb

Browse files
committed
Add support for removing calibrations
1 parent 5d39ef5 commit 6f3befb

File tree

6 files changed

+122
-0
lines changed

6 files changed

+122
-0
lines changed

photon-client/src/components/cameras/CameraCalibrationInfoCard.vue

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,47 @@ import { useStateStore } from "@/stores/StateStore";
55
import { computed, inject, ref } from "vue";
66
import { getResolutionString, parseJsonFile } from "@/lib/PhotonUtils";
77
import { useTheme } from "vuetify";
8+
import axios from "axios";
89
910
const theme = useTheme();
1011
1112
const props = defineProps<{
1213
videoFormat: VideoFormat;
1314
}>();
1415
16+
const removeCalibration = () => {
17+
axios
18+
.post("/calibration/remove", {
19+
cameraUniqueName: useCameraSettingsStore().currentCameraSettings.uniqueName,
20+
width: props.videoFormat.resolution.width,
21+
height: props.videoFormat.resolution.height
22+
})
23+
.then((response) => {
24+
useStateStore().showSnackbarMessage({
25+
message: response.data.text || response.data,
26+
color: "success"
27+
});
28+
})
29+
.catch((error) => {
30+
if (error.response) {
31+
useStateStore().showSnackbarMessage({
32+
color: "error",
33+
message: error.response.data.text || error.response.data
34+
});
35+
} else if (error.request) {
36+
useStateStore().showSnackbarMessage({
37+
color: "error",
38+
message: "Error while trying to process the request! The backend didn't respond."
39+
});
40+
} else {
41+
useStateStore().showSnackbarMessage({
42+
color: "error",
43+
message: "An error occurred while trying to process the request."
44+
});
45+
}
46+
});
47+
};
48+
1549
const exportCalibration = ref();
1650
const openExportCalibrationPrompt = () => {
1751
exportCalibration.value.click();
@@ -97,6 +131,18 @@ const calibrationImageURL = (index: number) =>
97131
<v-col cols="12" md="6">
98132
<v-card-title class="pa-0"> Calibration Details </v-card-title>
99133
</v-col>
134+
<v-col cols="6" md="3" class="d-flex align-center pt-0 pt-md-3 pr-6 pr-md-3">
135+
<v-btn
136+
color="error"
137+
:disabled="!currentCalibrationCoeffs"
138+
style="width: 100%"
139+
:variant="theme.global.name.value === 'LightTheme' ? 'elevated' : 'outlined'"
140+
@click="removeCalibration"
141+
>
142+
<v-icon start size="large">mdi-delete</v-icon>
143+
<span>Delete</span>
144+
</v-btn>
145+
</v-col>
100146
<v-col cols="6" md="3" class="d-flex align-center pt-0 pt-md-3 pl-6 pl-md-3">
101147
<v-btn
102148
color="buttonPassive"

photon-core/src/main/java/org/photonvision/common/configuration/CameraConfiguration.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.util.ArrayList;
2525
import java.util.List;
2626
import java.util.UUID;
27+
import org.opencv.core.Size;
2728
import org.photonvision.common.dataflow.websocket.UICameraConfiguration;
2829
import org.photonvision.common.logging.LogGroup;
2930
import org.photonvision.common.logging.Logger;
@@ -189,6 +190,23 @@ public void addCalibration(CameraCalibrationCoefficients calibration) {
189190
calibrations.add(calibration);
190191
}
191192

193+
/**
194+
* Remove a calibration from our list.
195+
*
196+
* @param calibration The calibration to remove
197+
*/
198+
public void removeCalibration(Size unrotatedImageSize) {
199+
logger.info("deleting calibration " + unrotatedImageSize);
200+
calibrations.stream()
201+
.filter(it -> it.unrotatedImageSize.equals(unrotatedImageSize))
202+
.findAny()
203+
.ifPresent(
204+
(it) -> {
205+
it.release();
206+
calibrations.remove(it);
207+
});
208+
}
209+
192210
/**
193211
* cscore will auto-reconnect to the camera path we give it. v4l does not guarantee that if i swap
194212
* cameras around, the same /dev/videoN ID will be assigned to that camera. So instead default to

photon-core/src/main/java/org/photonvision/vision/processes/VisionModule.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,16 @@ public void addCalibrationToConfig(CameraCalibrationCoefficients newCalibration)
680680
saveAndBroadcastAll();
681681
}
682682

683+
public void removeCalibrationFromConfig(Size unrotatedImageSize) {
684+
if (unrotatedImageSize != null) {
685+
visionSource.getSettables().removeCalibration(unrotatedImageSize);
686+
} else {
687+
logger.error("Got null size?");
688+
}
689+
690+
saveAndBroadcastAll();
691+
}
692+
683693
/**
684694
* Add/remove quirks from the camera we're controlling
685695
*

photon-core/src/main/java/org/photonvision/vision/processes/VisionSourceSettables.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import edu.wpi.first.cscore.VideoMode;
2121
import java.util.HashMap;
22+
import org.opencv.core.Size;
2223
import org.photonvision.common.configuration.CameraConfiguration;
2324
import org.photonvision.common.logging.LogGroup;
2425
import org.photonvision.common.logging.Logger;
@@ -120,6 +121,11 @@ public void addCalibration(CameraCalibrationCoefficients calibrationCoefficients
120121
calculateFrameStaticProps();
121122
}
122123

124+
public void removeCalibration(Size unrotatedImageSize) {
125+
configuration.removeCalibration(unrotatedImageSize);
126+
calculateFrameStaticProps();
127+
}
128+
123129
protected void calculateFrameStaticProps() {
124130
var videoMode = getCurrentVideoMode();
125131
this.frameStaticProperties =

photon-server/src/main/java/org/photonvision/server/RequestHandler.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.opencv.core.Mat;
3636
import org.opencv.core.MatOfByte;
3737
import org.opencv.core.MatOfInt;
38+
import org.opencv.core.Size;
3839
import org.opencv.imgcodecs.Imgcodecs;
3940
import org.photonvision.common.configuration.ConfigManager;
4041
import org.photonvision.common.configuration.NetworkConfig;
@@ -1001,6 +1002,46 @@ public static void onMetricsPublishRequest(Context ctx) {
10011002
ctx.status(204);
10021003
}
10031004

1005+
private record CalibrationRemoveRequest(int width, int height, String cameraUniqueName) {}
1006+
1007+
public static void onCalibrationRemoveRequest(Context ctx) {
1008+
try {
1009+
CalibrationRemoveRequest request =
1010+
kObjectMapper.readValue(ctx.body(), CalibrationRemoveRequest.class);
1011+
1012+
logger.info(
1013+
"Attempting to remove calibration for camera: "
1014+
+ request.cameraUniqueName
1015+
+ " with a resolution of "
1016+
+ request.width
1017+
+ "x"
1018+
+ request.height);
1019+
1020+
VisionSourceManager.getInstance()
1021+
.vmm
1022+
.getModule(request.cameraUniqueName)
1023+
.removeCalibrationFromConfig(new Size(request.width, request.height));
1024+
1025+
ctx.status(200);
1026+
ctx.result(
1027+
"Successfully removed calibration for resolution: "
1028+
+ request.width
1029+
+ "x"
1030+
+ request.height);
1031+
logger.info(
1032+
"Successfully removed calibration for resolution: "
1033+
+ request.width
1034+
+ "x"
1035+
+ request.height);
1036+
} catch (JsonProcessingException e) {
1037+
ctx.status(400).result("Invalid JSON format");
1038+
logger.error("Failed to process calibration removed request", e);
1039+
} catch (Exception e) {
1040+
ctx.status(500).result("Failed to removed calibration");
1041+
logger.error("Unexpected error while attempting to remove calibration", e);
1042+
}
1043+
}
1044+
10041045
public static void onCalibrationSnapshotRequest(Context ctx) {
10051046
String cameraUniqueName = ctx.queryParam("cameraUniqueName");
10061047
var width = Integer.parseInt(ctx.queryParam("width"));

photon-server/src/main/java/org/photonvision/server/Server.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ private static void start(int port) {
148148
// Calibration
149149
app.post("/api/calibration/end", RequestHandler::onCalibrationEndRequest);
150150
app.post("/api/calibration/importFromData", RequestHandler::onDataCalibrationImportRequest);
151+
app.post("/api/calibration/remove", RequestHandler::onCalibrationRemoveRequest);
151152

152153
// Object detection
153154
app.post("/api/objectdetection/import", RequestHandler::onImportObjectDetectionModelRequest);

0 commit comments

Comments
 (0)