mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-22 01:11:40 +00:00
Move Java backend to properly named folder
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
package com.chameleonvision.util;
|
||||
|
||||
import edu.wpi.cscore.VideoMode;
|
||||
import org.opencv.core.Scalar;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class Helpers {
|
||||
private Helpers() {
|
||||
}
|
||||
|
||||
public static Scalar colorToScalar(Color color) {
|
||||
return new Scalar(color.getRed(), color.getGreen(), color.getBlue());
|
||||
}
|
||||
|
||||
public static HashMap VideoModeToHashMap(VideoMode videoMode) {
|
||||
return new HashMap<String, Object>() {{
|
||||
put("width", videoMode.width);
|
||||
put("height", videoMode.height);
|
||||
put("fps", videoMode.fps);
|
||||
put("pixelFormat", videoMode.pixelFormat.toString());}};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.chameleonvision.util;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.json.JsonMapper;
|
||||
import com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
|
||||
import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class JacksonHelper {
|
||||
private JacksonHelper() {} // no construction, utility class
|
||||
|
||||
public static <T> void serializer(Path path, T object) throws IOException {
|
||||
PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder().allowIfBaseType(object.getClass()).build();
|
||||
ObjectMapper objectMapper = JsonMapper.builder().activateDefaultTyping(ptv, ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT).build();
|
||||
objectMapper.writerWithDefaultPrettyPrinter().writeValue(new File(path.toString()), object);
|
||||
}
|
||||
|
||||
public static <T> T deserializer(Path path, Class<T> ref) throws IOException {
|
||||
PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder().allowIfBaseType(ref).build();
|
||||
ObjectMapper objectMapper = JsonMapper.builder().activateDefaultTyping(ptv, ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT).build();
|
||||
File jsonFile = new File(path.toString());
|
||||
if (jsonFile.exists() && jsonFile.length() > 0) {
|
||||
return objectMapper.readValue(jsonFile, ref);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.chameleonvision.util;
|
||||
|
||||
/**
|
||||
* A thread that tries to run at a specified loop time
|
||||
*/
|
||||
public abstract class LoopingRunnable implements Runnable {
|
||||
protected volatile Long loopTimeMs;
|
||||
|
||||
protected abstract void process();
|
||||
|
||||
public LoopingRunnable(Long loopTimeMs) {
|
||||
this.loopTimeMs = loopTimeMs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while(!Thread.interrupted()) {
|
||||
var now = System.currentTimeMillis();
|
||||
|
||||
// Do the thing
|
||||
process();
|
||||
|
||||
// sleep for the remaining time
|
||||
var timeElapsed = System.currentTimeMillis() - now;
|
||||
var delta = loopTimeMs - timeElapsed;
|
||||
try {
|
||||
if(delta > 0.0) {
|
||||
|
||||
Thread.sleep(delta, 0);
|
||||
|
||||
} else {
|
||||
Thread.sleep(1);
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.chameleonvision.util;
|
||||
|
||||
import java.lang.Math;
|
||||
|
||||
import edu.wpi.first.wpiutil.math.Num;
|
||||
import org.apache.commons.math3.util.FastMath;
|
||||
|
||||
public class MathHandler {
|
||||
MathHandler() {}
|
||||
|
||||
public static double sigmoid(Number x){
|
||||
double bias = 0;
|
||||
double a = 5;
|
||||
double b = -0.05;
|
||||
double k = 200;
|
||||
|
||||
if (x.doubleValue() < 50){
|
||||
bias = -1.338;
|
||||
}
|
||||
|
||||
return ((k / (1 + Math.pow(Math.E,(a + (b * x.doubleValue()))))) + bias);
|
||||
}
|
||||
|
||||
public static double toSlope(Number angle){
|
||||
return FastMath.atan(FastMath.toRadians(angle.doubleValue() - 90));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.chameleonvision.util;
|
||||
|
||||
public class MemoryManager {
|
||||
|
||||
private static final long MEGABYTE_FACTOR = 1024L * 1024L;
|
||||
|
||||
private int collectionThreshold;
|
||||
private int lastUsedMb = 0;
|
||||
|
||||
public MemoryManager(int collectionThreshold) {
|
||||
this.collectionThreshold = collectionThreshold;
|
||||
}
|
||||
|
||||
public void setCollectionThreshold(int collectionThreshold) {
|
||||
this.collectionThreshold = collectionThreshold;
|
||||
}
|
||||
|
||||
public static long getUsedMemory() {
|
||||
return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
|
||||
}
|
||||
|
||||
public static int getUsedMemoryMB() {
|
||||
return (int) (getUsedMemory() / MEGABYTE_FACTOR);
|
||||
}
|
||||
|
||||
private static void collect() {
|
||||
System.gc();
|
||||
System.runFinalization();
|
||||
}
|
||||
|
||||
public void run() { run(false); }
|
||||
|
||||
public void run(boolean print) {
|
||||
var usedMem = getUsedMemoryMB();
|
||||
|
||||
if (usedMem != lastUsedMb) {
|
||||
lastUsedMb = usedMem;
|
||||
if (print) System.out.printf("Memory usage: %dMB\n", usedMem);
|
||||
}
|
||||
|
||||
if (usedMem >= collectionThreshold) {
|
||||
collect();
|
||||
if (print) System.out.printf("Garbage collected at %dMB\n", usedMem);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package com.chameleonvision.util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
public enum Platform {
|
||||
WINDOWS_64("Windows x64"),
|
||||
LINUX_64("Linux x64"),
|
||||
LINUX_RASPBIAN("Linux Raspbian"),
|
||||
LINUX_ARM64("Linux ARM64"),
|
||||
MACOS_64("Mac OS x64"),
|
||||
UNSUPPORTED("Unsupported Platform");
|
||||
|
||||
public final String value;
|
||||
|
||||
Platform(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
private static final String OS_NAME = System.getProperty("os.name");
|
||||
private static final String OS_ARCH = System.getProperty("os.arch");
|
||||
public static final Platform CurrentPlatform = getCurrentPlatform();
|
||||
|
||||
public boolean isWindows() {
|
||||
return this == WINDOWS_64;
|
||||
}
|
||||
|
||||
public boolean isLinux() {
|
||||
return this == LINUX_64 || this == LINUX_RASPBIAN || this == LINUX_ARM64;
|
||||
}
|
||||
|
||||
public boolean isMac() {
|
||||
return this == MACOS_64;
|
||||
}
|
||||
|
||||
private static ShellExec shell = new ShellExec(true, false);
|
||||
|
||||
public boolean isRoot() {
|
||||
if (isLinux() || isMac()) {
|
||||
try {
|
||||
shell.execute("id", null, true, "-u");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
while (!shell.isOutputCompleted()) {
|
||||
// ignored
|
||||
}
|
||||
if (shell.getExitCode() == 0) {
|
||||
var out = shell.getOutput();
|
||||
out = out.split("\n")[0];
|
||||
return out.equals("0");
|
||||
}
|
||||
} else if (isWindows()) {
|
||||
return true;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isRaspbian() {
|
||||
try (BufferedReader reader = Files.newBufferedReader(Paths.get("/etc/os-release"))) {
|
||||
String value = reader.readLine();
|
||||
return value.contains("Raspbian");
|
||||
} catch (IOException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static Platform getCurrentPlatform() {
|
||||
if (OS_NAME.contains("Windows")) {
|
||||
if (OS_ARCH.equals("amd64")) return Platform.WINDOWS_64;
|
||||
}
|
||||
|
||||
if (OS_NAME.contains("Linux")) {
|
||||
if (OS_ARCH.equals("amd64")) return Platform.LINUX_64;
|
||||
if (isRaspbian()) return Platform.LINUX_RASPBIAN;
|
||||
if (OS_ARCH.contains("aarch")) return Platform.LINUX_ARM64;
|
||||
}
|
||||
|
||||
if (OS_NAME.contains("Mac")) {
|
||||
if (OS_ARCH.equals("amd64")) return Platform.MACOS_64;
|
||||
}
|
||||
|
||||
System.out.printf("Unknown Platform! OS: %s, Architecture: %s", OS_NAME, OS_ARCH);
|
||||
return Platform.UNSUPPORTED;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if (this.equals(UNSUPPORTED)) {
|
||||
return String.format("Unknown Platform. OS: %s, Architecture: %s", OS_NAME, OS_ARCH);
|
||||
} else {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.chameleonvision.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
public class ProgramDirectoryUtilities
|
||||
{
|
||||
private static String getJarName()
|
||||
{
|
||||
return new File(ProgramDirectoryUtilities.class.getProtectionDomain()
|
||||
.getCodeSource()
|
||||
.getLocation()
|
||||
.getPath())
|
||||
.getName();
|
||||
}
|
||||
|
||||
private static boolean runningFromJAR()
|
||||
{
|
||||
String jarName = getJarName();
|
||||
return jarName.contains(".jar");
|
||||
}
|
||||
|
||||
public static String getProgramDirectory()
|
||||
{
|
||||
if (runningFromJAR())
|
||||
{
|
||||
return getCurrentJARDirectory();
|
||||
} else
|
||||
{
|
||||
return System.getProperty("user.dir");
|
||||
// return getCurrentProjectDirectory();
|
||||
}
|
||||
}
|
||||
|
||||
private static String getCurrentProjectDirectory()
|
||||
{
|
||||
return new File("").getAbsolutePath();
|
||||
}
|
||||
|
||||
private static String getCurrentJARDirectory()
|
||||
{
|
||||
try
|
||||
{
|
||||
return new File(ProgramDirectoryUtilities.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParent();
|
||||
} catch (URISyntaxException exception)
|
||||
{
|
||||
exception.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
package com.chameleonvision.util;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* Execute external process and optionally read output buffer.
|
||||
*/
|
||||
public class ShellExec {
|
||||
private int exitCode;
|
||||
private boolean readOutput, readError;
|
||||
private StreamGobbler errorGobbler, outputGobbler;
|
||||
|
||||
public ShellExec() {
|
||||
this(false, false);
|
||||
}
|
||||
|
||||
public ShellExec(boolean readOutput, boolean readError) {
|
||||
this.readOutput = readOutput;
|
||||
this.readError = readError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a command in current folder, and wait for process to end
|
||||
* @param command command ("c:/some/folder/script.bat" or "some/folder/script.sh")
|
||||
* @param args 0..n command line arguments
|
||||
* @return process exit code
|
||||
*/
|
||||
public int execute(String command, String... args) throws IOException {
|
||||
return execute(command, null, true, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a command.
|
||||
* @param command command ("c:/some/folder/script.bat" or "some/folder/script.sh")
|
||||
* @param workdir working directory or NULL to use command folder
|
||||
* @param wait wait for process to end
|
||||
* @param args 0..n command line arguments
|
||||
* @return process exit code
|
||||
*/
|
||||
public int execute(String command, String workdir, boolean wait, String...args) throws IOException {
|
||||
String[] cmdArr;
|
||||
if (args != null && args.length > 0) {
|
||||
cmdArr = new String[1+args.length];
|
||||
cmdArr[0] = command;
|
||||
System.arraycopy(args, 0, cmdArr, 1, args.length);
|
||||
} else {
|
||||
cmdArr = new String[] { command };
|
||||
}
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(cmdArr);
|
||||
File workingDir = (workdir==null ? new File(command).getParentFile() : new File(workdir) );
|
||||
pb.directory(workingDir);
|
||||
|
||||
Process process = pb.start();
|
||||
|
||||
// Consume streams, older jvm's had a memory leak if streams were not read,
|
||||
// some other jvm+OS combinations may block unless streams are consumed.
|
||||
errorGobbler = new StreamGobbler(process.getErrorStream(), readError);
|
||||
outputGobbler = new StreamGobbler(process.getInputStream(), readOutput);
|
||||
errorGobbler.start();
|
||||
outputGobbler.start();
|
||||
|
||||
exitCode = 0;
|
||||
if (wait) {
|
||||
try {
|
||||
process.waitFor();
|
||||
exitCode = process.exitValue();
|
||||
} catch (InterruptedException ignored) { }
|
||||
}
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
public int getExitCode() {
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
public boolean isOutputCompleted() {
|
||||
return (outputGobbler != null && outputGobbler.isCompleted());
|
||||
}
|
||||
|
||||
public boolean isErrorCompleted() {
|
||||
return (errorGobbler != null && errorGobbler.isCompleted());
|
||||
}
|
||||
|
||||
public String getOutput() {
|
||||
return (outputGobbler != null ? outputGobbler.getOutput() : null);
|
||||
}
|
||||
|
||||
public String getError() {
|
||||
return (errorGobbler != null ? errorGobbler.getOutput() : null);
|
||||
}
|
||||
|
||||
//********************************************
|
||||
//********************************************
|
||||
|
||||
/**
|
||||
* StreamGobbler reads inputstream to "gobble" it.
|
||||
* This is used by Executor class when running
|
||||
* a commandline applications. Gobblers must read/purge
|
||||
* INSTR and ERRSTR process streams.
|
||||
* http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=4
|
||||
*/
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
private static class StreamGobbler extends Thread {
|
||||
private InputStream is;
|
||||
private StringBuilder output;
|
||||
private volatile boolean completed; // mark volatile to guarantee a thread safety
|
||||
|
||||
public StreamGobbler(InputStream is, boolean readStream) {
|
||||
this.is = is;
|
||||
this.output = (readStream ? new StringBuilder(256) : null);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
completed = false;
|
||||
try {
|
||||
String NL = System.getProperty("line.separator", "\r\n");
|
||||
|
||||
InputStreamReader isr = new InputStreamReader(is);
|
||||
BufferedReader br = new BufferedReader(isr);
|
||||
String line;
|
||||
while ( (line = br.readLine()) != null) {
|
||||
if (output != null)
|
||||
output.append(line).append(NL);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
// ex.printStackTrace();
|
||||
}
|
||||
completed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get inputstream buffer or null if stream
|
||||
* was not consumed.
|
||||
* @return
|
||||
*/
|
||||
public String getOutput() {
|
||||
return (output != null ? output.toString() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is input stream completed.
|
||||
* @return
|
||||
*/
|
||||
public boolean isCompleted() {
|
||||
return completed;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.chameleonvision.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Utilities {
|
||||
private Utilities() {}
|
||||
|
||||
public static boolean isValidIPV4(final String ip) {
|
||||
String PATTERN = "^((0|1\\d?\\d?|2[0-4]?\\d?|25[0-5]?|[3-9]\\d?)\\.){3}(0|1\\d?\\d?|2[0-4]?\\d?|25[0-5]?|[3-9]\\d?)$";
|
||||
|
||||
return ip.matches(PATTERN);
|
||||
}
|
||||
|
||||
public static List<Byte> getDigitBytes(int num) {
|
||||
List<Byte> digits = new ArrayList<>();
|
||||
collectDigitBytes(num, digits);
|
||||
return digits;
|
||||
}
|
||||
|
||||
private static void collectDigitBytes(int num, List<Byte> digits) {
|
||||
if (num / 10 > 0) {
|
||||
collectDigitBytes( num / 10, digits);
|
||||
}
|
||||
digits.add((byte) (num % 10));
|
||||
}
|
||||
|
||||
public static List<Integer> getDigits(int num) {
|
||||
List<Integer> digits = new ArrayList<>();
|
||||
collectDigits(num, digits);
|
||||
return digits;
|
||||
}
|
||||
|
||||
private static void collectDigits(int num, List<Integer> digits) {
|
||||
if(num / 10 > 0) {
|
||||
collectDigits(num / 10, digits);
|
||||
}
|
||||
digits.add(num % 10);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user