From c5a169401274e3802cb9f920b23421a13b2f6919 Mon Sep 17 00:00:00 2001 From: Banks T Date: Thu, 16 Jan 2020 00:21:00 -0500 Subject: [PATCH] Add NetworkTablesManager (#48) * Add NetworkTablesManager, various cleanups * Add auto-restart when team number changes. --- .../main/java/com/chameleonvision/Main.java | 32 +-------- .../networktables/NetworkTablesManager.java | 69 +++++++++++++++++++ .../chameleonvision/vision/VisionManager.java | 4 +- .../chameleonvision/vision/VisionProcess.java | 43 ++++++------ .../chameleonvision/web/RequestHandler.java | 8 ++- 5 files changed, 102 insertions(+), 54 deletions(-) create mode 100644 chameleon-server/src/main/java/com/chameleonvision/networktables/NetworkTablesManager.java diff --git a/chameleon-server/src/main/java/com/chameleonvision/Main.java b/chameleon-server/src/main/java/com/chameleonvision/Main.java index d47027bf7..7c97b9fe9 100644 --- a/chameleon-server/src/main/java/com/chameleonvision/Main.java +++ b/chameleon-server/src/main/java/com/chameleonvision/Main.java @@ -2,20 +2,17 @@ package com.chameleonvision; import com.chameleonvision.config.ConfigManager; import com.chameleonvision.network.NetworkManager; +import com.chameleonvision.networktables.NetworkTablesManager; import com.chameleonvision.scripting.ScriptEventType; import com.chameleonvision.scripting.ScriptManager; import com.chameleonvision.util.Platform; -import com.chameleonvision.util.ShellExec; import com.chameleonvision.util.Utilities; import com.chameleonvision.vision.VisionManager; import com.chameleonvision.web.Server; import edu.wpi.cscore.CameraServerCvJNI; import edu.wpi.cscore.CameraServerJNI; -import edu.wpi.first.networktables.LogMessage; -import edu.wpi.first.networktables.NetworkTableInstance; import java.io.IOException; -import java.util.function.Consumer; import static com.chameleonvision.util.Platform.CurrentPlatform; @@ -37,21 +34,6 @@ public class Main { public static boolean testMode = false; public static int uiPort = DEFAULT_PORT; - private static class NTLogger implements Consumer { - - private boolean hasReportedConnectionFailure = false; - - @Override - public void accept(LogMessage logMessage) { - if (!hasReportedConnectionFailure && logMessage.message.contains("timed out")) { - System.err.println("NT Connection has failed!"); - hasReportedConnectionFailure = true; - } else if (logMessage.message.contains("connected")) { - ScriptManager.queueEvent(ScriptEventType.kNTConnected); - } - } - } - private static void handleArgs(String[] args) { for (int i = 0; i < args.length; i++) { var key = args[i].toLowerCase(); @@ -165,20 +147,12 @@ public class Main { System.out.println("Scripts not yet supported on Windows. ScriptEvents will be ignored."); } - NetworkManager.initialize(manageNetwork); if (ntServerMode) { - System.out.println("Starting NT Server"); - NetworkTableInstance.getDefault().startServer(); + NetworkTablesManager.setServerMode(); } else { - NetworkTableInstance.getDefault().addLogger(new NTLogger(), 0, 255); // to hide error messages - if (ntClientModeServer != null) { - NetworkTableInstance.getDefault().startClient(ntClientModeServer); - } else { - NetworkTableInstance.getDefault().startClientTeam(ConfigManager.settings.teamNumber); - } -// NetworkTableInstance.getDefault().startClient("localhost"); + NetworkTablesManager.setClientMode(ntClientModeServer); } ScriptManager.queueEvent(ScriptEventType.kProgramInit); diff --git a/chameleon-server/src/main/java/com/chameleonvision/networktables/NetworkTablesManager.java b/chameleon-server/src/main/java/com/chameleonvision/networktables/NetworkTablesManager.java new file mode 100644 index 000000000..de020466c --- /dev/null +++ b/chameleon-server/src/main/java/com/chameleonvision/networktables/NetworkTablesManager.java @@ -0,0 +1,69 @@ +package com.chameleonvision.networktables; + +import com.chameleonvision.config.ConfigManager; +import com.chameleonvision.scripting.ScriptEventType; +import com.chameleonvision.scripting.ScriptManager; +import edu.wpi.first.networktables.LogMessage; +import edu.wpi.first.networktables.NetworkTable; +import edu.wpi.first.networktables.NetworkTableInstance; + +import java.util.function.Consumer; + +public class NetworkTablesManager { + + private NetworkTablesManager() {} + + private static final NetworkTableInstance NTInst = NetworkTableInstance.getDefault(); + + public static final String kRootTableName = "/chameleon-vision"; + public static final NetworkTable kRootTable = NetworkTableInstance.getDefault().getTable(kRootTableName); + + public static boolean isServer = false; + + private static int getTeamNumber() { + return ConfigManager.settings.teamNumber; + } + + private static class NTLogger implements Consumer { + + private boolean hasReportedConnectionFailure = false; + + @Override + public void accept(LogMessage logMessage) { + if (!hasReportedConnectionFailure && logMessage.message.contains("timed out")) { + System.err.println("NT Connection has failed! Will retry in background."); + hasReportedConnectionFailure = true; + } else if (logMessage.message.contains("connected")) { + System.out.println("NT Connected!"); + hasReportedConnectionFailure = false; + ScriptManager.queueEvent(ScriptEventType.kNTConnected); + } + } + } + + static { + NetworkTableInstance.getDefault().addLogger(new NTLogger(), 0, 255); // to hide error messages + } + + public static void setClientMode(String host) { + isServer = false; + System.out.println("Starting NT Client"); + NTInst.stopServer(); + if (host != null) { + NTInst.startClient(host); + } else { + NTInst.startClientTeam(getTeamNumber()); + } + } + + public static void setTeamClientMode() { + setClientMode(null); + } + + public static void setServerMode() { + isServer = true; + System.out.println("Starting NT Server"); + NTInst.stopClient(); + NTInst.startServer(); + } +} diff --git a/chameleon-server/src/main/java/com/chameleonvision/vision/VisionManager.java b/chameleon-server/src/main/java/com/chameleonvision/vision/VisionManager.java index 17831d1ad..fdf464a13 100644 --- a/chameleon-server/src/main/java/com/chameleonvision/vision/VisionManager.java +++ b/chameleon-server/src/main/java/com/chameleonvision/vision/VisionManager.java @@ -15,9 +15,9 @@ import org.opencv.videoio.VideoCapture; import java.util.*; import java.util.stream.Collectors; +@SuppressWarnings("rawtypes") public class VisionManager { - private VisionManager() { - } + private VisionManager() {} private static final LinkedHashMap usbCameraInfosByCameraName = new LinkedHashMap<>(); private static final LinkedList loadedCameraConfigs = new LinkedList<>(); diff --git a/chameleon-server/src/main/java/com/chameleonvision/vision/VisionProcess.java b/chameleon-server/src/main/java/com/chameleonvision/vision/VisionProcess.java index 5535eae1d..2dbeabd10 100644 --- a/chameleon-server/src/main/java/com/chameleonvision/vision/VisionProcess.java +++ b/chameleon-server/src/main/java/com/chameleonvision/vision/VisionProcess.java @@ -4,6 +4,7 @@ import com.chameleonvision.Debug; import com.chameleonvision.config.CameraCalibrationConfig; import com.chameleonvision.config.CameraConfig; import com.chameleonvision.config.ConfigManager; +import com.chameleonvision.networktables.NetworkTablesManager; import com.chameleonvision.scripting.ScriptEventType; import com.chameleonvision.scripting.ScriptManager; import com.chameleonvision.config.FullCameraConfiguration; @@ -33,6 +34,7 @@ import java.util.concurrent.LinkedBlockingDeque; import java.util.stream.Collectors; +@SuppressWarnings("rawtypes") public class VisionProcess { private final USBCameraCapture cameraCapture; @@ -117,26 +119,26 @@ public class VisionProcess { public void setCameraNickname(String newName) { getCamera().getProperties().setNickname(newName); - var newTable = NetworkTableInstance.getDefault().getTable("/chameleon-vision/" + newName); - resetNT(newTable); + NetworkTable camTable = NetworkTablesManager.kRootTable.getSubTable(newName); + resetNT(camTable); } - private void initNT(NetworkTable newTable) { - tableInstance = newTable.getInstance(); - ntPipelineEntry = newTable.getEntry("pipeline"); - ntDriverModeEntry = newTable.getEntry("driverMode"); - ntPitchEntry = newTable.getEntry("targetPitch"); - ntYawEntry = newTable.getEntry("targetYaw"); - ntAreaEntry = newTable.getEntry("targetArea"); - ntLatencyEntry = newTable.getEntry("latency"); - ntValidEntry = newTable.getEntry("isValid"); - ntAuxListEntry = newTable.getEntry("auxTargets"); - ntPoseEntry = newTable.getEntry("targetPose"); - ntFittedHeightEntry = newTable.getEntry("targetFittedHeight"); - ntFittedWidthEntry = newTable.getEntry("targetFittedWidth"); - ntBoundingHeightEntry = newTable.getEntry("targetBoundingHeight"); - ntBoundingWidthEntry = newTable.getEntry("targetBoundingWidth"); - ntTargetRotation = newTable.getEntry("targetRotation"); + private void initNT(NetworkTable camTable) { + tableInstance = camTable.getInstance(); + ntPipelineEntry = camTable.getEntry("pipeline"); + ntDriverModeEntry = camTable.getEntry("driverMode"); + ntPitchEntry = camTable.getEntry("targetPitch"); + ntYawEntry = camTable.getEntry("targetYaw"); + ntAreaEntry = camTable.getEntry("targetArea"); + ntLatencyEntry = camTable.getEntry("latency"); + ntValidEntry = camTable.getEntry("isValid"); + ntAuxListEntry = camTable.getEntry("auxTargets"); + ntPoseEntry = camTable.getEntry("targetPose"); + ntFittedHeightEntry = camTable.getEntry("targetFittedHeight"); + ntFittedWidthEntry = camTable.getEntry("targetFittedWidth"); + ntBoundingHeightEntry = camTable.getEntry("targetBoundingHeight"); + ntBoundingWidthEntry = camTable.getEntry("targetBoundingWidth"); + ntTargetRotation = camTable.getEntry("targetRotation"); ntDriveModeListenerID = ntDriverModeEntry.addListener(this::setDriverMode, EntryListenerFlags.kUpdate); ntPipelineListenerID = ntPipelineEntry.addListener(this::setPipeline, EntryListenerFlags.kUpdate); ntDriverModeEntry.setBoolean(false); @@ -169,7 +171,6 @@ public class VisionProcess { } public void setDriverModeEntry(boolean isDriverMode) { - // if it's null, we haven't even started the program yet, so just return // otherwise, set it. if (ntDriverModeEntry != null) { @@ -188,7 +189,7 @@ public class VisionProcess { HashMap WebSend = new HashMap<>(); HashMap point = new HashMap<>(); HashMap pointMap = new HashMap<>(); - ArrayList webTargets = new ArrayList(); + ArrayList webTargets = new ArrayList<>(); List center = new ArrayList<>(); @@ -390,7 +391,6 @@ public class VisionProcess { temp /= 7.0; return temp; } - } private class CameraStreamerRunnable extends LoopingRunnable { @@ -408,7 +408,6 @@ public class VisionProcess { protected void process() { if (!streamFrameQueue.isEmpty()) { try { - bufferMat = streamFrameQueue.take(); try { diff --git a/chameleon-server/src/main/java/com/chameleonvision/web/RequestHandler.java b/chameleon-server/src/main/java/com/chameleonvision/web/RequestHandler.java index 64c926bcb..29dc62484 100644 --- a/chameleon-server/src/main/java/com/chameleonvision/web/RequestHandler.java +++ b/chameleon-server/src/main/java/com/chameleonvision/web/RequestHandler.java @@ -3,6 +3,7 @@ package com.chameleonvision.web; import com.chameleonvision.Exceptions.DuplicatedKeyException; import com.chameleonvision.config.ConfigManager; import com.chameleonvision.network.NetworkIPMode; +import com.chameleonvision.networktables.NetworkTablesManager; import com.chameleonvision.vision.VisionManager; import com.chameleonvision.vision.VisionProcess; import com.chameleonvision.vision.camera.USBCameraCapture; @@ -18,6 +19,7 @@ import edu.wpi.cscore.VideoMode; import edu.wpi.first.wpilibj.geometry.Rotation2d; import io.javalin.http.Context; import io.javalin.http.Handler; +import org.apache.commons.math3.ml.neuralnet.Network; import org.opencv.core.Point; import org.opencv.core.Point3; @@ -37,7 +39,11 @@ public class RequestHandler { Map map = objectMapper.readValue(ctx.body(), Map.class); // TODO: change to function, to restart NetworkTables - ConfigManager.settings.teamNumber = (int) map.get("teamNumber"); + int newTeamNumber = (int) map.get("teamNumber"); + if (newTeamNumber != ConfigManager.settings.teamNumber && !NetworkTablesManager.isServer) { + NetworkTablesManager.setTeamClientMode(); + } + ConfigManager.settings.teamNumber = newTeamNumber; ConfigManager.settings.connectionType = NetworkIPMode.values()[(int) map.get("connectionType")]; ConfigManager.settings.ip = (String) map.get("ip");