diff --git a/photon-core/src/main/java/org/photonvision/vision/processes/PipelineManager.java b/photon-core/src/main/java/org/photonvision/vision/processes/PipelineManager.java index 27bce5e55..81ea98153 100644 --- a/photon-core/src/main/java/org/photonvision/vision/processes/PipelineManager.java +++ b/photon-core/src/main/java/org/photonvision/vision/processes/PipelineManager.java @@ -17,6 +17,7 @@ package org.photonvision.vision.processes; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; @@ -465,6 +466,17 @@ public class PipelineManager { } } + private static List getAllFields(Class base) { + List ret = new ArrayList<>(); + ret.addAll(List.of(base.getDeclaredFields())); + var superclazz = base.getSuperclass(); + if (superclazz != null) { + ret.addAll(getAllFields(superclazz)); + } + + return ret; + } + public void changePipelineType(int newType) { // Find the PipelineType proposed // To do this we look at all the PipelineType entries and look for one with @@ -490,21 +502,38 @@ public class PipelineManager { return; } - // Our new settings will be totally nuked, but that's ok - // We *could* set things in common between the two, if we want - // But they're different enough it shouldn't be an issue - var name = getCurrentPipelineSettings().pipelineNickname; - var newSettings = createSettingsForType(type, name); - var idx = currentPipelineIndex; if (idx < 0) { logger.error("Cannot replace non-user pipeline!"); return; } + // The settings we used to have + var oldSettings = userPipelineSettings.get(idx); + + var name = getCurrentPipelineSettings().pipelineNickname; + // Dummy settings to copy common fileds over + var newSettings = createSettingsForType(type, name); + + // Copy all fields from AdvancedPipelineSettings/its superclasses from old to new + try { + for (Field field : getAllFields(AdvancedPipelineSettings.class)) { + Object value = field.get(oldSettings); + logger.debug("setting " + field.getName() + " to " + value); + field.set(newSettings, value); + } + } catch (Exception e) { + logger.error("Couldn't copy old settings", e); + } + logger.info("Adding new pipe of type " + type + " at idx " + idx); + + // type gets overritten by reflction hackery above newSettings.pipelineIndex = idx; + newSettings.pipelineType = type; + userPipelineSettings.set(idx, newSettings); + setPipelineInternal(idx); reassignIndexes(); recreateUserPipeline(); diff --git a/photon-core/src/test/java/org/photonvision/vision/processes/PipelineManagerTest.java b/photon-core/src/test/java/org/photonvision/vision/processes/PipelineManagerTest.java index 1219515cd..b90de65ae 100644 --- a/photon-core/src/test/java/org/photonvision/vision/processes/PipelineManagerTest.java +++ b/photon-core/src/test/java/org/photonvision/vision/processes/PipelineManagerTest.java @@ -20,15 +20,21 @@ package org.photonvision.vision.processes; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.photonvision.common.configuration.ConfigManager; import org.photonvision.common.util.TestUtils; import org.photonvision.vision.pipeline.DriverModePipelineSettings; import org.photonvision.vision.pipeline.PipelineType; public class PipelineManagerTest { + @BeforeAll + public static void init() { + TestUtils.loadLibraries(); + } + @Test public void testUniqueName() { - TestUtils.loadLibraries(); PipelineManager manager = new PipelineManager(new DriverModePipelineSettings(), List.of(), -1); manager.addPipeline(PipelineType.Reflective, "Another"); @@ -58,4 +64,18 @@ public class PipelineManagerTest { } Assertions.assertEquals(expected, nicks); } + + @Test + public void testChangeType() { + // hack since we try to publish to datachangeservice + ConfigManager.getInstance().load(); + + PipelineManager manager = new PipelineManager(new DriverModePipelineSettings(), List.of(), -1); + // add a reflective pipeline + manager.addPipeline(PipelineType.Reflective, "Another"); + manager.setIndex(0); + manager.getCurrentPipeline(); + // and change + manager.changePipelineType(PipelineType.Aruco.baseIndex); + } }