From fba44db55423bc34bdb4b2e274dcee63fd6087ae Mon Sep 17 00:00:00 2001 From: Matt Date: Wed, 20 Dec 2023 09:30:38 -0500 Subject: [PATCH 1/8] Save and send camera calibration data --- photon-client/package.json | 4 + .../cameras/CameraCalibrationCard.vue | 78 ++++++++++++++-- .../src/components/common/LineChart.vue | 89 +++++++++++++++++++ .../stores/settings/CameraSettingsStore.ts | 11 +-- photon-client/src/types/SettingTypes.ts | 2 - .../configuration/PhotonConfiguration.java | 2 +- .../photonvision/common/util/ColorHelper.java | 3 + .../common/util/math/MathUtils.java | 17 ++++ .../CameraCalibrationCoefficients.java | 60 +++++++++---- .../vision/camera/USBCameraSource.java | 8 ++ .../vision/pipe/impl/Calibrate3dPipe.java | 83 ++++++++++------- .../vision/pipe/impl/DrawCalibrationPipe.java | 70 +++++++++++++++ .../pipe/impl/FindBoardCornersPipe.java | 42 ++++----- .../vision/pipeline/Calibrate3dPipeline.java | 30 +++++-- .../vision/pipeline/OutputStreamPipeline.java | 15 +++- .../result/CalibrationPipelineResult.java | 37 ++++++++ .../vision/processes/VisionModule.java | 18 ++-- .../vision/target/TrackedTarget.java | 8 ++ .../vision/pipeline/Calibrate3dPipeTest.java | 25 +++--- 19 files changed, 477 insertions(+), 125 deletions(-) create mode 100644 photon-client/src/components/common/LineChart.vue create mode 100644 photon-core/src/main/java/org/photonvision/vision/pipe/impl/DrawCalibrationPipe.java create mode 100644 photon-core/src/main/java/org/photonvision/vision/pipeline/result/CalibrationPipelineResult.java diff --git a/photon-client/package.json b/photon-client/package.json index 63a0e080bd..1353ab95a3 100644 --- a/photon-client/package.json +++ b/photon-client/package.json @@ -17,10 +17,14 @@ "@mdi/font": "^7.2.96", "@msgpack/msgpack": "^3.0.0-beta2", "axios": "^1.4.0", + "chart.js": "^2.9.3", + "core-js": "^3.30.2", "jspdf": "^2.5.1", "pinia": "^2.1.4", "three": "^0.154.0", "vue": "^2.7.14", + "vue-axios": "^3.5.2", + "vue-chartjs": "^3.5.1", "vue-router": "^3.6.5", "vuetify": "^2.6.15" }, diff --git a/photon-client/src/components/cameras/CameraCalibrationCard.vue b/photon-client/src/components/cameras/CameraCalibrationCard.vue index 0bbfbe3df9..7a73fa7aeb 100644 --- a/photon-client/src/components/cameras/CameraCalibrationCard.vue +++ b/photon-client/src/components/cameras/CameraCalibrationCard.vue @@ -31,7 +31,6 @@ const getUniqueVideoResolutions = (): VideoFormat[] => { const calib = getCalibrationCoeffs(format.resolution); if (calib !== undefined) { - format.standardDeviation = calib.standardDeviation; format.mean = calib.perViewErrors.reduce((a, b) => a + b) / calib.perViewErrors.length; format.horizontalFOV = 2 * Math.atan2(format.resolution.width / 2, calib.intrinsics[0]) * (180 / Math.PI); format.verticalFOV = 2 * Math.atan2(format.resolution.height / 2, calib.intrinsics[4]) * (180 / Math.PI); @@ -214,6 +213,71 @@ const endCalibration = () => { isCalibrating.value = false; }); }; + + +const createSeries = ( + label, + xData, + yData, + color, + showLine = true, + fill = false, +) => { + if (xData.length !== yData.length) { + return null; + } + + if (xData == null || yData == null) { + console.log("Data was null. Skipping."); + return null; + } + + // Convert data to list of x/y pairs + let data = []; + yData.forEach((y, idx) => { + if (!isNaN(y) || y != null) { + data.push({ x: xData[idx], y: y }); + } + }); + return { + backgroundColor: color, + borderColor: color, + label: label, + showLine: showLine, + fill: fill, + data: data, + lineTension: 0, + }; +}; + +const reprojectionErrorSeries = () => { + // HUGE hack! + const calib = useCameraSettingsStore().currentCameraSettings.completeCalibrations[0]; + + const errorNorms = calib.observations.map(it2 => it2.reprojectionErrors).map(it2 => it2.map(it3 => Math.sqrt(it3.x * it3.x + it3.y * it3.y))).flat(1); + const xLocs = calib.observations.map(it => it.locationInImageSpace.map(it => it.x)).flat(1); + const yLocs = calib.observations.map(it => it.locationInImageSpace.map(it => it.y)).flat(1); + console.log(errorNorms); + console.log(xLocs); + console.log(yLocs); + + function rgb(r, g, b){ + return "rgb("+r+","+g+","+b+")"; + } + + const colors = errorNorms.map(it => rgb(it * 200, 0, 0)) + + return { + datasets: [ + createSeries( + `Reprojection error`, + xLocs, yLocs, colors, + false + ), + ], + }; +} +