From 9f0e89ea29bd9f4c9a80039a4cef9e1e919d55dd Mon Sep 17 00:00:00 2001 From: Matt Date: Wed, 26 Aug 2020 10:03:56 -0700 Subject: [PATCH] UI 3d mode, ConfigManager bugfixes (#103) * stupid bugs I guess idk where else to put this commit * Run spotless * Fix config file loading Splits load into own method * Run spotless --- photon-client/src/assets/FRCtargets.json | 68 ++++++++++++++----- .../src/components/pipeline/3D/MiniMap.vue | 2 +- photon-client/src/store/index.js | 2 +- .../src/views/PipelineViews/PnPTab.vue | 10 ++- .../src/views/PipelineViews/ThresholdTab.vue | 2 +- .../src/main/java/org/photonvision/Main.java | 3 +- .../common/configuration/ConfigManager.java | 10 ++- .../photonvision/server/RequestHandler.java | 20 ++++++ .../java/org/photonvision/server/Server.java | 1 + .../vision/processes/VisionModule.java | 12 ++++ .../VisionModuleChangeSubscriber.java | 2 +- .../common/configuration/ConfigTest.java | 7 +- .../processes/VisionModuleManagerTest.java | 2 + 13 files changed, 105 insertions(+), 36 deletions(-) diff --git a/photon-client/src/assets/FRCtargets.json b/photon-client/src/assets/FRCtargets.json index 55aa10fb6..2aa605e0c 100644 --- a/photon-client/src/assets/FRCtargets.json +++ b/photon-client/src/assets/FRCtargets.json @@ -1,20 +1,52 @@ { - "2020 Hex Goal": [ - [-19.625, 0], - [-9.819867, -17], - [9.819867, -17], - [19.625,0] - ], - "2020 Loading Station": [ - [-3.54,5.5], - [-3.54,-5.5], - [3.54,-5.5], - [3.54,5.5] - ], - "2019 Dual Target": [ - [-7.75, 3], - [-7.75, -3], - [7.75, -3], - [7.75, 3] - ] + "2020 Hex Goal": { + "realWorldCoordinatesArray": [ + { + "x": -0.49847498536109924, + "y": 0.0, + "z": 0.0 + }, + { + "x": -0.24942462146282196, + "y": -0.4318000078201294, + "z": 0.0 + }, + { + "x": 0.24942462146282196, + "y": -0.4318000078201294, + "z": 0.0 + }, + { + "x": 0.49847498536109924, + "y": 0.0, + "z": 0.0 + } + ], + "boxHeight": 0.30479999999999996 + }, + "2019 Dual Target": { + "realWorldCoordinatesArray": [ + { + "x": -0.15077440440654755, + "y": 0.06761480122804642, + "z": 0.0 + }, + { + "x": -0.18575020134449005, + "y": -0.06761480122804642, + "z": 0.0 + }, + { + "x": 0.18575020134449005, + "y": -0.06761480122804642, + "z": 0.0 + }, + { + "x": 0.15077440440654755, + "y": 0.06761480122804642, + "z": 0.0 + } + ], + "boxHeight": 0.1 + } } \ No newline at end of file diff --git a/photon-client/src/components/pipeline/3D/MiniMap.vue b/photon-client/src/components/pipeline/3D/MiniMap.vue index c513f2ca9..1db1e6ead 100644 --- a/photon-client/src/components/pipeline/3D/MiniMap.vue +++ b/photon-client/src/components/pipeline/3D/MiniMap.vue @@ -94,7 +94,7 @@ // move the rotation point to the center of the rect this.ctx.translate(y + this.targetWidth / 2, x + this.targetHeight / 2); // wpi lib makes x forward and back and y left to right // rotate the rect - this.ctx.rotate(target.rotation.radians * -1); + this.ctx.rotate(target.rot * -1 * Math.PI / 180.0); // draw the rect on the transformed context // Note: after transforming [0,0] is visually [x,y] diff --git a/photon-client/src/store/index.js b/photon-client/src/store/index.js index ec43448d3..935919f46 100644 --- a/photon-client/src/store/index.js +++ b/photon-client/src/store/index.js @@ -93,7 +93,7 @@ export default new Vuex.Store({ skew: 0, area: 0, // 3D only - pose: {x: 0, y: 0, rotation: 0}, + pose: {x: 0, y: 0, rot: 0}, }] }, settings: { diff --git a/photon-client/src/views/PipelineViews/PnPTab.vue b/photon-client/src/views/PipelineViews/PnPTab.vue index 9c41e3060..d8ef5e38c 100644 --- a/photon-client/src/views/PipelineViews/PnPTab.vue +++ b/photon-client/src/views/PipelineViews/PnPTab.vue @@ -66,7 +66,10 @@ color: "Success", text: "" }, - snack: false + snack: false, + selectedModel: { + isCustom: false + } } }, computed: { @@ -164,7 +167,10 @@ this.uploadModel(this.selectedModel, true); }, uploadModel(model, premade = false) { - this.axios.post("http://" + this.$address + "/api/vision/pnpModel", model).then(() => { + this.axios.post("http://" + this.$address + "/api/vision/pnpModel", { + ['targetModel']: model, + ['index']: this.$store.getters.currentCameraIndex + }).then(() => { this.snackbar = { color: "success", text: premade ? "Target model changed successfully" : "Custom target model uploaded and selected successfully" diff --git a/photon-client/src/views/PipelineViews/ThresholdTab.vue b/photon-client/src/views/PipelineViews/ThresholdTab.vue index d04b4e766..cf78bb71a 100644 --- a/photon-client/src/views/PipelineViews/ThresholdTab.vue +++ b/photon-client/src/views/PipelineViews/ThresholdTab.vue @@ -195,7 +195,6 @@ 'hsvHue': s.hsvHue, 'hsvSaturation': s.hsvSaturation, 'hsvValue': s.hsvValue, - 'outputShowThresholded': this.showThresholdState, 'cameraIndex': this.$store.state.currentCameraIndex } }); @@ -208,6 +207,7 @@ case 0: this.currentFunction = undefined; this.$store.state.colorPicking = false; + this.handlePipelineUpdate("outputShouldDraw", true); return; case 1: this.currentFunction = this.colorPicker.eyeDrop; diff --git a/photon-server/src/main/java/org/photonvision/Main.java b/photon-server/src/main/java/org/photonvision/Main.java index 89a33b85a..a13723780 100644 --- a/photon-server/src/main/java/org/photonvision/Main.java +++ b/photon-server/src/main/java/org/photonvision/Main.java @@ -162,12 +162,13 @@ public class Main { try { CameraServerCvJNI.forceLoad(); + TestUtils.loadLibraries(); logger.info("Native libraries loaded."); } catch (Exception e) { logger.error("Failed to load native libraries!", e); } - ConfigManager.getInstance(); // init config manager + ConfigManager.getInstance().load(); // init config manager NetworkManager.getInstance().initialize(false); NetworkTablesManager.getInstance() diff --git a/photon-server/src/main/java/org/photonvision/common/configuration/ConfigManager.java b/photon-server/src/main/java/org/photonvision/common/configuration/ConfigManager.java index d700efef4..83ab89651 100644 --- a/photon-server/src/main/java/org/photonvision/common/configuration/ConfigManager.java +++ b/photon-server/src/main/java/org/photonvision/common/configuration/ConfigManager.java @@ -87,11 +87,9 @@ public class ConfigManager { this.camerasFolder = new File(Path.of(configDirectoryFile.toString(), "cameras").toUri()); TimedTaskManager.getInstance().addTask("ConfigManager", this::checkSaveAndWrite, 1000); - - load(); } - private void load() { + public void load() { logger.info("Loading settings..."); if (!configDirectoryFile.exists()) { if (configDirectoryFile.mkdirs()) { @@ -163,6 +161,9 @@ public class ConfigManager { public void saveToDisk() { logger.info("Saving settings..."); + // Delete old configs + FileUtils.deleteDirectory(camerasFolder.toPath()); + try { JacksonUtils.serialize(hardwareConfigFile.toPath(), config.getHardwareConfig()); } catch (IOException e) { @@ -174,9 +175,6 @@ public class ConfigManager { logger.error("Could not save network config!", e); } - // Delete old configs - FileUtils.deleteDirectory(camerasFolder.toPath()); - // save all of our cameras var cameraConfigMap = config.getCameraConfigurations(); for (var subdirName : cameraConfigMap.keySet()) { 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 6157d1bdd..c00ea3c24 100644 --- a/photon-server/src/main/java/org/photonvision/server/RequestHandler.java +++ b/photon-server/src/main/java/org/photonvision/server/RequestHandler.java @@ -36,6 +36,7 @@ import org.photonvision.common.logging.LogGroup; import org.photonvision.common.logging.Logger; import org.photonvision.common.networking.NetworkManager; import org.photonvision.vision.processes.VisionModuleManager; +import org.photonvision.vision.target.TargetModel; public class RequestHandler { private static final Logger logger = new Logger(RequestHandler.class, LogGroup.WebServer); @@ -149,4 +150,23 @@ public class RequestHandler { ctx.status(200); System.exit(0); } + + public static void uploadPnpModel(Context ctx) { + UITargetData data; + try { + data = kObjectMapper.readValue(ctx.body(), UITargetData.class); + } catch (JsonProcessingException e) { + e.printStackTrace(); + ctx.status(500); + return; + } + + VisionModuleManager.getInstance().getModule(data.index).setTargetModel(data.targetModel); + ctx.status(200); + } + + public static class UITargetData { + public int index; + public TargetModel targetModel; + } } 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 d6b3bcbab..76476a7da 100644 --- a/photon-server/src/main/java/org/photonvision/server/Server.java +++ b/photon-server/src/main/java/org/photonvision/server/Server.java @@ -79,6 +79,7 @@ public class Server { app.post("/api/settings/endCalibration", RequestHandler::onCalibrationEnd); app.post("/api/restartDevice", RequestHandler::restartDevice); app.post("api/restartProgram", RequestHandler::restartProgram); + app.post("api/vision/pnpModel", RequestHandler::uploadPnpModel); app.start(port); } diff --git a/photon-server/src/main/java/org/photonvision/vision/processes/VisionModule.java b/photon-server/src/main/java/org/photonvision/vision/processes/VisionModule.java index 8fb99a0d5..61f5028a0 100644 --- a/photon-server/src/main/java/org/photonvision/vision/processes/VisionModule.java +++ b/photon-server/src/main/java/org/photonvision/vision/processes/VisionModule.java @@ -38,8 +38,10 @@ import org.photonvision.vision.camera.CameraQuirk; import org.photonvision.vision.camera.QuirkyCamera; import org.photonvision.vision.camera.USBCameraSource; import org.photonvision.vision.frame.consumer.MJPGFrameConsumer; +import org.photonvision.vision.pipeline.ReflectivePipelineSettings; import org.photonvision.vision.pipeline.UICalibrationData; import org.photonvision.vision.pipeline.result.CVPipelineResult; +import org.photonvision.vision.target.TargetModel; /** * This is the God Class @@ -345,4 +347,14 @@ public class VisionModule { lastFrameConsumeMillis = System.currentTimeMillis(); } } + + public void setTargetModel(TargetModel targetModel) { + var settings = pipelineManager.getCurrentUserPipeline().getSettings(); + if (settings instanceof ReflectivePipelineSettings) { + ((ReflectivePipelineSettings) settings).targetModel = targetModel; + saveAndBroadcastAll(); + } else { + logger.error("Cannot set target model of non-reflective pipe! Ignoring..."); + } + } } diff --git a/photon-server/src/main/java/org/photonvision/vision/processes/VisionModuleChangeSubscriber.java b/photon-server/src/main/java/org/photonvision/vision/processes/VisionModuleChangeSubscriber.java index 0bb56d440..81770e587 100644 --- a/photon-server/src/main/java/org/photonvision/vision/processes/VisionModuleChangeSubscriber.java +++ b/photon-server/src/main/java/org/photonvision/vision/processes/VisionModuleChangeSubscriber.java @@ -169,7 +169,7 @@ public class VisionModuleChangeSubscriber extends DataChangeSubscriber { var actual = new IntegerCouple(orig.get(0), orig.get(1)); propField.set(currentSettings, actual); } else if (propType.equals(Double.TYPE)) { - propField.setDouble(currentSettings, (Double) newPropValue); + propField.setDouble(currentSettings, ((Number) newPropValue).doubleValue()); } else if (propType.equals(Integer.TYPE)) { propField.setInt(currentSettings, (Integer) newPropValue); } else if (propType.equals(Boolean.TYPE)) { diff --git a/photon-server/src/test/java/org/photonvision/common/configuration/ConfigTest.java b/photon-server/src/test/java/org/photonvision/common/configuration/ConfigTest.java index e16f12946..0ba5f1607 100644 --- a/photon-server/src/test/java/org/photonvision/common/configuration/ConfigTest.java +++ b/photon-server/src/test/java/org/photonvision/common/configuration/ConfigTest.java @@ -34,10 +34,6 @@ import org.photonvision.vision.target.TargetModel; public class ConfigTest { - static { - TestUtils.loadLibraries(); - } - private static ConfigManager configMgr; private static final CameraConfiguration cameraConfig = new CameraConfiguration("TestCamera", "/dev/video420"); @@ -48,6 +44,7 @@ public class ConfigTest { public static void init() { TestUtils.loadLibraries(); configMgr = new ConfigManager(Path.of("testconfigdir")); + configMgr.load(); Logger.setLevel(LogGroup.General, LogLevel.TRACE); REFLECTIVE_PIPELINE_SETTINGS = new ReflectivePipelineSettings(); @@ -65,7 +62,7 @@ public class ConfigTest { @Test @Order(1) - public void serializeConfig() throws IOException { + public void serializeConfig() { TestUtils.loadLibraries(); Logger.setLevel(LogGroup.General, LogLevel.TRACE); diff --git a/photon-server/src/test/java/org/photonvision/vision/processes/VisionModuleManagerTest.java b/photon-server/src/test/java/org/photonvision/vision/processes/VisionModuleManagerTest.java index 98a6ea7b8..07225dc05 100644 --- a/photon-server/src/test/java/org/photonvision/vision/processes/VisionModuleManagerTest.java +++ b/photon-server/src/test/java/org/photonvision/vision/processes/VisionModuleManagerTest.java @@ -23,6 +23,7 @@ import java.util.HashMap; import java.util.List; import org.junit.jupiter.api.*; import org.photonvision.common.configuration.CameraConfiguration; +import org.photonvision.common.configuration.ConfigManager; import org.photonvision.common.dataflow.CVPipelineResultConsumer; import org.photonvision.common.util.TestUtils; import org.photonvision.vision.frame.FrameProvider; @@ -103,6 +104,7 @@ public class VisionModuleManagerTest { @Test public void setupManager() { + ConfigManager.getInstance().load(); var sources = new HashMap>(); sources.put( new TestSource(