mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-24 01:31:44 +00:00
Store calibration board measurements in native units (#2480)
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
"type-check": "vue-tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@adam-rocska/units-and-measurement": "^1.2.0",
|
||||
"@fontsource/prompt": "^5.2.6",
|
||||
"@mdi/font": "^7.4.47",
|
||||
"@msgpack/msgpack": "^3.1.2",
|
||||
|
||||
25
photon-client/pnpm-lock.yaml
generated
25
photon-client/pnpm-lock.yaml
generated
@@ -8,6 +8,9 @@ importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
'@adam-rocska/units-and-measurement':
|
||||
specifier: ^1.2.0
|
||||
version: 1.2.0
|
||||
'@fontsource/prompt':
|
||||
specifier: ^5.2.6
|
||||
version: 5.2.6
|
||||
@@ -96,6 +99,10 @@ importers:
|
||||
|
||||
packages:
|
||||
|
||||
'@adam-rocska/units-and-measurement@1.2.0':
|
||||
resolution: {integrity: sha512-mBnZ8/STbztVec+Mz9DH932z0gny52SebtSJ/y3n+IVtuF7KqbtQ3t1u1lpFSkLFU1msaNGzFgqsW7Emj0lrXA==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
'@babel/helper-string-parser@7.27.1':
|
||||
resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@@ -250,42 +257,36 @@ packages:
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@parcel/watcher-linux-arm-musl@2.5.1':
|
||||
resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@parcel/watcher-linux-arm64-glibc@2.5.1':
|
||||
resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@parcel/watcher-linux-arm64-musl@2.5.1':
|
||||
resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@parcel/watcher-linux-x64-glibc@2.5.1':
|
||||
resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@parcel/watcher-linux-x64-musl@2.5.1':
|
||||
resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@parcel/watcher-win32-arm64@2.5.1':
|
||||
resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==}
|
||||
@@ -353,42 +354,36 @@ packages:
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rolldown/binding-linux-arm64-musl@1.0.0-rc.17':
|
||||
resolution: {integrity: sha512-b/CgbwAJpmrRLp02RPfhbudf5tZnN9nsPWK82znefso832etkem8H7FSZwxrOI9djcdTP7U6YfNhbRnh7djErg==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.17':
|
||||
resolution: {integrity: sha512-4EII1iNGRUN5WwGbF/kOh/EIkoDN9HsupgLQoXfY+D1oyJm7/F4t5PYU5n8SWZgG0FEwakyM8pGgwcBYruGTlA==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rolldown/binding-linux-s390x-gnu@1.0.0-rc.17':
|
||||
resolution: {integrity: sha512-AH8oq3XqQo4IibpVXvPeLDI5pzkpYn0WiZAfT05kFzoJ6tQNzwRdDYQ45M8I/gslbodRZwW8uxLhbSBbkv96rA==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rolldown/binding-linux-x64-gnu@1.0.0-rc.17':
|
||||
resolution: {integrity: sha512-cLnjV3xfo7KslbU41Z7z8BH/E1y5mzUYzAqih1d1MDaIGZRCMqTijqLv76/P7fyHuvUcfGsIpqCdddbxLLK9rA==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rolldown/binding-linux-x64-musl@1.0.0-rc.17':
|
||||
resolution: {integrity: sha512-0phclDw1spsL7dUB37sIARuis2tAgomCJXAHZlpt8PXZ4Ba0dRP1e+66lsRqrfhISeN9bEGNjQs+T/Fbd7oYGw==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rolldown/binding-openharmony-arm64@1.0.0-rc.17':
|
||||
resolution: {integrity: sha512-0ag/hEgXOwgw4t8QyQvUCxvEg+V0KBcA6YuOx9g0r02MprutRF5dyljgm3EmR02O292UX7UeS6HzWHAl6KgyhA==}
|
||||
@@ -1084,28 +1079,24 @@ packages:
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
lightningcss-linux-arm64-musl@1.32.0:
|
||||
resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
lightningcss-linux-x64-gnu@1.32.0:
|
||||
resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
lightningcss-linux-x64-musl@1.32.0:
|
||||
resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
lightningcss-win32-arm64-msvc@1.32.0:
|
||||
resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==}
|
||||
@@ -1550,6 +1541,8 @@ packages:
|
||||
|
||||
snapshots:
|
||||
|
||||
'@adam-rocska/units-and-measurement@1.2.0': {}
|
||||
|
||||
'@babel/helper-string-parser@7.27.1': {}
|
||||
|
||||
'@babel/helper-validator-identifier@7.27.1': {}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watchEffect } from "vue";
|
||||
import { computed, ref, watch, watchEffect } from "vue";
|
||||
import { useCameraSettingsStore } from "@/stores/settings/CameraSettingsStore";
|
||||
import { CalibrationBoardTypes, CalibrationTagFamilies, type VideoFormat } from "@/types/SettingTypes";
|
||||
import MonoLogo from "@/assets/images/logoMono.png";
|
||||
@@ -15,12 +15,12 @@ import CameraCalibrationInfoCard from "@/components/cameras/CameraCalibrationInf
|
||||
import { useSettingsStore } from "@/stores/settings/GeneralSettingsStore";
|
||||
import { useTheme } from "vuetify";
|
||||
import TooltippedLabel from "@/components/common/pv-tooltipped-label.vue";
|
||||
import { length } from "@adam-rocska/units-and-measurement/length";
|
||||
|
||||
const PromptRegular = import("@/assets/fonts/PromptRegular");
|
||||
const jspdf = import("jspdf");
|
||||
|
||||
const theme = useTheme();
|
||||
const MM_PER_INCH = 25.4;
|
||||
|
||||
const settingsValid = ref(true);
|
||||
|
||||
@@ -110,8 +110,8 @@ watchEffect(() => {
|
||||
uniqueVideoResolutionIndex.value = currentIndex;
|
||||
});
|
||||
const dimensionUnit = ref<"in" | "mm">("in");
|
||||
const squareSizeIn = ref(1);
|
||||
const markerSizeIn = ref(0.75);
|
||||
const squareSize = ref(30);
|
||||
const markerSize = ref(22);
|
||||
const patternWidth = ref(8);
|
||||
const patternHeight = ref(8);
|
||||
const boardType = ref<CalibrationBoardTypes>(CalibrationBoardTypes.Charuco);
|
||||
@@ -119,24 +119,9 @@ const useOldPattern = ref(false);
|
||||
const tagFamily = ref<CalibrationTagFamilies>(CalibrationTagFamilies.Dict_4X4_1000);
|
||||
const requestedVideoFormatIndex = ref(0);
|
||||
|
||||
const convertInchesToDisplay = (valueInInches: number) =>
|
||||
dimensionUnit.value === "mm" ? valueInInches * MM_PER_INCH : valueInInches;
|
||||
|
||||
const convertDisplayToInches = (displayValue: number) =>
|
||||
dimensionUnit.value === "mm" ? displayValue / MM_PER_INCH : displayValue;
|
||||
|
||||
const squareSize = computed({
|
||||
get: () => convertInchesToDisplay(squareSizeIn.value),
|
||||
set(value) {
|
||||
squareSizeIn.value = convertDisplayToInches(value);
|
||||
}
|
||||
});
|
||||
|
||||
const markerSize = computed({
|
||||
get: () => convertInchesToDisplay(markerSizeIn.value),
|
||||
set(value) {
|
||||
markerSizeIn.value = convertDisplayToInches(value);
|
||||
}
|
||||
watch(dimensionUnit, (value, oldValue) => {
|
||||
squareSize.value = length[oldValue](squareSize.value)[value].value;
|
||||
markerSize.value = length[oldValue](markerSize.value)[value].value;
|
||||
});
|
||||
|
||||
const dimensionStep = computed(() => (dimensionUnit.value === "mm" ? 0.1 : 0.01));
|
||||
@@ -161,25 +146,31 @@ const downloadCalibBoard = async () => {
|
||||
|
||||
switch (boardType.value) {
|
||||
case CalibrationBoardTypes.Chessboard:
|
||||
const chessboardStartX = (paperWidth - patternWidth.value * squareSizeIn.value) / 2;
|
||||
const squareSizeIn = length[dimensionUnit.value](squareSize.value).in.value;
|
||||
const chessboardStartX = (paperWidth - patternWidth.value * squareSizeIn) / 2;
|
||||
|
||||
const chessboardStartY = (paperHeight - patternWidth.value * squareSizeIn.value) / 2;
|
||||
const chessboardStartY = (paperHeight - patternHeight.value * squareSizeIn) / 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 * squareSizeIn;
|
||||
const yPos = chessboardStartY + squareY * squareSizeIn;
|
||||
|
||||
// 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, squareSizeIn, squareSizeIn, "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:
|
||||
@@ -220,8 +211,8 @@ const isCalibrating = computed(
|
||||
|
||||
const startCalibration = () => {
|
||||
useCameraSettingsStore().startPnPCalibration({
|
||||
squareSizeIn: squareSizeIn.value,
|
||||
markerSizeIn: markerSizeIn.value,
|
||||
squareSizeMeters: length[dimensionUnit.value](squareSize.value).m.value,
|
||||
markerSizeMeters: length[dimensionUnit.value](markerSize.value).m.value,
|
||||
patternHeight: patternHeight.value,
|
||||
patternWidth: patternWidth.value,
|
||||
boardType: boardType.value,
|
||||
|
||||
@@ -368,8 +368,8 @@ export const useCameraSettingsStore = defineStore("cameraSettings", {
|
||||
*/
|
||||
startPnPCalibration(
|
||||
calibrationInitData: {
|
||||
squareSizeIn: number;
|
||||
markerSizeIn: number;
|
||||
squareSizeMeters: number;
|
||||
markerSizeMeters: number;
|
||||
patternWidth: number;
|
||||
patternHeight: number;
|
||||
boardType: CalibrationBoardTypes;
|
||||
|
||||
@@ -87,8 +87,8 @@ export interface WebsocketCalibrationData {
|
||||
minCount: number;
|
||||
videoModeIndex: number;
|
||||
patternHeight: number;
|
||||
squareSizeIn: number;
|
||||
markerSizeIn: number;
|
||||
squareSizeMm: number;
|
||||
markerSizeMm: number;
|
||||
}
|
||||
|
||||
export interface IncomingWebsocketData {
|
||||
|
||||
@@ -24,11 +24,11 @@ import org.opencv.objdetect.Objdetect;
|
||||
public class UICalibrationData {
|
||||
public int videoModeIndex;
|
||||
public int count;
|
||||
public double squareSizeIn;
|
||||
public double squareSizeMeters;
|
||||
public int patternWidth;
|
||||
public int patternHeight;
|
||||
public BoardType boardType;
|
||||
public double markerSizeIn;
|
||||
public double markerSizeMeters;
|
||||
public boolean useOldPattern;
|
||||
public TagFamily tagFamily;
|
||||
|
||||
@@ -37,8 +37,8 @@ public class UICalibrationData {
|
||||
public UICalibrationData(
|
||||
int count,
|
||||
int videoModeIndex,
|
||||
double squareSizeIn,
|
||||
double markerSizeIn,
|
||||
double squareSizeMeters,
|
||||
double markerSizeMeters,
|
||||
int patternWidth,
|
||||
int patternHeight,
|
||||
BoardType boardType,
|
||||
@@ -46,8 +46,8 @@ public class UICalibrationData {
|
||||
TagFamily tagFamily) {
|
||||
this.count = count;
|
||||
this.videoModeIndex = videoModeIndex;
|
||||
this.squareSizeIn = squareSizeIn;
|
||||
this.markerSizeIn = markerSizeIn;
|
||||
this.squareSizeMeters = squareSizeMeters;
|
||||
this.markerSizeMeters = markerSizeMeters;
|
||||
this.patternWidth = patternWidth;
|
||||
this.patternHeight = patternHeight;
|
||||
this.boardType = boardType;
|
||||
@@ -98,10 +98,10 @@ public class UICalibrationData {
|
||||
+ videoModeIndex
|
||||
+ ", count="
|
||||
+ count
|
||||
+ ", squareSizeIn="
|
||||
+ squareSizeIn
|
||||
+ ", markerSizeIn="
|
||||
+ markerSizeIn
|
||||
+ ", squareSizeMeters="
|
||||
+ squareSizeMeters
|
||||
+ ", markerSizeMeters="
|
||||
+ markerSizeMeters
|
||||
+ ", patternWidth="
|
||||
+ patternWidth
|
||||
+ ", patternHeight="
|
||||
|
||||
@@ -55,7 +55,6 @@ import org.photonvision.vision.pipeline.UICalibrationData;
|
||||
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 class VisionModule {
|
||||
+ data.videoModeIndex
|
||||
+ " and settings "
|
||||
+ data);
|
||||
settings.gridSize = Units.inchesToMeters(data.squareSizeIn);
|
||||
settings.markerSize = Units.inchesToMeters(data.markerSizeIn);
|
||||
settings.gridSize = data.squareSizeMeters;
|
||||
settings.markerSize = data.markerSizeMeters;
|
||||
settings.boardHeight = data.patternHeight;
|
||||
settings.boardWidth = data.patternWidth;
|
||||
settings.boardType = data.boardType;
|
||||
|
||||
Reference in New Issue
Block a user