diff --git a/.gitignore b/.gitignore index 9535c83..7d0efa3 100644 --- a/.gitignore +++ b/.gitignore @@ -160,3 +160,5 @@ bin/ # Simulation GUI and other tools window save file *-window.json + +src/main/deploy/config.json \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 4bca61f..4cb2727 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,13 +4,6 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ - { - "type": "java", - "name": "Launch Main", - "request": "launch", - "mainClass": "frc4388.robot.Main", - "projectName": "2022NoWayHome" - }, { "type": "wpilib", "name": "WPILib Desktop Debug", @@ -21,7 +14,8 @@ "type": "wpilib", "name": "WPILib roboRIO Debug", "request": "launch", - "desktop": false + "desktop": false, + "postDebugTask": "downloadDeployDirectory" } ] } diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 6ef8685..12d8f43 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,10 +1,19 @@ { "version": "2.0.0", "tasks": [ - { - "label": "downloadDeployDirectory", - "type": "shell", - "command": "scp -pr lvuser@roboRIO-4388-FRC.local:/home/lvuser/deploy ./deploy" - } + { + "label": "downloadDeployDirectory", + "type": "shell", + "command": "scp -prv lvuser@roboRIO-4388-FRC.local:/home/lvuser/deploy ./src/main/", + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": true + }, + "problemMatcher": [] + } ] } \ No newline at end of file diff --git a/src/main/java/edu/wpi/first/wpilibj/DriverStation.java b/src/main/java/edu/wpi/first/wpilibj/DriverStation.java index d58a61b..876e42d 100644 --- a/src/main/java/edu/wpi/first/wpilibj/DriverStation.java +++ b/src/main/java/edu/wpi/first/wpilibj/DriverStation.java @@ -399,29 +399,46 @@ public class DriverStation { boolean printTrace, StackTraceElement[] stackTrace, int stackTraceFirst) { - String locString; - if (stackTrace.length >= stackTraceFirst + 1) { - locString = stackTrace[stackTraceFirst].toString(); - } else { - locString = ""; - } - StringBuilder traceString = new StringBuilder(); - if (printTrace) { - boolean haveLoc = false; - for (int i = stackTraceFirst; i < stackTrace.length; i++) { - String loc = stackTrace[i].toString(); - traceString.append("\tat ").append(loc).append('\n'); - // get first user function - if (!haveLoc && !loc.startsWith("edu.wpi.first")) { - locString = loc; - haveLoc = true; - } - } - } + // String locString; + // if (stackTrace.length >= stackTraceFirst + 1) { + // locString = stackTrace[stackTraceFirst].toString(); + // } else { + // locString = ""; + // } + // StringBuilder traceString = new StringBuilder(); + // if (printTrace) { + // boolean haveLoc = false; + // for (int i = stackTraceFirst; i < stackTrace.length; i++) { + // String loc = stackTrace[i].toString(); + // traceString.append("\tat ").append(loc).append('\n'); + // // get first user function + // if (!haveLoc && !loc.startsWith("edu.wpi.first")) { + // locString = loc; + // haveLoc = true; + // } + // } + // } // HAL.sendError(isError, code, false, error, locString, traceString.toString(), true); // for (StackTraceElement traceElement : stackTrace) // System.err.println("\tat " + traceElement); - java.util.logging.Logger.getLogger(HAL.class.getName()).log(isError ? java.util.logging.Level.SEVERE : java.util.logging.Level.FINEST, "Warning at {0}: {1}", new Object[] {locString, error.split("\n")[0]}); + java.util.logging.LogRecord logRecord = new java.util.logging.LogRecord(isError ? java.util.logging.Level.SEVERE : java.util.logging.Level.FINER, error.stripTrailing()); + java.util.Optional.ofNullable(stackTrace).filter(s -> s.length >= stackTraceFirst + 1).map(s -> java.util.Arrays.copyOfRange(s, Math.min(Math.max(0, stackTraceFirst), s.length - 1), s.length - 1)).ifPresent(presentStackTrace -> { + logRecord.setSourceMethodName(presentStackTrace[0].getMethodName()); + String throwableMessage; + if (presentStackTrace[0].toString().equals("edu.wpi.first.wpilibj.Tracer.lambda$printEpochs$0(Tracer.java:63)")) { + throwableMessage = "Epochs" + System.lineSeparator() + logRecord.getMessage(); + presentStackTrace = new java.lang.StackTraceElement[0]; + logRecord.setLevel(java.util.logging.Level.FINEST); + logRecord.setMessage("Execution times:"); + } else if (printTrace) { + long lineCount = logRecord.getMessage().lines().count(); + throwableMessage = (lineCount > 1 ? logRecord.getMessage().lines().findFirst().map(s -> s + " + " + lineCount + " more lines...").orElse("") : logRecord.getMessage()).stripLeading(); + } else return; + java.lang.Throwable throwable = new java.lang.Throwable(throwableMessage); + throwable.setStackTrace(presentStackTrace); + logRecord.setThrown(throwable); + }); + java.util.logging.Logger.getLogger(HAL.class.getSimpleName()).log(logRecord); } /** diff --git a/src/main/java/frc4388/robot/Main.java b/src/main/java/frc4388/robot/Main.java index a718f7e..8d25e15 100644 --- a/src/main/java/frc4388/robot/Main.java +++ b/src/main/java/frc4388/robot/Main.java @@ -30,7 +30,7 @@ public final class Main { */ public static void main(String... args) { AnsiLogging.systemInstall(); - DurianPlugins.register(Errors.Plugins.Log.class, e -> Logger.getLogger(e.getStackTrace()[0].getClassName()).log(Level.SEVERE, e, e::getLocalizedMessage)); + DurianPlugins.register(Errors.Plugins.Log.class, e -> Logger.getLogger(e.getStackTrace()[0].getClassName().substring(e.getStackTrace()[0].getClassName().lastIndexOf('.') + 1)).log(Level.SEVERE, e, e::getLocalizedMessage)); RobotBase.startRobot(Robot::new); } } diff --git a/src/main/java/frc4388/robot/Robot.java b/src/main/java/frc4388/robot/Robot.java index 28fc2fe..90394c1 100644 --- a/src/main/java/frc4388/robot/Robot.java +++ b/src/main/java/frc4388/robot/Robot.java @@ -9,7 +9,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.logging.Level; import java.util.logging.Logger; -import java.util.stream.StreamSupport; +import java.util.stream.IntStream; import com.diffplug.common.base.Errors; @@ -19,7 +19,6 @@ import edu.wpi.first.wpilibj.TimedRobot; import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; import edu.wpi.first.wpilibj2.command.Command; import edu.wpi.first.wpilibj2.command.CommandScheduler; -import edu.wpi.first.wpilibj2.command.InstantCommand; import edu.wpi.first.wpilibj2.command.RunCommand; import frc4388.utility.RobotTime; @@ -31,7 +30,7 @@ import frc4388.utility.RobotTime; * project. */ public class Robot extends TimedRobot { - private static final Logger LOGGER = Logger.getLogger(Robot.class.getName()); + private static final Logger LOGGER = Logger.getLogger(Robot.class.getSimpleName()); Command m_autonomousCommand; private RobotTime m_robotTime = RobotTime.getInstance(); @@ -43,22 +42,21 @@ public class Robot extends TimedRobot { */ @Override public void robotInit() { - // if (org.fusesource.jansi.Ansi.isEnabled()) { - LOGGER.log(Level.ALL, "Logging Test 1/8"); - LOGGER.log(Level.SEVERE, "Logging Test 2/8"); - LOGGER.log(Level.WARNING, "Logging Test 3/8"); - LOGGER.log(Level.INFO, "Logging Test 4/8"); - LOGGER.log(Level.CONFIG, "Logging Test 5/8"); - LOGGER.log(Level.FINE, "Logging Test 6/8"); - LOGGER.log(Level.FINER, "Logging Test 7/8"); - LOGGER.log(Level.FINEST, "Logging Test 8/8"); - // } + LOGGER.log(Level.ALL, "Logging Test 1/8"); + LOGGER.log(Level.SEVERE, "Logging Test 2/8"); + LOGGER.log(Level.WARNING, "Logging Test 3/8"); + LOGGER.log(Level.INFO, "Logging Test 4/8"); + LOGGER.log(Level.CONFIG, "Logging Test 5/8"); + LOGGER.log(Level.FINE, "Logging Test 6/8"); + LOGGER.log(Level.FINER, "Logging Test 7/8"); + LOGGER.log(Level.FINEST, "Logging Test 8/8"); + Errors.log().run(() -> { throw new Throwable("Exception Test"); }); // var path = PathPlannerUtil.Path.read(Filesystem.getDeployDirectory().toPath().resolve("pathplanner").resolve("Move Forward.path").toFile()); // LOGGER.finest(path::toString); LOGGER.fine("robotInit()"); - LOGGER.fine("Sssssssssh."); - DriverStation.silenceJoystickConnectionWarning(true); + // LOGGER.fine("Sssssssssh."); + // DriverStation.silenceJoystickConnectionWarning(true); // Instantiate our RobotContainer. This will perform all our button bindings, and put our // autonomous chooser on the dashboard. m_robotContainer = new RobotContainer(); @@ -110,6 +108,7 @@ public class Robot extends TimedRobot { SmartDashboard.putNumber("Odometry X", m_robotContainer.getOdometry().getX()); SmartDashboard.putNumber("Odometry Y", m_robotContainer.getOdometry().getY()); SmartDashboard.putNumber("Odometry Theta", m_robotContainer.getOdometry().getRotation().getDegrees()); + IntStream.range(0, 9999).forEach(Math::cos); } /** diff --git a/src/main/java/frc4388/robot/RobotContainer.java b/src/main/java/frc4388/robot/RobotContainer.java index 2599576..83da3e9 100644 --- a/src/main/java/frc4388/robot/RobotContainer.java +++ b/src/main/java/frc4388/robot/RobotContainer.java @@ -75,7 +75,7 @@ import frc4388.utility.controller.DeadbandedXboxController; * commands, and button mappings) should be declared here. */ public class RobotContainer { - private static final Logger LOGGER = Logger.getLogger(RobotContainer.class.getName()); + private static final Logger LOGGER = Logger.getLogger(RobotContainer.class.getSimpleName()); /* RobotMap */ private final RobotMap m_robotMap = new RobotMap(); @@ -237,7 +237,7 @@ public class RobotContainer { m_robotSwerveDrive::setModuleStates, m_robotSwerveDrive), new InstantCommand(m_robotSwerveDrive::stopModules)).withName("Run Autonomous Path"); } else { - Logger.getLogger(this.getClass().getName()).severe("No auto selected."); + LOGGER.severe("No auto selected."); return new RunCommand(() -> { }).withName("No Autonomous Path"); } diff --git a/src/main/java/frc4388/robot/subsystems/LED.java b/src/main/java/frc4388/robot/subsystems/LED.java index eaab9dd..e46be14 100644 --- a/src/main/java/frc4388/robot/subsystems/LED.java +++ b/src/main/java/frc4388/robot/subsystems/LED.java @@ -27,7 +27,7 @@ public class LED extends SubsystemBase { m_LEDController = LEDController; setPattern(LEDConstants.DEFAULT_PATTERN); updateLED(); - Logger.getLogger(LED.class.getName()).finer("In the Beginning, there was Joe.\nAnd he said, 'Let there be LEDs.'\nAnd it was good."); + Logger.getLogger(LED.class.getSimpleName()).finer("In the Beginning, there was Joe.\nAnd he said, 'Let there be LEDs.'\nAnd it was good."); } @Override diff --git a/src/main/java/frc4388/utility/AnsiLogging.java b/src/main/java/frc4388/utility/AnsiLogging.java index c37a3a6..15930ea 100644 --- a/src/main/java/frc4388/utility/AnsiLogging.java +++ b/src/main/java/frc4388/utility/AnsiLogging.java @@ -9,6 +9,8 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.time.ZoneId; import java.time.ZonedDateTime; +import java.util.Map; +import java.util.Optional; import java.util.logging.ConsoleHandler; import java.util.logging.Formatter; import java.util.logging.Level; @@ -19,10 +21,6 @@ import java.util.logging.Logger; import org.fusesource.jansi.Ansi; import org.fusesource.jansi.Ansi.Attribute; import org.fusesource.jansi.Ansi.Color; - -import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard; -import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; - import org.fusesource.jansi.AnsiConsole; public class AnsiLogging extends ConsoleHandler { @@ -31,67 +29,72 @@ public class AnsiLogging extends ConsoleHandler { // Configures java.util.logging.Logger to output additional colored information. LogManager.getLogManager().updateConfiguration(key -> (o, n) -> { switch (key) { - case ".level": return Level.ALL.getName(); - case "handlers": return AnsiColorConsoleHandler.class.getName(); - default: return n; + case ".level": + return Level.ALL.getName(); + case "handlers": + return AnsiColorConsoleHandler.class.getName(); + default: + return n; } }); // Replaces standard output streams with org.fusesource.jansi.AnsiPrintStreams. AnsiConsole.systemInstall(); // Replaces standard output stream with java.util.logging.Logger. - System.setOut(printStreamLogger(Logger.getGlobal(), Level.ALL)); + System.setOut(printStreamLogger(Logger.getGlobal(), Level.INFO)); // Replaces standard error output stream with java.util.logging.Logger. System.setErr(printStreamLogger(Logger.getGlobal(), Level.SEVERE)); } catch (IOException exception) { exception.printStackTrace(AnsiConsole.sysErr()); } } - + public static class AnsiColorConsoleHandler extends ConsoleHandler { @Override public void publish(LogRecord logRecord) { AnsiConsole.err().print(getFormatter().format(logRecord)); AnsiConsole.err().flush(); } + @Override public Formatter getFormatter() { return formatter; } + private static final Formatter formatter = new Formatter() { + private final ZoneId zoneId = ZoneId.systemDefault(); + private final Map levelColors = Map.of( + Level.OFF.intValue(), "", + Level.SEVERE.intValue(), makeSignatureFormatString(ansi().fgBright(Color.RED)), + Level.WARNING.intValue(), makeSignatureFormatString(ansi().fgBright(Color.YELLOW)), + Level.INFO.intValue(), makeSignatureFormatString(ansi().fg(Color.GREEN)), + Level.CONFIG.intValue(), makeSignatureFormatString(ansi().fgBright(Color.BLUE)), + Level.FINE.intValue(), makeSignatureFormatString(ansi().fg(Color.CYAN)), + Level.FINER.intValue(), makeSignatureFormatString(ansi().fg(Color.MAGENTA)), + Level.FINEST.intValue(), makeSignatureFormatString(ansi().fgBright(Color.BLACK)), + Level.ALL.intValue(), makeSignatureFormatString(ansi().fg(Color.DEFAULT)) + ); + + private String makeSignatureFormatString(Ansi base) { + return base.bold().a(Attribute.UNDERLINE).a("[%1$tb %1$td %1$tk:%1$tM:%1$tS.%1$tL] %2$s %3$s:").boldOff().a(Attribute.UNDERLINE_OFF).a("%4$s%5$s").a(Attribute.INTENSITY_FAINT).a("%6$s").reset().a("%n").toString(); + } + + private String makeStackTraceString(Throwable throwable) { + StringWriter stringWriter = new StringWriter(); + try (PrintWriter printWriter = new PrintWriter(stringWriter)) { + printWriter.println(); + throwable.printStackTrace(printWriter); + } + return stringWriter.toString(); + } + @Override public String format(LogRecord logRecord) { - ZonedDateTime zdt = ZonedDateTime.ofInstant(logRecord.getInstant(), ZoneId.systemDefault()); - String source; - if (logRecord.getSourceClassName() != null && !logRecord.getSourceClassName().startsWith(AnsiLogging.class.getName())) { - source = logRecord.getSourceClassName(); - if (logRecord.getSourceMethodName() != null) { - source += " " + logRecord.getSourceMethodName(); - } - } else - source = logRecord.getLoggerName(); + ZonedDateTime time = ZonedDateTime.ofInstant(logRecord.getInstant(), zoneId); + String source = Optional.ofNullable(logRecord.getLoggerName()).or(() -> Optional.ofNullable(logRecord.getSourceClassName())).map(s -> s + " ").orElse("") + Optional.ofNullable(logRecord.getSourceMethodName()).orElse(""); String message = formatMessage(logRecord); - boolean multiline = message.contains("\n"); - String throwable = ""; - if (logRecord.getThrown() != null) { - StringWriter sw = new StringWriter(); - try (PrintWriter pw = new PrintWriter(sw)) { - pw.println(); - logRecord.getThrown().printStackTrace(pw); - } - throwable = sw.toString(); - multiline = true; - } - Ansi ansi; - if (logRecord.getLevel() == Level.SEVERE) ansi = ansi().fgBright(Color.RED); - else if (logRecord.getLevel() == Level.WARNING) ansi = ansi().fgBright(Color.YELLOW); - else if (logRecord.getLevel() == Level.INFO) ansi = ansi().fg(Color.GREEN); - else if (logRecord.getLevel() == Level.CONFIG) ansi = ansi().fgBright(Color.BLUE); - else if (logRecord.getLevel() == Level.FINE) ansi = ansi().fg(Color.CYAN); - else if (logRecord.getLevel() == Level.FINER) ansi = ansi().fg(Color.MAGENTA); - else if (logRecord.getLevel() == Level.FINEST) ansi = ansi().fgBright(Color.BLACK); - else ansi = ansi().fg(Color.DEFAULT); - String format = ansi.bold().a(Attribute.UNDERLINE).a("%1$tb %1$td, %1$tY %1$tl:%1$tM:%1$tS %1$Tp %2$s %4$s:").boldOff().a(Attribute.UNDERLINE_OFF).a(multiline ? "%n%5$s%6$s" : " %5$s%6$s").reset().a("%n").toString(); - return String.format(format, zdt, source, logRecord.getLoggerName(), logRecord.getLevel().getLocalizedName(), message, throwable); + String throwable = Optional.ofNullable(logRecord.getThrown()).map(this::makeStackTraceString).orElse(""); + String format = levelColors.getOrDefault(logRecord.getLevel().intValue(), levelColors.get(Level.ALL.intValue())); + return String.format(format, time, source, logRecord.getLevel().getLocalizedName(), message.lines().count() > 1 ? System.lineSeparator() : " ", message, throwable); } }; } @@ -101,7 +104,7 @@ public class AnsiLogging extends ConsoleHandler { private final StringBuilder stringBuilder = new StringBuilder(); @Override - public final void write(int i) throws IOException { + public void write(int i) throws IOException { if (i == '\n') { logger.log(level, stringBuilder::toString); stringBuilder.setLength(0);