Add PipelineManager

This commit is contained in:
Banks Troutman
2019-11-29 23:13:57 -05:00
parent 1674feae73
commit d01e70b1ec
9 changed files with 237 additions and 125 deletions

View File

@@ -67,7 +67,7 @@ public class CameraConfig {
pipelineConfig.save(pipelines);
}
void saveDriverMode(CVPipelineSettings driverMode) {
public void saveDriverMode(CVPipelineSettings driverMode) {
try {
JacksonHelper.serializer(getDriverModePath(), driverMode);
} catch (IOException e) {

View File

@@ -24,6 +24,7 @@ public class VisionManager {
private static final LinkedList<FullCameraConfiguration> loadedCameraConfigs = new LinkedList<>();
private static final LinkedList<VisionProcessManageable> visionProcesses = new LinkedList<>();
@SuppressWarnings("WeakerAccess")
private static class VisionProcessManageable {
public final int index;
public final String name;
@@ -85,7 +86,7 @@ public class VisionManager {
CameraCapture camera = new USBCameraCapture(cameraJsonConfig);
VisionProcess process = new VisionProcess(camera, cameraJsonConfig.name, config.pipelines);
process.setDriverModeSettings(config.drivermode);
process.pipelineManager.driverModePipeline.settings = config.drivermode;
visionProcesses.add(new VisionProcessManageable(i, cameraJsonConfig.name, process));
}
currentUIVisionProcess = getVisionProcessByIndex(0);
@@ -101,16 +102,11 @@ public class VisionManager {
return currentUIVisionProcess;
}
private static CameraConfig getCameraConfig(VisionProcess process) {
public static CameraConfig getCameraConfig(VisionProcess process) {
String cameraName = process.getCamera().getProperties().name;
return Objects.requireNonNull(loadedCameraConfigs.stream().filter(x -> x.cameraConfig.name.equals(cameraName)).findFirst().orElse(null)).fileConfig;
}
public static void addPipelineToCamera(CVPipelineSettings newPipeline, VisionProcess process) {
getCameraConfig(process).pipelineConfig.save(newPipeline);
process.addPipeline(newPipeline);
}
public static void setCurrentProcessByIndex(int processIndex) {
if (processIndex > visionProcesses.size() - 1) {
return;
@@ -135,7 +131,7 @@ public class VisionManager {
}
public static List<String> getCurrentCameraPipelineNicknames() {
return currentUIVisionProcess.getPipelines().stream().map(cvPipeline -> cvPipeline.settings.nickname).collect(Collectors.toList());
return currentUIVisionProcess.pipelineManager.pipelines.stream().map(cvPipeline -> cvPipeline.settings.nickname).collect(Collectors.toList());
}
@@ -143,7 +139,7 @@ public class VisionManager {
visionProcesses.forEach((vpm) -> {
VisionProcess process = vpm.visionProcess;
String cameraName = process.getCamera().getProperties().name;
List<CVPipelineSettings> pipelines = process.getPipelines().stream().map(cvPipeline -> cvPipeline.settings).collect(Collectors.toList());
List<CVPipelineSettings> pipelines = process.pipelineManager.pipelines.stream().map(cvPipeline -> cvPipeline.settings).collect(Collectors.toList());
CVPipelineSettings driverMode = process.getDriverModeSettings();
CameraJsonConfig config = CameraJsonConfig.fromVisionProcess(process);
ConfigManager.saveCameraPipelines(cameraName, pipelines);
@@ -162,16 +158,14 @@ public class VisionManager {
}
public static void saveCurrentCameraPipelines() {
List<CVPipelineSettings> pipelineSettings = currentUIVisionProcess.getPipelines().stream().map(pipeline -> pipeline.settings).collect(Collectors.toList());
ConfigManager.saveCameraPipelines(getCurrentCameraName(), pipelineSettings);
currentUIVisionProcess.pipelineManager.saveAllPipelines();
}
public static void saveCurrentCameraDriverMode() {
CVPipelineSettings driverModeSettings = currentUIVisionProcess.getDriverModeSettings();
ConfigManager.saveCameraDriverMode(getCurrentCameraName(), driverModeSettings);
currentUIVisionProcess.pipelineManager.saveDriverModeConfig();
}
public static List<HashMap> getCameraResolutionList(CameraCapture capture) {
private static List<HashMap> getCameraResolutionList(CameraCapture capture) {
return capture.getProperties().getVideoModes().stream().map(Helpers::VideoModeToHashMap).collect(Collectors.toList());
}

View File

@@ -29,6 +29,7 @@ public class VisionProcess {
private final CameraStreamerRunnable streamRunnable;
private final VisionProcessRunnable visionRunnable;
public final CameraStreamer cameraStreamer;
public final PipelineManager pipelineManager;
private CVPipeline currentPipeline;
private int currentPipelineIndex = 0;
@@ -56,15 +57,7 @@ public class VisionProcess {
VisionProcess(CameraCapture cameraCapture, String name, List<CVPipelineSettings> loadedPipelineSettings) {
this.cameraCapture = cameraCapture;
if (loadedPipelineSettings == null || loadedPipelineSettings.size() == 0) {
pipelines.add(new CVPipeline2d("New Pipeline"));
} else {
for (CVPipelineSettings setting : loadedPipelineSettings) {
addPipeline(setting);
}
setPipeline(0, false);
}
pipelineManager = new PipelineManager(this, loadedPipelineSettings);
// Thread to put frames on the dashboard
this.cameraStreamer = new CameraStreamer(cameraCapture, name);
@@ -80,10 +73,16 @@ public class VisionProcess {
public void start() {
System.out.println("Starting NetworkTables.");
initNT(defaultTable);
System.out.println("Starting vision thread.");
new Thread(visionRunnable).start();
var visionThread = new Thread(visionRunnable);
visionThread.setName(getCamera().getProperties().name + " - Vision Thread");
visionThread.start();
System.out.println("Starting stream thread.");
new Thread(streamRunnable).start();
var streamThread = new Thread(streamRunnable);
streamThread.setName(getCamera().getProperties().name + " - Stream Thread");
streamThread.start();
}
/**
@@ -110,7 +109,7 @@ public class VisionProcess {
ntDriveModeListenerID = ntDriverModeEntry.addListener(this::setDriverMode, EntryListenerFlags.kUpdate);
ntPipelineListenerID = ntPipelineEntry.addListener(this::setPipeline, EntryListenerFlags.kUpdate);
ntDriverModeEntry.setBoolean(false);
ntPipelineEntry.setNumber(0);
ntPipelineEntry.setNumber(pipelineManager.getCurrentPipelineIndex());
}
private void setDriverMode(EntryNotification driverModeEntryNotification) {
@@ -118,11 +117,7 @@ public class VisionProcess {
}
public void setDriverMode(boolean driverMode) {
if (driverMode) {
setPipelineInternal(driverModePipeline);
} else {
setPipeline(currentPipelineIndex, true);
}
pipelineManager.setDriverMode(driverMode);
}
/**
@@ -133,38 +128,12 @@ public class VisionProcess {
var wantedPipelineIndex = (int) notification.value.getDouble();
if (wantedPipelineIndex >= pipelines.size()) {
ntPipelineEntry.setNumber(currentPipelineIndex);
ntPipelineEntry.setNumber(pipelineManager.getCurrentPipelineIndex());
} else {
currentPipelineIndex = wantedPipelineIndex;
setPipeline(wantedPipelineIndex, true);
pipelineManager.setCurrentPipeline(wantedPipelineIndex);
}
}
public void setPipeline(int pipelineIndex, boolean updateUI) {
CVPipeline newPipeline = pipelines.get(pipelineIndex);
if (newPipeline != null) {
setPipelineInternal(newPipeline);
currentPipelineIndex = pipelineIndex;
// update the configManager
if(ConfigManager.settings.currentCamera.equals(cameraCapture.getProperties().name)) {
ConfigManager.settings.currentPipeline = pipelineIndex;
if (updateUI) {
HashMap<String, Object> pipeChange = new HashMap<>();
pipeChange.put("currentPipeline", pipelineIndex);
SocketHandler.broadcastMessage(pipeChange);
SocketHandler.sendFullSettings();
}
}
}
}
private void setPipelineInternal(CVPipeline pipeline) {
currentPipeline = pipeline;
currentPipeline.initPipeline(cameraCapture);
}
private void updateUI(CVPipelineResult data) {
if(cameraCapture.getProperties().name.equals(ConfigManager.settings.currentCamera)) {
HashMap<String, Object> WebSend = new HashMap<>();
@@ -243,56 +212,16 @@ public class VisionProcess {
return cameraCapture.getProperties().videoModes;
}
public List<CVPipeline> getPipelines() {
return pipelines;
}
public CVPipeline getCurrentPipeline() {
return currentPipeline;
}
public int getCurrentPipelineIndex() {
return currentPipelineIndex;
}
public void addBlankPipeline() {
// TODO: (2.1) add to UI option between 2d and 3d pipeline
var newPipeline = new CVPipeline2d();
// if (pipelines.stream().filter(x -> x.settings.nickname.equals(newPipeline.settings.nickname));
addPipeline(new CVPipeline2d());
}
public void addPipeline(CVPipeline pipeline) {
pipelines.add(pipeline);
}
public void addPipeline(CVPipelineSettings settings) {
if (settings instanceof CVPipeline2dSettings) {
addPipeline(new CVPipeline2d((CVPipeline2dSettings) settings));
}
}
public void deletePipeline(int index) {
pipelines.remove(index);
}
public CameraCapture getCamera() {
return cameraCapture;
}
public boolean getDriverMode() {
return (currentPipeline == driverModePipeline);
}
public void setDriverModeSettings(CVPipelineSettings settings) {
driverModePipeline.settings = settings;
pipelineManager.driverModePipeline.settings = settings;
}
public CVPipelineSettings getDriverModeSettings() {
return driverModePipeline.settings;
}
public CVPipeline getPipelineByIndex(int pipelineIndex) {
return pipelines.get(pipelineIndex);
return pipelineManager.driverModePipeline.settings;
}
/**
@@ -313,7 +242,7 @@ public class VisionProcess {
Mat camFrame = camData.getLeft();
if (camFrame.cols() > 0 && camFrame.rows() > 0) {
CVPipelineResult result = currentPipeline.runPipeline(camFrame);
CVPipelineResult result = pipelineManager.getCurrentPipeline().runPipeline(camFrame);
if (result != null) {
result.setTimestamp(camData.getRight());

View File

@@ -27,4 +27,8 @@ public abstract class CVPipeline<R extends CVPipelineResult, S extends CVPipelin
cameraCapture.setBrightness((int) settings.brightness);
}
abstract public R runPipeline(Mat inputMat);
public boolean is3D() {
return (this instanceof CVPipeline3d);
}
}

View File

@@ -13,6 +13,10 @@ public class CVPipeline3d extends CVPipeline<CVPipeline3dResult, CVPipeline3dSet
super(settings);
}
CVPipeline3d() {
super(new CVPipeline3dSettings());
}
@Override
public CVPipeline3dResult runPipeline(Mat inputMat) {
return null;
@@ -25,7 +29,7 @@ public class CVPipeline3d extends CVPipeline<CVPipeline3dResult, CVPipeline3dSet
}
}
public static class Target3d {
public static class Target3d extends CVPipeline2d.Target2d {
// TODO: (2.1) Define 3d-specific target data
}
}

View File

@@ -2,4 +2,6 @@ package com.chameleonvision.vision.pipeline;
public class CVPipeline3dSettings extends CVPipeline2dSettings {
// TODO: (2.1) define 3d-specific pipeline settings
// add 3d-specific property to ensure serializing/deserializing works
public boolean placeholder = false;
}

View File

@@ -5,6 +5,7 @@ import com.chameleonvision.vision.enums.ImageRotationMode;
@SuppressWarnings("ALL")
public class CVPipelineSettings {
public int index = 0;
public ImageFlipMode flipMode = ImageFlipMode.NONE;
public ImageRotationMode rotationMode = ImageRotationMode.DEG_0;
public String nickname = "New Pipeline";

View File

@@ -0,0 +1,181 @@
package com.chameleonvision.vision.pipeline;
import com.chameleonvision.config.CameraConfig;
import com.chameleonvision.config.ConfigManager;
import com.chameleonvision.vision.VisionManager;
import com.chameleonvision.vision.VisionProcess;
import com.chameleonvision.web.SocketHandler;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
@SuppressWarnings("WeakerAccess")
public class PipelineManager {
public final LinkedList<CVPipeline> pipelines = new LinkedList<>();
public final CVPipeline driverModePipeline = new DriverVisionPipeline(new CVPipelineSettings());
private final VisionProcess parentProcess;
private int currentPipelineIndex;
private boolean driverMode;
public PipelineManager(VisionProcess visionProcess, List<CVPipelineSettings> loadedPipelineSettings) {
parentProcess = visionProcess;
if (loadedPipelineSettings == null || loadedPipelineSettings.size() == 0) {
pipelines.add(new CVPipeline2d("New Pipeline"));
} else {
for (CVPipelineSettings setting : loadedPipelineSettings) {
addInternalPipeline(setting);
}
}
setCurrentPipeline(0);
}
private void reassignIndexes() {
pipelines.sort(IndexComparator);
for (int i = 0; i < pipelines.size(); i++) {
pipelines.get(i).settings.index = i;
}
}
private CameraConfig getConfig(VisionProcess process) {
return VisionManager.getCameraConfig(process);
}
private CameraConfig getConfig() {
return getConfig(parentProcess);
}
private void savePipelineConfig(CVPipelineSettings setting) {
getConfig().pipelineConfig.save(setting);
}
private void deletePipelineConfig(CVPipelineSettings setting) {
getConfig().pipelineConfig.delete(setting);
}
private void renamePipelineConfig(CVPipelineSettings setting, String newName) {
getConfig().pipelineConfig.rename(setting, newName);
}
public void saveAllPipelines() {
pipelines.parallelStream().map(pipeline -> pipeline.settings).forEach(this::savePipelineConfig);
}
private void addInternalPipeline(CVPipelineSettings setting) {
if (setting instanceof CVPipeline3dSettings) {
pipelines.add(new CVPipeline3d((CVPipeline3dSettings) setting));
} else if (setting instanceof CVPipeline2dSettings) {
pipelines.add(new CVPipeline2d((CVPipeline2dSettings) setting));
} else {
System.out.println("Non 2D/3D pipelines not supported!");
}
reassignIndexes();
}
public void setDriverMode(boolean driverMode) {
this.driverMode = driverMode;
}
public boolean getDriverMode() {
return driverMode;
}
public int getCurrentPipelineIndex() {
return currentPipelineIndex;
}
public CVPipeline getCurrentPipeline() {
return driverMode ? driverModePipeline : pipelines.get(currentPipelineIndex);
}
public void setCurrentPipeline(int index) {
CVPipeline newPipeline = pipelines.get(index);
if (newPipeline != null) {
currentPipelineIndex = index;
getCurrentPipeline().initPipeline(parentProcess.getCamera());
if(ConfigManager.settings.currentCamera.equals(parentProcess.getCamera().getProperties().name)) {
ConfigManager.settings.currentPipeline = currentPipelineIndex;
HashMap<String, Object> pipeChange = new HashMap<>();
pipeChange.put("currentPipeline", currentPipelineIndex);
SocketHandler.broadcastMessage(pipeChange);
try {
SocketHandler.sendFullSettings();
} catch (Exception e) {
// avoid NullPointerException when run before threads start
}
}
newPipeline.initPipeline(parentProcess.getCamera());
}
}
public void addPipeline(CVPipelineSettings setting) {
addInternalPipeline(setting);
savePipelineConfig(setting);
}
public void addPipeline(CVPipeline pipeline) {
pipelines.add(pipeline);
reassignIndexes();
savePipelineConfig(pipeline.settings);
}
public void addNewPipeline(boolean is3D) {
CVPipeline newPipeline;
if (!is3D) {
newPipeline = new CVPipeline2d();
} else {
newPipeline = new CVPipeline3d();
}
newPipeline.settings.index = pipelines.size();
addPipeline(newPipeline);
}
public CVPipeline getPipeline(int index) {
return pipelines.get(index);
}
public void duplicatePipeline(CVPipelineSettings pipeline) {
duplicatePipeline(pipeline, parentProcess);
}
public void duplicatePipeline(CVPipelineSettings pipeline, VisionProcess destinationProcess) {
pipeline.index = destinationProcess.pipelineManager.pipelines.size();
pipeline.nickname += "(Copy)";
destinationProcess.pipelineManager.addPipeline(pipeline);
}
public void deleteCurrentPipeline() {
deletePipeline(currentPipelineIndex);
}
private void deletePipeline(int index) {
if (index == currentPipelineIndex) {
currentPipelineIndex -= 1;
}
deletePipelineConfig(getPipeline(index).settings);
pipelines.remove(index);
reassignIndexes();
}
public void saveDriverModeConfig() {
getConfig().saveDriverMode(driverModePipeline.settings);
}
private static final Comparator<CVPipeline> IndexComparator = (o1, o2) -> {
int o1Index = o1.settings.index;
int o2Index = o2.settings.index;
if (o1Index == o2Index) {
return 0;
} else if (o1Index < o2Index) {
return -1;
}
return 1;
};
}

View File

@@ -51,7 +51,7 @@ public class SocketHandler {
try {
VisionProcess currentProcess = VisionManager.getCurrentUIVisionProcess();
CameraCapture currentCamera = currentProcess.getCamera();
CVPipeline currentPipeline = currentProcess.getCurrentPipeline();
CVPipeline currentPipeline = currentProcess.pipelineManager.getCurrentPipeline();
switch (entry.getKey()) {
case "driverMode": {
@@ -80,21 +80,22 @@ public class SocketHandler {
int pipelineIndex = (int) pipelineVals.get("pipeline");
int cameraIndex = (int) pipelineVals.get("camera");
ObjectMapper mapper = new ObjectMapper();
CVPipelineSettings origPipeline = currentProcess.getPipelineByIndex(pipelineIndex).settings;
CVPipelineSettings origPipeline = currentProcess.pipelineManager.getPipeline(pipelineIndex).settings;
String val = mapper.writeValueAsString(origPipeline);
CVPipelineSettings newPipeline = mapper.readValue(val, origPipeline.getClass());
// TODO: move to PipelineManager
newPipeline.nickname += "(Copy)";
if (cameraIndex != -1) {
VisionProcess newProcess = VisionManager.getVisionProcessByIndex(cameraIndex);
if (newProcess != null) {
VisionManager.addPipelineToCamera(newPipeline, newProcess);
newProcess.addPipeline(newPipeline);
currentProcess.pipelineManager.duplicatePipeline(newPipeline, newProcess);
} else {
System.err.println("Failed to get new camera for pipeline duplication!");
}
} else {
VisionManager.addPipelineToCamera(newPipeline, currentProcess);
currentProcess.addPipeline(newPipeline);
currentProcess.pipelineManager.duplicatePipeline(newPipeline);
}
VisionManager.saveCurrentCameraPipelines();
@@ -104,17 +105,14 @@ public class SocketHandler {
case "command": {
switch ((String) entry.getValue()) {
case "addNewPipeline":
currentProcess.addBlankPipeline();
// TODO: add to UI selection for new 2d/3d
boolean is3d = false;
currentProcess.pipelineManager.addNewPipeline(is3d);
sendFullSettings();
VisionManager.saveCurrentCameraPipelines();
break;
case "deleteCurrentPipeline":
int currentIndex = currentProcess.getCurrentPipelineIndex();
if (currentIndex == currentProcess.getPipelines().size() - 1) {
currentProcess.setPipeline(currentIndex - 1, false);
}
currentProcess.deletePipeline(currentIndex);
currentProcess.pipelineManager.deleteCurrentPipeline();
sendFullSettings();
VisionManager.saveCurrentCameraPipelines();
break;
@@ -133,7 +131,7 @@ public class SocketHandler {
break;
}
case "currentPipeline": {
currentProcess.setPipeline((Integer) entry.getValue(), true);
currentProcess.pipelineManager.setCurrentPipeline((Integer) entry.getValue());
sendFullSettings();
break;
}
@@ -195,9 +193,9 @@ public class SocketHandler {
for (Field field : cvClass.getFields()) { // iterate over every field in CVPipelineSettings
try {
if (!field.getType().isEnum()) { // if the field is not an enum, get it based on the current pipeline
tmp.put(field.getName(), field.get(VisionManager.getCurrentUIVisionProcess().getCurrentPipeline().settings));
tmp.put(field.getName(), field.get(VisionManager.getCurrentUIVisionProcess().pipelineManager.getCurrentPipeline().settings));
} else {
var ordinal = (Enum) field.get(VisionManager.getCurrentUIVisionProcess().getCurrentPipeline().settings);
var ordinal = (Enum) field.get(VisionManager.getCurrentUIVisionProcess().pipelineManager.getCurrentPipeline().settings);
tmp.put(field.getName(), ordinal.ordinal());
}
} catch (IllegalArgumentException e) {
@@ -231,8 +229,8 @@ public class SocketHandler {
private static HashMap<String, Object> getOrdinalDriver() {
HashMap<String, Object> tmp = new HashMap<>();
VisionProcess currentProcess = VisionManager.getCurrentUIVisionProcess();
CVPipelineSettings driverModeSettings = currentProcess.getDriverModeSettings();
tmp.put("isDriver", currentProcess.getDriverMode());
CVPipelineSettings driverModeSettings = currentProcess.pipelineManager.driverModePipeline.settings;
tmp.put("isDriver", currentProcess.pipelineManager.getDriverMode());
tmp.put("driverBrightness", driverModeSettings.brightness);
tmp.put("driverExposure", driverModeSettings.exposure);
return tmp;
@@ -243,8 +241,7 @@ public class SocketHandler {
Map<String, Object> fullSettings = new HashMap<>();
VisionProcess currentProcess = VisionManager.getCurrentUIVisionProcess();
CameraCapture currentCamera = currentProcess.getCamera();
CVPipeline currentPipeline = currentProcess.getCurrentPipeline();
CVPipeline currentPipeline = currentProcess.pipelineManager.getCurrentPipeline();
try {
fullSettings.put("settings", getOrdinalSettings());
@@ -255,7 +252,7 @@ public class SocketHandler {
fullSettings.put("pipelineList", VisionManager.getCurrentCameraPipelineNicknames());
fullSettings.put("resolutionList", VisionManager.getCurrentCameraResolutionList());
fullSettings.put("port", currentProcess.cameraStreamer.getStreamPort());
fullSettings.put("currentPipelineIndex", VisionManager.getCurrentUIVisionProcess().getCurrentPipelineIndex());
fullSettings.put("currentPipelineIndex", VisionManager.getCurrentUIVisionProcess().pipelineManager.getCurrentPipelineIndex());
fullSettings.put("currentCameraIndex", VisionManager.getCurrentUIVisionProcessIndex());
} catch (IllegalAccessException e) {
System.err.println("No camera found!");