diff --git a/photon-client/package-lock.json b/photon-client/package-lock.json index 1f579daa8e..cad4fa4db4 100644 --- a/photon-client/package-lock.json +++ b/photon-client/package-lock.json @@ -5,6 +5,7 @@ "requires": true, "packages": { "": { + "name": "photon-client", "version": "3.0.0", "dependencies": { "@femessage/log-viewer": "^1.4.2", @@ -2682,7 +2683,6 @@ "thread-loader": "^2.1.3", "url-loader": "^2.2.0", "vue-loader": "^15.9.2", - "vue-loader-v16": "npm:vue-loader@^16.0.0-beta.3", "vue-style-loader": "^4.1.2", "webpack": "^4.0.0", "webpack-bundle-analyzer": "^3.8.0", @@ -3116,7 +3116,6 @@ "merge-source-map": "^1.1.0", "postcss": "^7.0.14", "postcss-selector-parser": "^6.0.2", - "prettier": "^1.18.2", "source-map": "~0.6.1", "vue-template-es2015-compiler": "^1.9.0" }, @@ -4703,7 +4702,6 @@ "dependencies": { "anymatch": "~3.1.1", "braces": "~3.0.2", - "fsevents": "~2.1.2", "glob-parent": "~5.1.0", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", @@ -9167,9 +9165,6 @@ "version": "4.0.0", "dev": true, "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.6" - }, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -9181,11 +9176,7 @@ "@babel/runtime": "^7.14.0", "atob": "^2.1.2", "btoa": "^1.2.1", - "canvg": "^3.0.6", - "core-js": "^3.6.0", - "dompurify": "^2.2.0", - "fflate": "^0.4.8", - "html2canvas": "^1.0.0-rc.5" + "fflate": "^0.4.8" }, "optionalDependencies": { "canvg": "^3.0.6", @@ -14200,10 +14191,8 @@ "dev": true, "license": "MIT", "dependencies": { - "chokidar": "^3.4.0", "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0", - "watchpack-chokidar2": "^2.0.0" + "neo-async": "^2.5.0" }, "optionalDependencies": { "chokidar": "^3.4.0", @@ -14312,7 +14301,6 @@ "anymatch": "^2.0.0", "async-each": "^1.0.1", "braces": "^2.3.2", - "fsevents": "^1.2.7", "glob-parent": "^3.1.0", "inherits": "^2.0.3", "is-binary-path": "^1.0.0", @@ -14553,7 +14541,6 @@ "anymatch": "^2.0.0", "async-each": "^1.0.1", "braces": "^2.3.2", - "fsevents": "^1.2.7", "glob-parent": "^3.1.0", "inherits": "^2.0.3", "is-binary-path": "^1.0.0", diff --git a/photon-client/src/views/CamerasView.vue b/photon-client/src/views/CamerasView.vue index 4ade293daa..2cabc81339 100644 --- a/photon-client/src/views/CamerasView.vue +++ b/photon-client/src/views/CamerasView.vue @@ -299,6 +299,19 @@ Download Target + + + + mdi-camera-iris + + Focus Camera + + @@ -387,6 +400,77 @@ + + + @@ -427,9 +511,13 @@ export default { }, data() { return { - snack: false, + calibrationSnack: false, + focusSnack: false, calibrationInProgress: false, calibrationFailed: false, + focusInProgress: false, + focusFailed: false, + focusQueryInterval: null, filteredVideomodeIndex: 0, settingsValid: true, unfilteredStreamDivisors: [1, 2, 4], @@ -655,9 +743,15 @@ export default { }, closeDialog() { - this.snack = false; + this.calibrationSnack = false; + this.focusSnack = false; + + this.focusInProgress = false; + this.focusFailed = false; this.calibrationInProgress = false; this.calibrationFailed = false; + + clearInterval(this.focusQueryInterval); }, getCalibrationCoeffs(resolution) { const calList = this.$store.getters.calibrationList; @@ -762,6 +856,44 @@ export default { doc.save("calibrationTarget.pdf"); }, + focusCamera() { + this.focusSnack = true; + this.focusFailed = false; + this.focusInProgress = true; + + this.axios.post("http://" + this.$address + "/api/autofocusCamera", { + "index": this.$store.state.currentCameraIndex + }).then(()=> { + // check every 500ms + this.focusQueryInterval = setInterval(()=>this.checkFocusStatus(), 500) + } + ).catch(res=>{ + this.focusFailed = true; + clearInterval(this.focusQueryInterval); + console.error(res) + }) + }, + checkFocusStatus() { + console.log("Checking focus status..."); + this.axios.post("http://" + this.$address + "/api/getAutofocusStatus", { + "index": this.$store.state.currentCameraIndex + }).then(response => { + if(response == null || response.data == null || response.data == -1 || response.data == 0 || response.data == 3) { + this.focusFailed = true; + clearInterval(this.focusQueryInterval); + console.error(response) + } else if (response.data == 2) { + this.focusFailed = false; + clearInterval(this.focusQueryInterval); + this.focusInProgress = false; + } + } + ).catch(res=>{ + this.focusFailed = true; + clearInterval(this.focusQueryInterval); + console.error(res) + }) + }, sendCameraSettings() { this.axios.post("http://" + this.$address + "/api/settings/camera", { "settings": this.cameraSettings, @@ -800,7 +932,7 @@ export default { sendCalibrationFinish() { console.log("finishing calibration for index " + this.$store.getters.currentCameraIndex); - this.snack = true; + this.calibrationSnack = true; this.calibrationInProgress = true; this.axios.post("http://" + this.$address + "/api/settings/endCalibration", this.$store.getters.currentCameraIndex) diff --git a/photon-core/src/main/java/org/photonvision/raspi/LibCameraJNI.java b/photon-core/src/main/java/org/photonvision/raspi/LibCameraJNI.java index 4ebc2c8735..256fa8376c 100644 --- a/photon-core/src/main/java/org/photonvision/raspi/LibCameraJNI.java +++ b/photon-core/src/main/java/org/photonvision/raspi/LibCameraJNI.java @@ -140,6 +140,12 @@ public static native boolean setThresholds( // Exposure time, in microseconds public static native boolean setExposure(int exposureUs); + + // Return int of autofocus status from libcamera AfState + public static native int getAutofocusStatus(); + + // Set whether or not to use autofocus + public static native boolean setAutofocus(boolean doAutoFocus); // Set brighness on [-1, 1] public static native boolean setBrightness(double brightness); diff --git a/photon-core/src/main/java/org/photonvision/vision/camera/LibcameraGpuSettables.java b/photon-core/src/main/java/org/photonvision/vision/camera/LibcameraGpuSettables.java index f3b32d44c2..61cf659f49 100644 --- a/photon-core/src/main/java/org/photonvision/vision/camera/LibcameraGpuSettables.java +++ b/photon-core/src/main/java/org/photonvision/vision/camera/LibcameraGpuSettables.java @@ -187,6 +187,16 @@ public void setAwbGain(int red, int blue) { } } + @Override + public int getAutofocusStatus() { + return LibCameraJNI.getAutofocusStatus(); + } + + @Override + public void autofocus() { + LibCameraJNI.setAutofocus(true); + } + @Override public FPSRatedVideoMode getCurrentVideoMode() { return currentVideoMode; diff --git a/photon-core/src/main/java/org/photonvision/vision/pipeline/CVPipelineSettings.java b/photon-core/src/main/java/org/photonvision/vision/pipeline/CVPipelineSettings.java index 077b4254a1..dcb76ba443 100644 --- a/photon-core/src/main/java/org/photonvision/vision/pipeline/CVPipelineSettings.java +++ b/photon-core/src/main/java/org/photonvision/vision/pipeline/CVPipelineSettings.java @@ -42,6 +42,7 @@ public class CVPipelineSettings implements Cloneable { public boolean cameraAutoExposure = false; // manual exposure only used if cameraAutoExposure if false public double cameraExposure = 20; + public boolean cameraAutoFocus = false; public int cameraBrightness = 50; // Currently only used by a few cameras (notably the zero-copy Pi Camera driver) with the Gain // quirk 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 82dd668126..1612fc57eb 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 @@ -478,6 +478,14 @@ public void setCameraNickname(String newName) { saveAndBroadcastAll(); } + public int getAutofocusStatus() { + return visionSource.getSettables().getAutofocusStatus(); + } + + public void autofocus() { + visionSource.getSettables().autofocus(); + } + public PhotonConfiguration.UICameraConfiguration toUICameraConfig() { var ret = new PhotonConfiguration.UICameraConfiguration(); diff --git a/photon-core/src/main/java/org/photonvision/vision/processes/VisionSourceSettables.java b/photon-core/src/main/java/org/photonvision/vision/processes/VisionSourceSettables.java index bbabf6ba96..ff0acca0ff 100644 --- a/photon-core/src/main/java/org/photonvision/vision/processes/VisionSourceSettables.java +++ b/photon-core/src/main/java/org/photonvision/vision/processes/VisionSourceSettables.java @@ -45,7 +45,7 @@ public CameraConfiguration getConfiguration() { public abstract void setExposure(double exposure); public abstract void setAutoExposure(boolean cameraAutoExposure); - + public abstract void setBrightness(int brightness); public abstract void setGain(int gain); @@ -57,6 +57,10 @@ public void setBlueGain(int blue) {} public abstract VideoMode getCurrentVideoMode(); + public void autofocus(){} + + public int getAutofocusStatus(){return -1;} + public void setVideoModeInternal(int index) { setVideoMode(getAllVideoModes().get(index)); } diff --git a/photon-core/src/test/java/org/photonvision/vision/processes/VisionModuleManagerTest.java b/photon-core/src/test/java/org/photonvision/vision/processes/VisionModuleManagerTest.java index b6cdc59851..d7a529a4ef 100644 --- a/photon-core/src/test/java/org/photonvision/vision/processes/VisionModuleManagerTest.java +++ b/photon-core/src/test/java/org/photonvision/vision/processes/VisionModuleManagerTest.java @@ -97,6 +97,9 @@ public HashMap getAllVideoModes() { @Override public void setAutoExposure(boolean cameraAutoExposure) {} + + @Override + public void setAutoFocus(boolean cameraAutoFocus) {} } private static class TestDataConsumer implements CVPipelineResultConsumer { diff --git a/photon-server/lib/libphotonlibcamera.so b/photon-server/lib/libphotonlibcamera.so index f11ed7338a..13bcbc05b5 100644 Binary files a/photon-server/lib/libphotonlibcamera.so and b/photon-server/lib/libphotonlibcamera.so differ diff --git a/photon-server/src/main/java/org/photonvision/server/RequestHandler.java b/photon-server/src/main/java/org/photonvision/server/RequestHandler.java index b611fc3082..ba31e530d9 100644 --- a/photon-server/src/main/java/org/photonvision/server/RequestHandler.java +++ b/photon-server/src/main/java/org/photonvision/server/RequestHandler.java @@ -317,6 +317,35 @@ public static void importCalibrationFromCalibdb(Context ctx) { } } + public static void autofocusCamera(Context ctx) { + try { + var data = kObjectMapper.readValue(ctx.body(), HashMap.class); + int idx = Integer.parseInt(String.valueOf(data.get("index"))); + VisionModuleManager.getInstance().getModule(idx).autofocus(); + ctx.status(200); + return; + } catch (Exception e) { + logger.warn("Failed to start autofocus!"); + e.printStackTrace(); + } + ctx.status(500); + } + + public static void getAutofocusStatus(Context ctx) { + try { + var data = kObjectMapper.readValue(ctx.body(), HashMap.class); + int idx = Integer.parseInt(String.valueOf(data.get("index"))); + int status = VisionModuleManager.getInstance().getModule(idx).getAutofocusStatus(); + ctx.result(String.valueOf(status)); + ctx.status(200); + return; + } catch (Exception e) { + logger.warn("Could not check if camera supports autofocus!"); + e.printStackTrace(); + } + ctx.status(500); + } + public static void setCameraNickname(Context ctx) { try { var data = kObjectMapper.readValue(ctx.body(), HashMap.class); diff --git a/photon-server/src/main/java/org/photonvision/server/Server.java b/photon-server/src/main/java/org/photonvision/server/Server.java index a67dae8a10..7434f067c9 100644 --- a/photon-server/src/main/java/org/photonvision/server/Server.java +++ b/photon-server/src/main/java/org/photonvision/server/Server.java @@ -92,6 +92,8 @@ public static void main(int port) { app.post("api/restartProgram", RequestHandler::restartProgram); app.post("api/vision/pnpModel", RequestHandler::uploadPnpModel); app.post("api/sendMetrics", RequestHandler::sendMetrics); + app.post("/api/getAutofocusStatus", RequestHandler::getAutofocusStatus); + app.post("/api/autofocusCamera", RequestHandler::autofocusCamera); app.post("api/setCameraNickname", RequestHandler::setCameraNickname); app.post("api/calibration/import", RequestHandler::importCalibrationFromCalibdb);