From 4750cd01096a4b28d8dae1d3ccb3549d974796d8 Mon Sep 17 00:00:00 2001 From: thatcomputerguy0101 Date: Sun, 10 May 2026 07:04:08 -0400 Subject: [PATCH 1/4] Convert backend to use mm for calibration --- .../cameras/CameraCalibrationCard.vue | 50 +++++++++++-------- .../stores/settings/CameraSettingsStore.ts | 4 +- photon-client/src/types/WebsocketDataTypes.ts | 4 +- .../vision/pipeline/UICalibrationData.java | 20 ++++---- .../vision/processes/VisionModule.java | 5 +- 5 files changed, 44 insertions(+), 39 deletions(-) diff --git a/photon-client/src/components/cameras/CameraCalibrationCard.vue b/photon-client/src/components/cameras/CameraCalibrationCard.vue index 1bd01bc8d3..511f1a794c 100644 --- a/photon-client/src/components/cameras/CameraCalibrationCard.vue +++ b/photon-client/src/components/cameras/CameraCalibrationCard.vue @@ -110,8 +110,8 @@ watchEffect(() => { uniqueVideoResolutionIndex.value = currentIndex; }); const dimensionUnit = ref<"in" | "mm">("in"); -const squareSizeIn = ref(1); -const markerSizeIn = ref(0.75); +const squareSizeMm = ref(30); +const markerSizeMm = ref(22); const patternWidth = ref(8); const patternHeight = ref(8); const boardType = ref(CalibrationBoardTypes.Charuco); @@ -119,23 +119,23 @@ const useOldPattern = ref(false); const tagFamily = ref(CalibrationTagFamilies.Dict_4X4_1000); const requestedVideoFormatIndex = ref(0); -const convertInchesToDisplay = (valueInInches: number) => - dimensionUnit.value === "mm" ? valueInInches * MM_PER_INCH : valueInInches; +const convertMetricToDisplay = (valueInMm: number) => + dimensionUnit.value === "in" ? valueInMm / MM_PER_INCH : valueInMm; -const convertDisplayToInches = (displayValue: number) => - dimensionUnit.value === "mm" ? displayValue / MM_PER_INCH : displayValue; +const convertDisplayToMetric = (displayValue: number) => + dimensionUnit.value === "in" ? displayValue * MM_PER_INCH : displayValue; const squareSize = computed({ - get: () => convertInchesToDisplay(squareSizeIn.value), + get: () => convertMetricToDisplay(squareSizeMm.value), set(value) { - squareSizeIn.value = convertDisplayToInches(value); + squareSizeMm.value = convertDisplayToMetric(value); } }); const markerSize = computed({ - get: () => convertInchesToDisplay(markerSizeIn.value), + get: () => convertMetricToDisplay(markerSizeMm.value), set(value) { - markerSizeIn.value = convertDisplayToInches(value); + markerSizeMm.value = convertDisplayToMetric(value); } }); @@ -149,7 +149,7 @@ const tooManyPoints = computed( const downloadCalibBoard = async () => { const { jsPDF } = await jspdf; const { font } = await PromptRegular; - const doc = new jsPDF({ unit: "in", format: "letter" }); + const doc = new jsPDF({ unit: "mm", format: "letter" }); doc.addFileToVFS("Prompt-Regular.tff", font); doc.addFont("Prompt-Regular.tff", "Prompt-Regular", "normal"); @@ -161,28 +161,34 @@ const downloadCalibBoard = async () => { switch (boardType.value) { case CalibrationBoardTypes.Chessboard: - const chessboardStartX = (paperWidth - patternWidth.value * squareSizeIn.value) / 2; + const chessboardStartX = (paperWidth - patternWidth.value * squareSizeMm.value) / 2; - const chessboardStartY = (paperHeight - patternWidth.value * squareSizeIn.value) / 2; + const chessboardStartY = (paperHeight - patternWidth.value * squareSizeMm.value) / 2; for (let squareY = 0; squareY < patternHeight.value; squareY++) { for (let squareX = 0; squareX < patternWidth.value; squareX++) { - const xPos = chessboardStartX + squareX * squareSizeIn.value; - const yPos = chessboardStartY + squareY * squareSizeIn.value; + const xPos = chessboardStartX + squareX * squareSizeMm.value; + const yPos = chessboardStartY + squareY * squareSizeMm.value; // Only draw the odd squares to create the chessboard pattern if (squareY % 2 !== squareX % 2) { - doc.rect(xPos, yPos, squareSizeIn.value, squareSizeIn.value, "F"); + doc.rect(xPos, yPos, squareSizeMm.value, squareSizeMm.value, "F"); } } } - doc.text(`${patternWidth.value} x ${patternHeight.value} | ${squareSizeIn.value}in`, paperWidth - 1, 1.0, { - maxWidth: (paperWidth - 2.0) / 2, - align: "right" - }); + doc.text( + `${patternWidth.value} x ${patternHeight.value} | ${squareSize.value}${dimensionUnit.value}`, + paperWidth - 1, + 1.0, + { + maxWidth: (paperWidth - 2.0) / 2, + align: "right" + } + ); break; case CalibrationBoardTypes.Charuco: + // TODO: Dynamically generate ChArUco using opencv // Add pregenerated ChArUco const charucoImage = new Image(); charucoImage.src = CharucoImage; @@ -220,8 +226,8 @@ const isCalibrating = computed( const startCalibration = () => { useCameraSettingsStore().startPnPCalibration({ - squareSizeIn: squareSizeIn.value, - markerSizeIn: markerSizeIn.value, + squareSizeMm: squareSizeMm.value, + markerSizeMm: markerSizeMm.value, patternHeight: patternHeight.value, patternWidth: patternWidth.value, boardType: boardType.value, diff --git a/photon-client/src/stores/settings/CameraSettingsStore.ts b/photon-client/src/stores/settings/CameraSettingsStore.ts index 703cf3d9fc..ffa8bca9e0 100644 --- a/photon-client/src/stores/settings/CameraSettingsStore.ts +++ b/photon-client/src/stores/settings/CameraSettingsStore.ts @@ -368,8 +368,8 @@ export const useCameraSettingsStore = defineStore("cameraSettings", { */ startPnPCalibration( calibrationInitData: { - squareSizeIn: number; - markerSizeIn: number; + squareSizeMm: number; + markerSizeMm: number; patternWidth: number; patternHeight: number; boardType: CalibrationBoardTypes; diff --git a/photon-client/src/types/WebsocketDataTypes.ts b/photon-client/src/types/WebsocketDataTypes.ts index 3116f4667b..3a3e179a2f 100644 --- a/photon-client/src/types/WebsocketDataTypes.ts +++ b/photon-client/src/types/WebsocketDataTypes.ts @@ -87,8 +87,8 @@ export interface WebsocketCalibrationData { minCount: number; videoModeIndex: number; patternHeight: number; - squareSizeIn: number; - markerSizeIn: number; + squareSizeMm: number; + markerSizeMm: number; } export interface IncomingWebsocketData { diff --git a/photon-core/src/main/java/org/photonvision/vision/pipeline/UICalibrationData.java b/photon-core/src/main/java/org/photonvision/vision/pipeline/UICalibrationData.java index 21a049ca66..e748f9a9e1 100644 --- a/photon-core/src/main/java/org/photonvision/vision/pipeline/UICalibrationData.java +++ b/photon-core/src/main/java/org/photonvision/vision/pipeline/UICalibrationData.java @@ -24,11 +24,11 @@ public class UICalibrationData { public int videoModeIndex; public int count; - public double squareSizeIn; + public double squareSizeMm; public int patternWidth; public int patternHeight; public BoardType boardType; - public double markerSizeIn; + public double markerSizeMm; public boolean useOldPattern; public TagFamily tagFamily; @@ -37,8 +37,8 @@ public UICalibrationData() {} public UICalibrationData( int count, int videoModeIndex, - double squareSizeIn, - double markerSizeIn, + double squareSizeMm, + double markerSizeMm, int patternWidth, int patternHeight, BoardType boardType, @@ -46,8 +46,8 @@ public UICalibrationData( TagFamily tagFamily) { this.count = count; this.videoModeIndex = videoModeIndex; - this.squareSizeIn = squareSizeIn; - this.markerSizeIn = markerSizeIn; + this.squareSizeMm = squareSizeMm; + this.markerSizeMm = markerSizeMm; this.patternWidth = patternWidth; this.patternHeight = patternHeight; this.boardType = boardType; @@ -98,10 +98,10 @@ public String toString() { + videoModeIndex + ", count=" + count - + ", squareSizeIn=" - + squareSizeIn - + ", markerSizeIn=" - + markerSizeIn + + ", squareSizeMm=" + + squareSizeMm + + ", markerSizeMm=" + + markerSizeMm + ", patternWidth=" + patternWidth + ", patternHeight=" diff --git a/photon-core/src/main/java/org/photonvision/vision/processes/VisionModule.java b/photon-core/src/main/java/org/photonvision/vision/processes/VisionModule.java index 6ae1b8a9fa..16dbaf0e10 100644 --- a/photon-core/src/main/java/org/photonvision/vision/processes/VisionModule.java +++ b/photon-core/src/main/java/org/photonvision/vision/processes/VisionModule.java @@ -55,7 +55,6 @@ import org.photonvision.vision.pipeline.result.CVPipelineResult; import org.photonvision.vision.target.TargetModel; import org.photonvision.vision.target.TrackedTarget; -import org.wpilib.math.util.Units; import org.wpilib.vision.camera.CameraServerJNI; import org.wpilib.vision.camera.VideoException; @@ -391,8 +390,8 @@ public void startCalibration(UICalibrationData data) { + data.videoModeIndex + " and settings " + data); - settings.gridSize = Units.inchesToMeters(data.squareSizeIn); - settings.markerSize = Units.inchesToMeters(data.markerSizeIn); + settings.gridSize = data.squareSizeMm / 1000; + settings.markerSize = data.markerSizeMm / 1000; settings.boardHeight = data.patternHeight; settings.boardWidth = data.patternWidth; settings.boardType = data.boardType; From d7e7a74c6d1654bb9ae5f466e4b825588f7ff5dd Mon Sep 17 00:00:00 2001 From: thatcomputerguy0101 Date: Sat, 16 May 2026 11:34:22 -0400 Subject: [PATCH 2/4] Convert backend to meters, but store frontend in dynamic units --- .../cameras/CameraCalibrationCard.vue | 47 +++++++++---------- .../vision/pipeline/UICalibrationData.java | 20 ++++---- .../vision/processes/VisionModule.java | 4 +- 3 files changed, 35 insertions(+), 36 deletions(-) diff --git a/photon-client/src/components/cameras/CameraCalibrationCard.vue b/photon-client/src/components/cameras/CameraCalibrationCard.vue index 511f1a794c..9afb094595 100644 --- a/photon-client/src/components/cameras/CameraCalibrationCard.vue +++ b/photon-client/src/components/cameras/CameraCalibrationCard.vue @@ -1,5 +1,5 @@