New formatting rules

This commit is contained in:
lucas lelievre
2022-04-27 22:29:09 +02:00
parent ba58f4df6a
commit 7ac7f7d424
95 changed files with 4092 additions and 3348 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,19 +1,16 @@
package dev.slimevr;
import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import javax.swing.JOptionPane;
import dev.slimevr.websocketapi.WebsocketAPI;
import org.apache.commons.cli.*;
import org.apache.commons.lang3.JavaVersion;
import org.apache.commons.lang3.SystemUtils;
import dev.slimevr.gui.Keybinding;
import dev.slimevr.gui.VRServerGUI;
import io.eiren.util.logging.LogManager;
import org.apache.commons.cli.*;
import org.apache.commons.lang3.JavaVersion;
import org.apache.commons.lang3.SystemUtils;
import javax.swing.*;
import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
public class Main {
@@ -35,7 +32,6 @@ public class Main {
Option noGui = new Option("g", "no-gui", false, "disable swing gui (allow for other gui to be used)");
Option help = new Option("h", "help", false, "Show help");
options.addOption(noGui);
options.addOption(help);
try {
@@ -51,7 +47,6 @@ public class Main {
System.exit(0);
}
File dir = new File("").getAbsoluteFile();
try {
LogManager.initialize(new File(dir, "logs/"), dir);
@@ -97,5 +92,4 @@ public class Main {
}
}
}
}

View File

@@ -4,5 +4,5 @@ public enum NetworkProtocol {
OWO_LEGACY,
SLIMEVR_RAW,
SLIMEVR_FLATBUFFER,
SLIMEVR_WEBSOCKET;
SLIMEVR_WEBSOCKET
}

View File

@@ -1,32 +1,17 @@
package dev.slimevr;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.function.Consumer;
import dev.slimevr.bridge.Bridge;
import dev.slimevr.platform.windows.WindowsNamedPipeBridge;
import dev.slimevr.bridge.VMCBridge;
import dev.slimevr.platform.windows.WindowsNamedPipeBridge;
import dev.slimevr.poserecorder.BVHRecorder;
import dev.slimevr.serial.SerialHandler;
import dev.slimevr.protocol.ProtocolAPI;
import dev.slimevr.vr.trackers.*;
import dev.slimevr.websocketapi.WebSocketVRBridge;
import dev.slimevr.serial.SerialHandler;
import dev.slimevr.util.ann.VRServerThread;
import dev.slimevr.vr.processor.HumanPoseProcessor;
import dev.slimevr.vr.processor.skeleton.HumanSkeleton;
import dev.slimevr.vr.trackers.*;
import dev.slimevr.vr.trackers.udp.TrackersUDPServer;
import dev.slimevr.websocketapi.WebSocketVRBridge;
import io.eiren.util.OperatingSystem;
import io.eiren.util.ann.ThreadSafe;
import io.eiren.util.ann.ThreadSecure;
@@ -36,23 +21,30 @@ import io.eiren.yaml.YamlFile;
import io.eiren.yaml.YamlNode;
import solarxr_protocol.datatypes.TrackerIdT;
import java.io.*;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.function.Consumer;
public class VRServer extends Thread {
private final List<Tracker> trackers = new FastList<>();
public final HumanPoseProcessor humanPoseProcessor;
public final YamlFile config = new YamlFile();
public final HMDTracker hmdTracker;
private final List<Tracker> trackers = new FastList<>();
private final TrackersUDPServer trackersServer;
private final List<Bridge> bridges = new FastList<>();
private final Queue<Runnable> tasks = new LinkedBlockingQueue<>();
private final Map<String, TrackerConfig> configuration = new HashMap<>();
public final YamlFile config = new YamlFile();
public final HMDTracker hmdTracker;
private final List<Consumer<Tracker>> newTrackersConsumers = new FastList<>();
private final List<Runnable> onTick = new FastList<>();
private final List<? extends ShareableTracker> shareTrackers;
private final BVHRecorder bvhRecorder;
private final SerialHandler serialHandler;
private final ProtocolAPI protocolAPI;
private String configPath;
private final String configPath;
public VRServer() {
this("vrconfig.yml");
@@ -88,10 +80,8 @@ public class VRServer extends Thread {
WindowsNamedPipeBridge feederBridge = new WindowsNamedPipeBridge(null, "steamvr_feeder", "SteamVR Feeder Bridge", "\\\\.\\pipe\\SlimeVRInput", new FastList<ShareableTracker>());
tasks.add(() -> feederBridge.startBridge());
bridges.add(feederBridge);
}
// Create WebSocket server
WebSocketVRBridge wsBridge = new WebSocketVRBridge(hmdTracker, shareTrackers, this);
tasks.add(() -> wsBridge.startBridge());
@@ -106,10 +96,8 @@ public class VRServer extends Thread {
e.printStackTrace();
}
bvhRecorder = new BVHRecorder(this);
registerTracker(hmdTracker);
for (int i = 0; i < shareTrackers.size(); ++i)
registerTracker(shareTrackers.get(i));
@@ -279,7 +267,6 @@ public class VRServer extends Thread {
});
}
public void updateTrackersFilters(TrackerFilters filter, float amount, int ticks) {
config.setProperty("filters.type", filter.name());
config.setProperty("filters.amount", amount);
@@ -333,7 +320,6 @@ public class VRServer extends Thread {
return null;
}
public BVHRecorder getBvhRecorder() {
return this.bvhRecorder;
}

View File

@@ -1,15 +1,7 @@
package dev.slimevr.autobone;
import java.io.File;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Consumer;
import com.jme3.math.FastMath;
import com.jme3.math.Vector3f;
import dev.slimevr.VRServer;
import dev.slimevr.poserecorder.*;
import dev.slimevr.vr.processor.HumanPoseProcessor;
@@ -20,80 +12,58 @@ import dev.slimevr.vr.trackers.TrackerPosition;
import dev.slimevr.vr.trackers.TrackerRole;
import dev.slimevr.vr.trackers.TrackerUtils;
import io.eiren.util.StringUtils;
import io.eiren.util.logging.LogManager;
import io.eiren.util.collections.FastList;
import io.eiren.util.logging.LogManager;
import org.apache.commons.lang3.tuple.Pair;
import java.io.File;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Consumer;
public class AutoBone {
public class Epoch {
public final int epoch;
public final float epochError;
public Epoch(int epoch, float epochError) {
this.epoch = epoch;
this.epochError = epochError;
}
@Override
public String toString() {
return "Epoch: " + epoch + ", Epoch Error: " + epochError;
}
}
private static File saveDir = new File("Recordings");
private static File loadDir = new File("LoadRecordings");
private static final File saveDir = new File("Recordings");
private static final File loadDir = new File("LoadRecordings");
// This is filled by reloadConfigValues()
public final EnumMap<SkeletonConfigValue, Float> configs = new EnumMap<SkeletonConfigValue, Float>(SkeletonConfigValue.class);
public final EnumMap<SkeletonConfigValue, Float> staticConfigs = new EnumMap<SkeletonConfigValue, Float>(SkeletonConfigValue.class);
public final FastList<SkeletonConfigValue> heightConfigs = new FastList<SkeletonConfigValue>(new SkeletonConfigValue[]{
SkeletonConfigValue.NECK, SkeletonConfigValue.TORSO, SkeletonConfigValue.LEGS_LENGTH});
public final FastList<SkeletonConfigValue> lengthConfigs = new FastList<SkeletonConfigValue>(new SkeletonConfigValue[]{
SkeletonConfigValue.HEAD, SkeletonConfigValue.NECK, SkeletonConfigValue.TORSO, SkeletonConfigValue.HIPS_WIDTH, SkeletonConfigValue.LEGS_LENGTH});
protected final VRServer server;
public int cursorIncrement = 1;
public int minDataDistance = 2;
public int maxDataDistance = 32;
public int numEpochs = 5;
public float initialAdjustRate = 2.5f;
public float adjustRateDecay = 1.01f;
public float slideErrorFactor = 1.0f;
public float offsetSlideErrorFactor = 0.0f;
public float offsetErrorFactor = 0.0f;
public float proportionErrorFactor = 0.2f;
public float heightErrorFactor = 0.1f;
public float positionErrorFactor = 0.0f;
public float positionOffsetErrorFactor = 0.0f;
public boolean calcInitError = false;
public float targetHeight = -1;
// TODO Needs much more work, probably going to rethink how the errors work to avoid this barely functional workaround @ButterscotchV
// For scaling distances, since smaller sizes will cause smaller distances
//private float totalLengthBase = 2f;
public float positionErrorFactor = 0.0f;
public float positionOffsetErrorFactor = 0.0f;
public boolean calcInitError = false;
public float targetHeight = -1;
// TODO hip tracker stuff... Hip tracker should be around 3 to 5 centimeters.
// Human average is probably 1.1235 (SD 0.07)
public float legBodyRatio = 1.1235f;
// SD of 0.07, capture 68% within range
public float legBodyRatioRange = 0.07f;
// kneeLegRatio seems to be around 0.54 to 0.6 after asking a few people in the SlimeVR discord.
public float kneeLegRatio = 0.55f;
// kneeLegRatio seems to be around 0.55 to 0.64 after asking a few people in the SlimeVR discord. TODO : Chest should be a bit shorter (0.54?) if user has an additional hip tracker.
public float chestTorsoRatio = 0.57f;
// TODO hip tracker stuff... Hip tracker should be around 3 to 5 centimeters.
protected final VRServer server;
// This is filled by reloadConfigValues()
public final EnumMap<SkeletonConfigValue, Float> configs = new EnumMap<SkeletonConfigValue, Float>(SkeletonConfigValue.class);
public final EnumMap<SkeletonConfigValue, Float> staticConfigs = new EnumMap<SkeletonConfigValue, Float>(SkeletonConfigValue.class);
public final FastList<SkeletonConfigValue> heightConfigs = new FastList<SkeletonConfigValue>(new SkeletonConfigValue[]{
SkeletonConfigValue.NECK, SkeletonConfigValue.TORSO, SkeletonConfigValue.LEGS_LENGTH});
public final FastList<SkeletonConfigValue> lengthConfigs = new FastList<SkeletonConfigValue>(new SkeletonConfigValue[]{
SkeletonConfigValue.HEAD, SkeletonConfigValue.NECK, SkeletonConfigValue.TORSO, SkeletonConfigValue.HIPS_WIDTH, SkeletonConfigValue.LEGS_LENGTH});
public AutoBone(VRServer server) {
this.server = server;
reloadConfigValues();
@@ -118,6 +88,15 @@ public class AutoBone {
this.targetHeight = server.config.getFloat("autobone.manualTargetHeight", -1f);
}
// Mean square error function
protected static float errorFunc(float errorDeriv) {
return 0.5f * (errorDeriv * errorDeriv);
}
public static File getLoadDir() {
return loadDir;
}
public void reloadConfigValues() {
reloadConfigValues(null);
}
@@ -611,11 +590,6 @@ public class AutoBone {
return sumWeight > 0f ? totalError / sumWeight : 0f;
}
// Mean square error function
protected static float errorFunc(float errorDeriv) {
return 0.5f * (errorDeriv * errorDeriv);
}
protected void updateSkeletonBoneLength(PoseFrameSkeleton skeleton1, PoseFrameSkeleton skeleton2, SkeletonConfigValue config, float newLength) {
skeleton1.skeletonConfig.setConfig(config, newLength);
skeleton1.updatePoseAffectedByConfig(config);
@@ -637,7 +611,6 @@ public class AutoBone {
return configInfo.toString();
}
public void saveRecording(PoseFrames frames) {
if (saveDir.isDirectory() || saveDir.mkdirs()) {
File saveRecording;
@@ -680,7 +653,19 @@ public class AutoBone {
return recordings;
}
public static File getLoadDir() {
return loadDir;
public class Epoch {
public final int epoch;
public final float epochError;
public Epoch(int epoch, float epochError) {
this.epoch = epoch;
this.epochError = epochError;
}
@Override
public String toString() {
return "Epoch: " + epoch + ", Epoch Error: " + epochError;
}
}
}

View File

@@ -13,10 +13,10 @@ import dev.slimevr.vr.trackers.ShareableTracker;
public interface Bridge {
@VRServerThread
public void dataRead();
void dataRead();
@VRServerThread
public void dataWrite();
void dataWrite();
/**
* Adds shared tracker to the bridge. Bridge should notify the
@@ -26,7 +26,7 @@ public interface Bridge {
* @param tracker
*/
@VRServerThread
public void addSharedTracker(ShareableTracker tracker);
void addSharedTracker(ShareableTracker tracker);
/**
* Removes tracker from a bridge. If the other side supports
@@ -38,8 +38,8 @@ public interface Bridge {
* @param tracker
*/
@VRServerThread
public void removeSharedTracker(ShareableTracker tracker);
void removeSharedTracker(ShareableTracker tracker);
@VRServerThread
public void startBridge();
void startBridge();
}

View File

@@ -38,5 +38,4 @@ public class OpenVRNativeBridge implements Bridge {
public void startBridge() {
}
}

View File

@@ -3,5 +3,5 @@ package dev.slimevr.bridge;
public enum PipeState {
CREATED,
OPEN,
ERROR;
ERROR
}

View File

@@ -1,53 +1,38 @@
package dev.slimevr.bridge;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import dev.slimevr.Main;
import dev.slimevr.bridge.ProtobufMessages.Position;
import dev.slimevr.bridge.ProtobufMessages.ProtobufMessage;
import dev.slimevr.bridge.ProtobufMessages.TrackerAdded;
import dev.slimevr.bridge.ProtobufMessages.TrackerStatus;
import dev.slimevr.bridge.ProtobufMessages.UserAction;
import dev.slimevr.bridge.ProtobufMessages.*;
import dev.slimevr.util.ann.VRServerThread;
import dev.slimevr.vr.trackers.ComputedTracker;
import dev.slimevr.vr.trackers.HMDTracker;
import dev.slimevr.vr.trackers.ShareableTracker;
import dev.slimevr.vr.trackers.TrackerRole;
import dev.slimevr.vr.trackers.VRTracker;
import dev.slimevr.vr.trackers.*;
import io.eiren.util.ann.Synchronize;
import io.eiren.util.ann.ThreadSafe;
import io.eiren.util.collections.FastList;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.LinkedBlockingQueue;
public abstract class ProtobufBridge<T extends VRTracker> implements Bridge {
@VRServerThread
protected final List<ShareableTracker> sharedTrackers = new FastList<>();
protected final String bridgeName;
private final Vector3f vec1 = new Vector3f();
private final Quaternion quat1 = new Quaternion();
@ThreadSafe
private final Queue<ProtobufMessage> inputQueue = new LinkedBlockingQueue<>();
@ThreadSafe
private final Queue<ProtobufMessage> outputQueue = new LinkedBlockingQueue<>();
@VRServerThread
protected final List<ShareableTracker> sharedTrackers = new FastList<>();
@Synchronize("self")
private final Map<String, T> remoteTrackersBySerial = new HashMap<>();
@Synchronize("self")
private final Map<Integer, T> remoteTrackersByTrackerId = new HashMap<>();
private boolean hadNewData = false;
private T hmdTracker;
private final HMDTracker hmd;
protected final String bridgeName;
private boolean hadNewData = false;
private T hmdTracker;
public ProtobufBridge(String bridgeName, HMDTracker hmd) {
this.bridgeName = bridgeName;

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,9 @@
package dev.slimevr.bridge;
import java.net.InetAddress;
import dev.slimevr.vr.trackers.ShareableTracker;
import java.net.InetAddress;
public class VMCBridge extends Thread implements Bridge {
public final int readPort;
@@ -47,5 +47,4 @@ public class VMCBridge extends Thread implements Bridge {
public void startBridge() {
start();
}
}

View File

@@ -1,43 +1,31 @@
package dev.slimevr.gui;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.JButton;
import javax.swing.border.EmptyBorder;
import java.awt.event.MouseEvent;
import java.io.File;
import java.util.List;
import java.util.concurrent.Future;
import io.eiren.util.StringUtils;
import io.eiren.util.ann.AWTThread;
import io.eiren.util.collections.FastList;
import io.eiren.util.logging.LogManager;
import javax.swing.event.MouseInputAdapter;
import org.apache.commons.lang3.tuple.Pair;
import dev.slimevr.VRServer;
import dev.slimevr.autobone.AutoBone;
import dev.slimevr.gui.swing.EJBox;
import dev.slimevr.poserecorder.PoseFrames;
import dev.slimevr.poserecorder.PoseFrameIO;
import dev.slimevr.poserecorder.PoseRecorder;
import dev.slimevr.vr.processor.skeleton.SkeletonConfigValue;
import io.eiren.util.StringUtils;
import io.eiren.util.ann.AWTThread;
import io.eiren.util.collections.FastList;
import io.eiren.util.logging.LogManager;
import org.apache.commons.lang3.tuple.Pair;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.MouseInputAdapter;
import java.awt.event.MouseEvent;
import java.util.List;
import java.util.concurrent.Future;
public class AutoBoneWindow extends JFrame {
private EJBox pane;
private final transient VRServer server;
private final transient SkeletonConfigGUI skeletonConfig;
private final transient PoseRecorder poseRecorder;
private final transient AutoBone autoBone;
private final EJBox pane;
private transient Thread recordingThread = null;
private transient Thread saveRecordingThread = null;
private transient Thread autoBoneThread = null;
@@ -63,7 +51,6 @@ public class AutoBoneWindow extends JFrame {
build();
}
private float processFrames(PoseFrames frames) {
return autoBone.processFrames(frames, autoBone.calcInitError, autoBone.targetHeight, (epoch) -> {
processLabel.setText(epoch.toString());

View File

@@ -1,22 +1,16 @@
package dev.slimevr.gui;
import java.awt.Container;
import java.awt.event.MouseEvent;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextArea;
import javax.swing.border.EmptyBorder;
import javax.swing.event.MouseInputAdapter;
import dev.slimevr.gui.swing.EJBox;
import dev.slimevr.vr.trackers.CalibratingTracker;
import dev.slimevr.vr.trackers.Tracker;
import io.eiren.util.ann.AWTThread;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.MouseInputAdapter;
import java.awt.*;
import java.awt.event.MouseEvent;
public class CalibrationWindow extends JFrame {
public final Tracker tracker;
@@ -74,7 +68,6 @@ public class CalibrationWindow extends JFrame {
add(newCalibration = new JTextArea(10, 25));
}});
// Pack and display
pack();
setLocationRelativeTo(null);

View File

@@ -2,16 +2,15 @@ package dev.slimevr.gui;
import com.melloware.jintellitype.HotkeyListener;
import com.melloware.jintellitype.JIntellitype;
import dev.slimevr.VRServer;
import io.eiren.util.OperatingSystem;
import io.eiren.util.ann.AWTThread;
import io.eiren.util.logging.LogManager;
public class Keybinding implements HotkeyListener {
public final VRServer server;
private static final int RESET = 1;
private static final int QUICK_RESET = 2;
public final VRServer server;
@AWTThread
public Keybinding(VRServer server) {

View File

@@ -1,6 +1,6 @@
package dev.slimevr.gui;
import java.awt.Font;
import java.awt.*;
import java.text.AttributedCharacterIterator.Attribute;
import java.util.Map;

View File

@@ -1,14 +1,5 @@
package dev.slimevr.gui;
import java.awt.event.MouseEvent;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.event.MouseInputAdapter;
import dev.slimevr.VRServer;
import dev.slimevr.gui.swing.ButtonTimer;
import dev.slimevr.gui.swing.EJBagNoStretch;
@@ -17,12 +8,18 @@ import dev.slimevr.vr.processor.skeleton.SkeletonConfigValue;
import io.eiren.util.StringUtils;
import io.eiren.util.ann.ThreadSafe;
import javax.swing.*;
import javax.swing.event.MouseInputAdapter;
import java.awt.event.MouseEvent;
import java.util.HashMap;
import java.util.Map;
public class SkeletonConfigGUI extends EJBagNoStretch {
private final VRServer server;
private final VRServerGUI gui;
private final AutoBoneWindow autoBone;
private Map<SkeletonConfigValue, SkeletonLabel> labels = new HashMap<>();
private final Map<SkeletonConfigValue, SkeletonLabel> labels = new HashMap<>();
private JCheckBox precisionCb;
public SkeletonConfigGUI(VRServer server, VRServerGUI gui) {

View File

@@ -1,14 +1,8 @@
package dev.slimevr.gui;
import java.awt.GridBagConstraints;
import java.util.List;
import javax.swing.JLabel;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import dev.slimevr.VRServer;
import dev.slimevr.gui.swing.EJBagNoStretch;
import dev.slimevr.util.ann.VRServerThread;
@@ -18,16 +12,18 @@ import io.eiren.util.StringUtils;
import io.eiren.util.ann.ThreadSafe;
import io.eiren.util.collections.FastList;
import javax.swing.*;
import java.awt.*;
import java.util.List;
public class SkeletonList extends EJBagNoStretch {
private static final long UPDATE_DELAY = 50;
private final VRServerGUI gui;
private final List<NodeStatus> nodes = new FastList<>();
Quaternion q = new Quaternion();
Vector3f v = new Vector3f();
float[] angles = new float[3];
private final VRServerGUI gui;
private final List<NodeStatus> nodes = new FastList<>();
private long lastUpdate = 0;
public SkeletonList(VRServer server, VRServerGUI gui) {

View File

@@ -1,29 +1,25 @@
package dev.slimevr.gui;
import java.awt.event.MouseEvent;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.event.MouseInputAdapter;
import com.jme3.math.FastMath;
import dev.slimevr.VRServer;
import dev.slimevr.gui.swing.EJBagNoStretch;
import dev.slimevr.vr.trackers.TrackerFilters;
import io.eiren.util.StringUtils;
import javax.swing.*;
import javax.swing.event.MouseInputAdapter;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
public class TrackersFiltersGUI extends EJBagNoStretch {
private final VRServer server;
TrackerFilters filterType;
float filterAmount;
int filterTicks;
private JLabel amountLabel, ticksLabel;
private final JLabel amountLabel;
private final JLabel ticksLabel;
public TrackersFiltersGUI(VRServer server, VRServerGUI gui) {
@@ -54,7 +50,7 @@ public class TrackersFiltersGUI extends EJBagNoStretch {
add(Box.createVerticalStrut(40));
row++;
filterAmount = (Float) FastMath.clamp(server.config.getFloat("filters.amount", 0.3f), 0, 1);
filterAmount = FastMath.clamp(server.config.getFloat("filters.amount", 0.3f), 0, 1);
add(new JLabel("Intensity"), c(0, row, 2));
add(new AdjButton("+", 0, false), c(1, row, 2));
@@ -67,15 +63,14 @@ public class TrackersFiltersGUI extends EJBagNoStretch {
add(new AdjButton("+", 1, false), c(1, row, 2));
add(ticksLabel = new JLabel(StringUtils.prettyNumber(filterTicks)), c(2, row, 2));
add(new AdjButton("-", 1, true), c(3, row, 2));
}
void adjustValues(int cat, boolean neg) {
if (cat == 0) {
if (neg) {
filterAmount = (Float) FastMath.clamp(filterAmount - 0.1f, 0, 1);
filterAmount = FastMath.clamp(filterAmount - 0.1f, 0, 1);
} else {
filterAmount = (Float) FastMath.clamp(filterAmount + 0.1f, 0, 1);
filterAmount = FastMath.clamp(filterAmount + 0.1f, 0, 1);
}
amountLabel.setText((StringUtils.prettyNumber(filterAmount * 100f)) + "%");
} else if (cat == 1) {
@@ -101,6 +96,5 @@ public class TrackersFiltersGUI extends EJBagNoStretch {
}
});
}
}
}

View File

@@ -1,53 +1,33 @@
package dev.slimevr.gui;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import java.util.Objects;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import dev.slimevr.VRServer;
import dev.slimevr.gui.swing.EJBagNoStretch;
import dev.slimevr.gui.swing.EJBoxNoStretch;
import dev.slimevr.vr.trackers.ComputedTracker;
import dev.slimevr.vr.trackers.HMDTracker;
import dev.slimevr.vr.trackers.IMUTracker;
import dev.slimevr.vr.trackers.ReferenceAdjustedTracker;
import dev.slimevr.vr.trackers.Tracker;
import dev.slimevr.vr.trackers.TrackerConfig;
import dev.slimevr.vr.trackers.TrackerMountingRotation;
import dev.slimevr.vr.trackers.TrackerPosition;
import dev.slimevr.vr.trackers.TrackerWithBattery;
import dev.slimevr.vr.trackers.TrackerWithTPS;
import dev.slimevr.vr.trackers.*;
import io.eiren.util.StringUtils;
import io.eiren.util.ann.AWTThread;
import io.eiren.util.ann.ThreadSafe;
import io.eiren.util.collections.FastList;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import java.util.Objects;
public class TrackersList extends EJBoxNoStretch {
private static final long UPDATE_DELAY = 50;
private final VRServer server;
private final VRServerGUI gui;
Quaternion q = new Quaternion();
Vector3f v = new Vector3f();
float[] angles = new float[3];
private List<TrackerPanel> trackers = new FastList<>();
private final VRServer server;
private final VRServerGUI gui;
private final List<TrackerPanel> trackers = new FastList<>();
private long lastUpdate = 0;
private boolean debug = false;
@@ -61,6 +41,18 @@ public class TrackersList extends EJBoxNoStretch {
server.addNewTrackerConsumer(this::newTrackerAdded);
}
private static int getTrackerSort(Tracker t) {
if (t instanceof ReferenceAdjustedTracker)
t = ((ReferenceAdjustedTracker<?>) t).getTracker();
if (t instanceof IMUTracker)
return 0;
if (t instanceof HMDTracker)
return 100;
if (t instanceof ComputedTracker)
return 200;
return 1000;
}
@AWTThread
public void setDebug(boolean debug) {
this.debug = debug;
@@ -363,7 +355,7 @@ public class TrackersList extends EJBoxNoStretch {
// -40 dBm is excellent, -95 dBm is very poor
int percentage = (signal - -95) * (100 - 0) / (-40 - -95) + 0;
percentage = Math.max(Math.min(percentage, 100), 0);
signalStrength.setText(String.valueOf(percentage) + "% " + "(" + String.valueOf(signal) + " dBm" + ")");
signalStrength.setText(percentage + "% " + "(" + signal + " dBm" + ")");
}
}
}
@@ -414,16 +406,4 @@ public class TrackersList extends EJBoxNoStretch {
}
}
}
private static int getTrackerSort(Tracker t) {
if (t instanceof ReferenceAdjustedTracker)
t = ((ReferenceAdjustedTracker<?>) t).getTracker();
if (t instanceof IMUTracker)
return 0;
if (t instanceof HMDTracker)
return 100;
if (t instanceof ComputedTracker)
return 200;
return 1000;
}
}

View File

@@ -1,29 +1,23 @@
package dev.slimevr.gui;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.MouseInputAdapter;
import dev.slimevr.Main;
import dev.slimevr.VRServer;
import dev.slimevr.platform.windows.WindowsNamedPipeBridge;
import dev.slimevr.gui.swing.ButtonTimer;
import dev.slimevr.gui.swing.EJBagNoStretch;
import dev.slimevr.gui.swing.EJBox;
import dev.slimevr.gui.swing.EJBoxNoStretch;
import dev.slimevr.platform.windows.WindowsNamedPipeBridge;
import dev.slimevr.vr.trackers.TrackerRole;
import io.eiren.util.MacOSX;
import io.eiren.util.OperatingSystem;
import io.eiren.util.StringUtils;
import io.eiren.util.ann.AWTThread;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GraphicsConfiguration;
import java.awt.Rectangle;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.MouseInputAdapter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
@@ -33,8 +27,8 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static javax.swing.BoxLayout.PAGE_AXIS;
import static javax.swing.BoxLayout.LINE_AXIS;
import static javax.swing.BoxLayout.PAGE_AXIS;
public class VRServerGUI extends JFrame {
@@ -45,7 +39,7 @@ public class VRServerGUI extends JFrame {
private final TrackersFiltersGUI trackersFiltersGUI;
private final SkeletonList skeletonList;
private JButton resetButton;
private EJBox pane;
private final EJBox pane;
private float zoom = 1.5f;
private float initZoom = zoom;
@@ -90,7 +84,6 @@ public class VRServerGUI extends JFrame {
trackersFiltersGUI = new TrackersFiltersGUI(server, this);
this.skeletonList = new SkeletonList(server, this);
JScrollPane scrollPane = (JScrollPane) add(new JScrollPane(pane = new EJBox(PAGE_AXIS), ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED));
scrollPane.getVerticalScrollBar().setUnitIncrement(16);
@@ -116,6 +109,31 @@ public class VRServerGUI extends JFrame {
build();
}
private static void processNewZoom(float zoom, Component comp) {
if (comp.isFontSet()) {
Font newFont = new ScalableFont(comp.getFont(), zoom);
comp.setFont(newFont);
}
if (comp instanceof Container) {
Container cont = (Container) comp;
for (Component child : cont.getComponents())
processNewZoom(zoom, child);
}
}
private static void setDefaultFontSize(float zoom) {
java.util.Enumeration<Object> keys = UIManager.getDefaults().keys();
while (keys.hasMoreElements()) {
Object key = keys.nextElement();
Object value = UIManager.get(key);
if (value instanceof javax.swing.plaf.FontUIResource) {
javax.swing.plaf.FontUIResource f = (javax.swing.plaf.FontUIResource) value;
javax.swing.plaf.FontUIResource f2 = new javax.swing.plaf.FontUIResource(f.deriveFont(f.getSize() * zoom));
UIManager.put(key, f2);
}
}
}
protected void saveFrameInfo() {
Rectangle b = getBounds();
server.config.setProperty("window.width", b.width);
@@ -320,10 +338,8 @@ public class VRServerGUI extends JFrame {
});
}
});
}});
add(Box.createVerticalStrut(10));
}
@@ -366,31 +382,6 @@ public class VRServerGUI extends JFrame {
server.saveConfig();
}
private static void processNewZoom(float zoom, Component comp) {
if (comp.isFontSet()) {
Font newFont = new ScalableFont(comp.getFont(), zoom);
comp.setFont(newFont);
}
if (comp instanceof Container) {
Container cont = (Container) comp;
for (Component child : cont.getComponents())
processNewZoom(zoom, child);
}
}
private static void setDefaultFontSize(float zoom) {
java.util.Enumeration<Object> keys = UIManager.getDefaults().keys();
while (keys.hasMoreElements()) {
Object key = keys.nextElement();
Object value = UIManager.get(key);
if (value instanceof javax.swing.plaf.FontUIResource) {
javax.swing.plaf.FontUIResource f = (javax.swing.plaf.FontUIResource) value;
javax.swing.plaf.FontUIResource f2 = new javax.swing.plaf.FontUIResource(f.deriveFont(f.getSize() * zoom));
UIManager.put(key, f2);
}
}
}
@AWTThread
private void resetFast() {
server.resetTrackersYaw();

View File

@@ -1,29 +1,26 @@
package dev.slimevr.gui;
import java.awt.Container;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.*;
import javax.swing.event.MouseInputAdapter;
import com.fazecast.jSerialComm.SerialPort;
import dev.slimevr.gui.swing.EJBox;
import dev.slimevr.serial.SerialListener;
import io.eiren.util.ann.AWTThread;
import javax.swing.*;
import javax.swing.event.MouseInputAdapter;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class WiFiWindow extends JFrame implements SerialListener {
private static String savedSSID = "";
private static String savedPassword = "";
private final VRServerGUI gui;
JTextField ssidField;
JPasswordField passwdField;
JTextArea log;
private final VRServerGUI gui;
public WiFiWindow(VRServerGUI gui) {
super("WiFi Settings");
this.gui = gui;

View File

@@ -1,13 +1,12 @@
package dev.slimevr.gui.swing;
import javax.swing.*;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.AbstractButton;
public class ButtonTimer {
private static Timer timer = new Timer();
private static final Timer timer = new Timer();
public static void runTimer(AbstractButton button, int seconds, String defaultText, Runnable runnable) {
if (seconds <= 0) {
@@ -37,6 +36,5 @@ public class ButtonTimer {
public void run() {
runTimer(button, seconds, defaultText, runnable);
}
}
}

View File

@@ -1,6 +1,6 @@
package dev.slimevr.gui.swing;
import java.awt.GridBagLayout;
import java.awt.*;
public class EJBag extends EJPanel {

View File

@@ -1,8 +1,6 @@
package dev.slimevr.gui.swing;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.*;
public class EJBagNoStretch extends EJPanel {

View File

@@ -1,6 +1,6 @@
package dev.slimevr.gui.swing;
import javax.swing.BoxLayout;
import javax.swing.*;
public class EJBox extends EJPanel {

View File

@@ -1,9 +1,7 @@
package dev.slimevr.gui.swing;
import java.awt.Container;
import java.awt.Dimension;
import javax.swing.BoxLayout;
import javax.swing.*;
import java.awt.*;
public class EJBoxNoStretch extends EJPanel {

View File

@@ -1,13 +1,7 @@
package dev.slimevr.gui.swing;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.LayoutManager;
import javax.swing.Box;
import javax.swing.JPanel;
import javax.swing.*;
import java.awt.*;
public abstract class EJPanel extends JPanel {

View File

@@ -1,8 +1,7 @@
package dev.slimevr.gui.swing;
import javax.swing.JLabel;
import javax.swing.*;
public class EJlabel extends JLabel {
}

View File

@@ -9,5 +9,5 @@ public interface Magneto extends Library {
void calculate(double[] data, int nlines, double nxsrej, double hm, double[] B, double[] A_1);
double calculateHnorm(double data[], int nlines);
double calculateHnorm(double[] data, int nlines);
}

View File

@@ -1,14 +1,10 @@
package dev.slimevr.platform.windows;
import java.io.IOException;
import java.util.List;
import com.google.protobuf.CodedOutputStream;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinBase;
import com.sun.jna.platform.win32.WinError;
import com.sun.jna.ptr.IntByReference;
import dev.slimevr.Main;
import dev.slimevr.bridge.BridgeThread;
import dev.slimevr.bridge.PipeState;
@@ -16,24 +12,21 @@ import dev.slimevr.bridge.ProtobufBridge;
import dev.slimevr.bridge.ProtobufMessages.ProtobufMessage;
import dev.slimevr.bridge.ProtobufMessages.TrackerAdded;
import dev.slimevr.util.ann.VRServerThread;
import dev.slimevr.vr.trackers.HMDTracker;
import dev.slimevr.vr.trackers.ShareableTracker;
import dev.slimevr.vr.trackers.TrackerPosition;
import dev.slimevr.vr.trackers.TrackerRole;
import dev.slimevr.vr.trackers.VRTracker;
import dev.slimevr.vr.trackers.*;
import io.eiren.util.logging.LogManager;
import java.io.IOException;
import java.util.List;
public class WindowsNamedPipeBridge extends ProtobufBridge<VRTracker> implements Runnable {
private final TrackerRole[] defaultRoles = new TrackerRole[]{TrackerRole.WAIST, TrackerRole.LEFT_FOOT, TrackerRole.RIGHT_FOOT};
private final byte[] buffArray = new byte[2048];
protected WindowsPipe pipe;
protected final String pipeName;
protected final String bridgeSettingsKey;
protected final Thread runnerThread;
private final TrackerRole[] defaultRoles = new TrackerRole[]{TrackerRole.WAIST, TrackerRole.LEFT_FOOT, TrackerRole.RIGHT_FOOT};
private final byte[] buffArray = new byte[2048];
private final List<? extends ShareableTracker> shareableTrackers;
protected WindowsPipe pipe;
public WindowsNamedPipeBridge(HMDTracker hmd, String bridgeSettingsKey, String bridgeName, String pipeName, List<? extends ShareableTracker> shareableTrackers) {
super(bridgeName, hmd);

View File

@@ -1,35 +1,30 @@
package dev.slimevr.platform.windows;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinBase;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.ptr.IntByReference;
import dev.slimevr.VRServer;
import dev.slimevr.bridge.Bridge;
import dev.slimevr.bridge.PipeState;
import dev.slimevr.vr.trackers.ComputedTracker;
import dev.slimevr.vr.trackers.HMDTracker;
import dev.slimevr.vr.trackers.ShareableTracker;
import dev.slimevr.vr.trackers.Tracker;
import dev.slimevr.vr.trackers.TrackerStatus;
import dev.slimevr.vr.trackers.*;
import io.eiren.util.collections.FastList;
import io.eiren.util.logging.LogManager;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
public class WindowsNamedPipeVRBridge extends Thread implements Bridge {
private static final int MAX_COMMAND_LENGTH = 2048;
public static final String HMDPipeName = "\\\\.\\pipe\\HMDPipe";
public static final String TrackersPipeName = "\\\\.\\pipe\\TrackPipe";
public static final Charset ASCII = Charset.forName("ASCII");
public static final Charset ASCII = StandardCharsets.US_ASCII;
private static final int MAX_COMMAND_LENGTH = 2048;
private final byte[] buffArray = new byte[1024];
private final StringBuilder commandBuilder = new StringBuilder(1024);
private final StringBuilder sbBuffer = new StringBuilder(1024);
@@ -37,15 +32,13 @@ public class WindowsNamedPipeVRBridge extends Thread implements Bridge {
private final Vector3f vBuffer2 = new Vector3f();
private final Quaternion qBuffer = new Quaternion();
private final Quaternion qBuffer2 = new Quaternion();
private WindowsPipe hmdPipe;
private final HMDTracker hmd;
private final List<WindowsPipe> trackerPipes;
private final List<? extends Tracker> shareTrackers;
private final List<ComputedTracker> internalTrackers;
private final HMDTracker internalHMDTracker = new HMDTracker("internal://HMD");
private final AtomicBoolean newHMDData = new AtomicBoolean(false);
private WindowsPipe hmdPipe;
public WindowsNamedPipeVRBridge(HMDTracker hmd, List<? extends Tracker> shareTrackers, VRServer server) {
super("Named Pipe VR Bridge");
@@ -61,6 +54,14 @@ public class WindowsNamedPipeVRBridge extends Thread implements Bridge {
}
}
public static void safeDisconnect(WindowsPipe pipe) {
try {
if (pipe != null && pipe.pipeHandle != null)
Kernel32.INSTANCE.DisconnectNamedPipe(pipe.pipeHandle);
} catch (Exception e) {
}
}
@Override
public void run() {
try {
@@ -150,7 +151,7 @@ public class WindowsNamedPipeVRBridge extends Thread implements Bridge {
private void executeHMDInput() throws IOException {
String[] split = commandBuilder.toString().split(" ");
if (split.length < 7) {
LogManager.log.severe("[VRBridge] Short HMD data received: " + commandBuilder.toString());
LogManager.log.severe("[VRBridge] Short HMD data received: " + commandBuilder);
return;
}
try {
@@ -264,14 +265,6 @@ public class WindowsNamedPipeVRBridge extends Thread implements Bridge {
}
}
public static void safeDisconnect(WindowsPipe pipe) {
try {
if (pipe != null && pipe.pipeHandle != null)
Kernel32.INSTANCE.DisconnectNamedPipe(pipe.pipeHandle);
} catch (Exception e) {
}
}
@Override
public void addSharedTracker(ShareableTracker tracker) {
// TODO Auto-generated method stub

View File

@@ -1,5 +1,22 @@
package dev.slimevr.platform.windows;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinBase;
import com.sun.jna.platform.win32.WinError;
import com.sun.jna.ptr.IntByReference;
import dev.slimevr.VRServer;
import dev.slimevr.bridge.Bridge;
import dev.slimevr.bridge.PipeState;
import dev.slimevr.vr.trackers.ShareableTracker;
import dev.slimevr.vr.trackers.TrackerPosition;
import dev.slimevr.vr.trackers.TrackerStatus;
import dev.slimevr.vr.trackers.VRTracker;
import io.eiren.util.collections.FastList;
import io.eiren.util.logging.LogManager;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
@@ -7,38 +24,18 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import dev.slimevr.VRServer;
import dev.slimevr.bridge.Bridge;
import org.apache.commons.lang3.StringUtils;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinBase;
import com.sun.jna.platform.win32.WinError;
import com.sun.jna.ptr.IntByReference;
import dev.slimevr.bridge.PipeState;
import dev.slimevr.vr.trackers.ShareableTracker;
import dev.slimevr.vr.trackers.TrackerPosition;
import dev.slimevr.vr.trackers.TrackerStatus;
import dev.slimevr.vr.trackers.VRTracker;
import io.eiren.util.collections.FastList;
import io.eiren.util.logging.LogManager;
public class WindowsSteamVRPipeInputBridge extends Thread implements Bridge {
private static final int MAX_COMMAND_LENGTH = 2048;
public static final String PipeName = "\\\\.\\pipe\\SlimeVRInput";
private static final int MAX_COMMAND_LENGTH = 2048;
private final byte[] buffArray = new byte[1024];
private final VRServer server;
private final StringBuilder commandBuilder = new StringBuilder(1024);
private final List<VRTracker> trackers = new FastList<>();
private final Map<Integer, VRTracker> trackersInternal = new HashMap<>();
private AtomicBoolean newData = new AtomicBoolean(false);
private final Vector3f vBuffer = new Vector3f();
private final Quaternion qBuffer = new Quaternion();
private final AtomicBoolean newData = new AtomicBoolean(false);
private WindowsPipe pipe;
public WindowsSteamVRPipeInputBridge(VRServer server) {
@@ -112,7 +109,7 @@ public class WindowsSteamVRPipeInputBridge extends Thread implements Bridge {
switch (command[0]) {
case "ADD": // Add new tracker
if (command.length < 4) {
LogManager.log.severe("[SteamVRPipeInputBridge] Error in ADD command. Command requires at least 4 arguments. Supplied: " + commandBuilder.toString());
LogManager.log.severe("[SteamVRPipeInputBridge] Error in ADD command. Command requires at least 4 arguments. Supplied: " + commandBuilder);
return;
}
VRTracker internalTracker = new VRTracker(Integer.parseInt(command[1]), StringUtils.join(command, " ", 3, command.length), true, true);
@@ -126,14 +123,14 @@ public class WindowsSteamVRPipeInputBridge extends Thread implements Bridge {
oldTracker = trackersInternal.put(internalTracker.getTrackerId(), internalTracker);
}
if (oldTracker != null) {
LogManager.log.severe("[SteamVRPipeInputBridge] New tracker added with the same id. Supplied: " + commandBuilder.toString());
LogManager.log.severe("[SteamVRPipeInputBridge] New tracker added with the same id. Supplied: " + commandBuilder);
return;
}
newData.set(true);
break;
case "UPD": // Update tracker data
if (command.length < 9) {
LogManager.log.severe("[SteamVRPipeInputBridge] Error in UPD command. Command requires at least 9 arguments. Supplied: " + commandBuilder.toString());
LogManager.log.severe("[SteamVRPipeInputBridge] Error in UPD command. Command requires at least 9 arguments. Supplied: " + commandBuilder);
return;
}
int id = Integer.parseInt(command[1]);
@@ -154,14 +151,14 @@ public class WindowsSteamVRPipeInputBridge extends Thread implements Bridge {
break;
case "STA": // Update tracker status
if (command.length < 3) {
LogManager.log.severe("[SteamVRPipeInputBridge] Error in STA command. Command requires at least 3 arguments. Supplied: " + commandBuilder.toString());
LogManager.log.severe("[SteamVRPipeInputBridge] Error in STA command. Command requires at least 3 arguments. Supplied: " + commandBuilder);
return;
}
id = Integer.parseInt(command[1]);
int status = Integer.parseInt(command[2]);
TrackerStatus st = TrackerStatus.getById(status);
if (st == null) {
LogManager.log.severe("[SteamVRPipeInputBridge] Unrecognized status id. Supplied: " + commandBuilder.toString());
LogManager.log.severe("[SteamVRPipeInputBridge] Unrecognized status id. Supplied: " + commandBuilder);
return;
}
internalTracker = trackersInternal.get(id);
@@ -264,6 +261,11 @@ public class WindowsSteamVRPipeInputBridge extends Thread implements Bridge {
}
@Override
public void startBridge() {
start();
}
public enum SteamVRInputRoles {
HEAD(TrackerPosition.HMD),
LEFT_HAND(TrackerPosition.LEFT_CONTROLLER),
@@ -283,13 +285,8 @@ public class WindowsSteamVRPipeInputBridge extends Thread implements Bridge {
private static final SteamVRInputRoles[] values = values();
public final TrackerPosition bodyPosition;
private SteamVRInputRoles(TrackerPosition slimeVrPosition) {
SteamVRInputRoles(TrackerPosition slimeVrPosition) {
this.bodyPosition = slimeVrPosition;
}
}
@Override
public void startBridge() {
start();
}
}

View File

@@ -11,16 +11,14 @@ import java.io.IOException;
public class BVHRecorder {
private static File bvhSaveDir = new File("BVH Recordings");
private PoseDataStream poseDataStream = null;
private static final File bvhSaveDir = new File("BVH Recordings");
private final ServerPoseStreamer poseStreamer;
private PoseDataStream poseDataStream = null;
public BVHRecorder(VRServer server) {
this.poseStreamer = new ServerPoseStreamer(server);
}
public void startRecording() {
File bvhFile = getBvhFile();
if (bvhFile != null) {
@@ -35,7 +33,6 @@ public class BVHRecorder {
}
}
public void endRecording() {
try {
@@ -47,7 +44,6 @@ public class BVHRecorder {
}
}
private File getBvhFile() {
if (bvhSaveDir.isDirectory() || bvhSaveDir.mkdirs()) {
File saveRecording;
@@ -64,7 +60,6 @@ public class BVHRecorder {
return null;
}
public boolean isRecording() {
return poseDataStream != null;
}

View File

@@ -1,20 +1,13 @@
package dev.slimevr.poserecorder;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import dev.slimevr.vr.trackers.TrackerPosition;
import io.eiren.util.collections.FastList;
import io.eiren.util.logging.LogManager;
import java.io.*;
public final class PoseFrameIO {
private PoseFrameIO() {

View File

@@ -1,14 +1,14 @@
package dev.slimevr.poserecorder;
import java.util.List;
import java.util.Map;
import dev.slimevr.VRServer;
import dev.slimevr.vr.processor.ComputedHumanPoseTracker;
import dev.slimevr.vr.processor.skeleton.SimpleSkeleton;
import dev.slimevr.vr.processor.skeleton.SkeletonConfigValue;
import dev.slimevr.vr.trackers.Tracker;
import java.util.List;
import java.util.Map;
public class PoseFrameSkeleton extends SimpleSkeleton {
private int frameCursor = 0;

View File

@@ -1,10 +1,7 @@
package dev.slimevr.poserecorder;
import java.util.Iterator;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import dev.slimevr.vr.trackers.Tracker;
import dev.slimevr.vr.trackers.TrackerConfig;
import dev.slimevr.vr.trackers.TrackerPosition;
@@ -12,13 +9,15 @@ import dev.slimevr.vr.trackers.TrackerStatus;
import dev.slimevr.vr.trackers.udp.Device;
import io.eiren.util.collections.FastList;
import java.util.Iterator;
public class PoseFrameTracker implements Tracker, Iterable<TrackerFrame> {
public final String name;
private final FastList<TrackerFrame> frames;
private int frameCursor = 0;
private final int trackerId = Tracker.getNextLocalTrackerId();
private int frameCursor = 0;
public PoseFrameTracker(String name, FastList<TrackerFrame> frames) {
if (frames == null) {

View File

@@ -1,13 +1,13 @@
package dev.slimevr.poserecorder;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import dev.slimevr.vr.trackers.TrackerPosition;
import dev.slimevr.vr.trackers.TrackerUtils;
import io.eiren.util.collections.FastList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
public final class PoseFrames implements Iterable<TrackerFrame[]> {
private final FastList<PoseFrameTracker> trackers;

View File

@@ -1,30 +1,26 @@
package dev.slimevr.poserecorder;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import org.apache.commons.lang3.tuple.Pair;
import dev.slimevr.VRServer;
import dev.slimevr.util.ann.VRServerThread;
import dev.slimevr.vr.trackers.Tracker;
import io.eiren.util.collections.FastList;
import io.eiren.util.logging.LogManager;
import org.apache.commons.lang3.tuple.Pair;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
public class PoseRecorder {
protected final VRServer server;
protected PoseFrames poseFrame = null;
protected int numFrames = -1;
protected int frameCursor = 0;
protected long frameRecordingInterval = 60L;
protected long nextFrameTimeMs = -1L;
protected CompletableFuture<PoseFrames> currentRecording;
protected final VRServer server;
FastList<Pair<Tracker, PoseFrameTracker>> trackers = new FastList<Pair<Tracker, PoseFrameTracker>>();
public PoseRecorder(VRServer server) {

View File

@@ -2,7 +2,6 @@ package dev.slimevr.poserecorder;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import dev.slimevr.vr.trackers.Tracker;
import dev.slimevr.vr.trackers.TrackerConfig;
import dev.slimevr.vr.trackers.TrackerPosition;
@@ -11,12 +10,11 @@ import dev.slimevr.vr.trackers.udp.Device;
public final class TrackerFrame implements Tracker {
private int dataFlags = 0;
public final TrackerPosition designation;
public final Quaternion rotation;
public final Vector3f position;
private final int trackerId = Tracker.getNextLocalTrackerId();
private int dataFlags = 0;
public TrackerFrame(TrackerPosition designation, Quaternion rotation, Vector3f position) {
this.designation = designation;

View File

@@ -1,32 +1,22 @@
package dev.slimevr.posestreamer;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Transform;
import com.jme3.math.Vector3f;
import org.apache.commons.lang3.StringUtils;
import dev.slimevr.vr.processor.TransformNode;
import dev.slimevr.vr.processor.skeleton.HumanSkeleton;
import org.apache.commons.lang3.StringUtils;
import java.io.*;
public class BVHFileStream extends PoseDataStream {
private static final int LONG_MAX_VALUE_DIGITS = Long.toString(Long.MAX_VALUE).length();
private static final float OFFSET_SCALE = 100f;
private static final float POSITION_SCALE = 100f;
private long frameCount = 0;
private final BufferedWriter writer;
private long frameCount = 0;
private long frameCountOffset;
private float[] angleBuf = new float[3];
@@ -106,7 +96,7 @@ public class BVHFileStream extends PoseDataStream {
if (level > 0 && node.wrappedNode.getParent() != null) {
Vector3f offset = node.localTransform.getTranslation();
float reverseMultiplier = node.hasReversedHierarchy() ? -1 : 1;
writer.write(nextIndentLevel + "OFFSET " + Float.toString(offset.getX() * OFFSET_SCALE * reverseMultiplier) + " " + Float.toString(offset.getY() * OFFSET_SCALE * reverseMultiplier) + " " + Float.toString(offset.getZ() * OFFSET_SCALE * reverseMultiplier) + "\n");
writer.write(nextIndentLevel + "OFFSET " + offset.getX() * OFFSET_SCALE * reverseMultiplier + " " + offset.getY() * OFFSET_SCALE * reverseMultiplier + " " + offset.getZ() * OFFSET_SCALE * reverseMultiplier + "\n");
} else {
writer.write(nextIndentLevel + "OFFSET 0.0 0.0 0.0\n");
}
@@ -217,7 +207,7 @@ public class BVHFileStream extends PoseDataStream {
angleBuf = quatToXyzAngles(rotBuf.normalizeLocal(), angleBuf);
// Output in order of roll (Z), pitch (X), yaw (Y) (extrinsic)
writer.write(Float.toString(angleBuf[0] * FastMath.RAD_TO_DEG) + " " + Float.toString(angleBuf[1] * FastMath.RAD_TO_DEG) + " " + Float.toString(angleBuf[2] * FastMath.RAD_TO_DEG));
writer.write(angleBuf[0] * FastMath.RAD_TO_DEG + " " + angleBuf[1] * FastMath.RAD_TO_DEG + " " + angleBuf[2] * FastMath.RAD_TO_DEG);
// Get inverse rotation for child local rotations
if (!node.children.isEmpty()) {
@@ -246,7 +236,7 @@ public class BVHFileStream extends PoseDataStream {
Vector3f rootPos = rootNode.worldTransform.getTranslation();
// Write root position
writer.write(Float.toString(rootPos.getX() * POSITION_SCALE) + " " + Float.toString(rootPos.getY() * POSITION_SCALE) + " " + Float.toString(rootPos.getZ() * POSITION_SCALE) + " ");
writer.write(rootPos.getX() * POSITION_SCALE + " " + rootPos.getY() * POSITION_SCALE + " " + rootPos.getZ() * POSITION_SCALE + " ");
writeNodeHierarchyRotation(rootNode, null);
writer.newLine();

View File

@@ -1,17 +1,13 @@
package dev.slimevr.posestreamer;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import dev.slimevr.vr.processor.skeleton.HumanSkeleton;
import java.io.*;
public abstract class PoseDataStream implements AutoCloseable {
protected boolean closed = false;
protected final OutputStream outputStream;
protected boolean closed = false;
protected PoseDataStream(OutputStream outputStream) {
this.outputStream = outputStream;

View File

@@ -1,14 +1,14 @@
package dev.slimevr.posestreamer;
import java.io.File;
import dev.slimevr.poserecorder.PoseFrameIO;
import dev.slimevr.poserecorder.PoseFrameSkeleton;
import dev.slimevr.poserecorder.PoseFrames;
import java.io.File;
public class PoseFrameStreamer extends PoseStreamer {
private PoseFrames frames;
private final PoseFrames frames;
public PoseFrameStreamer(String path) {
this(new File(path));

View File

@@ -1,10 +1,10 @@
package dev.slimevr.posestreamer;
import java.io.IOException;
import dev.slimevr.vr.processor.skeleton.HumanSkeleton;
import io.eiren.util.logging.LogManager;
import java.io.IOException;
public class PoseStreamer {
protected long frameRecordingInterval = 60L;
@@ -30,6 +30,10 @@ public class PoseStreamer {
}
}
public synchronized long getFrameInterval() {
return frameRecordingInterval;
}
public synchronized void setFrameInterval(long intervalMs) {
if (intervalMs < 1) {
throw new IllegalArgumentException("intervalMs must at least have a value of 1");
@@ -38,19 +42,10 @@ public class PoseStreamer {
this.frameRecordingInterval = intervalMs;
}
public synchronized long getFrameInterval() {
return frameRecordingInterval;
}
public synchronized HumanSkeleton getSkeleton() {
return skeleton;
}
public synchronized void setOutput(PoseDataStream poseFileStream) throws IOException {
poseFileStream.writeHeader(skeleton, this);
this.poseFileStream = poseFileStream;
}
public synchronized void setOutput(PoseDataStream poseFileStream, long intervalMs) throws IOException {
setFrameInterval(intervalMs);
setOutput(poseFileStream);
@@ -60,6 +55,11 @@ public class PoseStreamer {
return poseFileStream;
}
public synchronized void setOutput(PoseDataStream poseFileStream) throws IOException {
poseFileStream.writeHeader(skeleton, this);
this.poseFileStream = poseFileStream;
}
public synchronized void closeOutput() throws IOException {
PoseDataStream poseFileStream = this.poseFileStream;

View File

@@ -1,6 +1,5 @@
package dev.slimevr.posestreamer;
import dev.slimevr.VRServer;
import dev.slimevr.util.ann.VRServerThread;
import dev.slimevr.vr.processor.skeleton.HumanSkeleton;

View File

@@ -1,11 +1,11 @@
package dev.slimevr.posestreamer;
import dev.slimevr.vr.processor.TransformNode;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.OutputStream;
import dev.slimevr.vr.processor.TransformNode;
public class StdBVHFileStream extends BVHFileStream {
public StdBVHFileStream(OutputStream outputStream) {

View File

@@ -1,9 +1,9 @@
package dev.slimevr.posestreamer;
import java.io.IOException;
import dev.slimevr.vr.processor.skeleton.HumanSkeleton;
import java.io.IOException;
public class TickPoseStreamer extends PoseStreamer {
protected long nextFrameTimeMs = -1L;

View File

@@ -1,26 +1,21 @@
package dev.slimevr.posestreamer;
import java.util.List;
import com.jme3.math.Quaternion;
import com.jme3.math.Transform;
import dev.slimevr.vr.processor.TransformNode;
import io.eiren.util.collections.FastList;
import java.util.List;
public class TransformNodeWrapper {
public final TransformNode wrappedNode;
protected String name;
public final Transform localTransform;
public final Transform worldTransform;
private boolean reversedHierarchy = false;
protected TransformNodeWrapper parent;
public final List<TransformNodeWrapper> children;
protected String name;
protected TransformNodeWrapper parent;
private boolean reversedHierarchy = false;
public TransformNodeWrapper(TransformNode nodeToWrap, String name, boolean reversedHierarchy, int initialChildCapacity) {
this.wrappedNode = nodeToWrap;

View File

@@ -9,8 +9,12 @@ import dev.slimevr.vr.trackers.udp.Device;
import solarxr_protocol.data_feed.DataFeedUpdate;
import solarxr_protocol.data_feed.device_data.DeviceData;
import solarxr_protocol.data_feed.device_data.DeviceDataMaskT;
import solarxr_protocol.data_feed.tracker.*;
import solarxr_protocol.datatypes.*;
import solarxr_protocol.data_feed.tracker.TrackerData;
import solarxr_protocol.data_feed.tracker.TrackerDataMaskT;
import solarxr_protocol.data_feed.tracker.TrackerInfo;
import solarxr_protocol.datatypes.DeviceId;
import solarxr_protocol.datatypes.Temperature;
import solarxr_protocol.datatypes.TrackerId;
import solarxr_protocol.datatypes.hardware_info.HardwareInfo;
import solarxr_protocol.datatypes.hardware_info.HardwareStatus;
import solarxr_protocol.datatypes.math.Quat;

View File

@@ -5,11 +5,9 @@ import java.util.UUID;
public interface GenericConnection {
UUID getConnectionId();
ConnectionContext getContext();
void send(ByteBuffer bytes);
}

View File

@@ -5,5 +5,4 @@ import java.util.Map;
public interface ProtocolAPIServer {
Map<Integer, GenericConnection> getAPIConnections();
}

View File

@@ -8,7 +8,6 @@ import solarxr_protocol.rpc.SkeletonPart;
public class RPCBuilder {
public static int createSkeletonConfig(FlatBufferBuilder fbb, HumanPoseProcessor humanPoseProcessor) {
int[] partsOffsets = new int[SkeletonConfigValue.values().length];
@@ -18,9 +17,7 @@ public class RPCBuilder {
partsOffsets[index] = part;
}
int parts = SkeletonConfigResponse.createSkeletonPartsVector(fbb, partsOffsets);
return SkeletonConfigResponse.createSkeletonConfigResponse(fbb, parts);
}
}

View File

@@ -42,7 +42,6 @@ public class RPCHandler extends ProtocolHandler<RpcMessageHeader> implements Ser
this.api.server.getSerialHandler().addListener(this);
}
public void onSetWifiRequest(GenericConnection conn, RpcMessageHeader messageHeader) {
SetWifiRequest req = (SetWifiRequest) messageHeader.message(new SetWifiRequest());
if (req == null) return;
@@ -86,7 +85,6 @@ public class RPCHandler extends ProtocolHandler<RpcMessageHeader> implements Ser
conn.send(fbb.dataBuffer());
}
public void onSkeletonResetAllRequest(GenericConnection conn, RpcMessageHeader messageHeader) {
SkeletonResetAllRequest req = (SkeletonResetAllRequest) messageHeader.message(new SkeletonResetAllRequest());
if (req == null) return;
@@ -94,7 +92,6 @@ public class RPCHandler extends ProtocolHandler<RpcMessageHeader> implements Ser
this.api.server.humanPoseProcessor.getSkeletonConfig().resetConfigs();
this.api.server.saveConfig();
// might not be a good idea maybe let the client ask again
FlatBufferBuilder fbb = new FlatBufferBuilder(300);
int config = RPCBuilder.createSkeletonConfig(fbb, this.api.server.humanPoseProcessor);
@@ -103,7 +100,6 @@ public class RPCHandler extends ProtocolHandler<RpcMessageHeader> implements Ser
conn.send(fbb.dataBuffer());
}
public void onSkeletonConfigRequest(GenericConnection conn, RpcMessageHeader messageHeader) {
SkeletonConfigRequest req = (SkeletonConfigRequest) messageHeader.message(new SkeletonConfigRequest());
if (req == null) return;
@@ -232,7 +228,6 @@ public class RPCHandler extends ProtocolHandler<RpcMessageHeader> implements Ser
}
}
@Override
public void onMessage(GenericConnection conn, RpcMessageHeader message) {
BiConsumer<GenericConnection, RpcMessageHeader> consumer = this.handlers[message.messageType()];
@@ -245,7 +240,6 @@ public class RPCHandler extends ProtocolHandler<RpcMessageHeader> implements Ser
public int createRPCMessage(FlatBufferBuilder fbb, byte messageType, int messageOffset) {
int[] data = new int[1];
RpcMessageHeader.startRpcMessageHeader(fbb);
RpcMessageHeader.addMessage(fbb, messageOffset);
RpcMessageHeader.addMessageType(fbb, messageType);

View File

@@ -4,15 +4,18 @@ import com.fazecast.jSerialComm.SerialPort;
import com.fazecast.jSerialComm.SerialPortEvent;
import com.fazecast.jSerialComm.SerialPortMessageListener;
import java.io.*;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
public class SerialHandler implements SerialPortMessageListener {
private SerialPort trackerPort = null;
private List<SerialListener> listeners = new ArrayList<>();
private final List<SerialListener> listeners = new ArrayList<>();
public void addListener(SerialListener channel) {
this.listeners.add(channel);
@@ -22,7 +25,6 @@ public class SerialHandler implements SerialPortMessageListener {
listeners.removeIf(listener -> l == listener);
}
public boolean openSerial() {
if (this.isConnected()) {
return true;
@@ -57,7 +59,6 @@ public class SerialHandler implements SerialPortMessageListener {
trackerPort = null;
}
public void setWifi(String ssid, String passwd) {
if (trackerPort == null)
return;
@@ -67,7 +68,7 @@ public class SerialHandler implements SerialPortMessageListener {
writer.append("SET WIFI \"" + ssid + "\" \"" + passwd + "\"\n");
writer.flush();
} catch (IOException e) {
addLog(e.toString() + "\n");
addLog(e + "\n");
e.printStackTrace();
}
}

View File

@@ -4,10 +4,9 @@ import com.fazecast.jSerialComm.SerialPort;
public interface SerialListener {
public void onSerialConnected(SerialPort port);
void onSerialConnected(SerialPort port);
public void onSerialDisconnected();
public void onSerialLog(String str);
void onSerialDisconnected();
void onSerialLog(String str);
}

View File

@@ -11,5 +11,5 @@ public enum ComputedHumanPoseTrackerPosition {
LEFT_ELBOW,
RIGHT_ELBOW,
LEFT_HAND,
RIGHT_HAND;
RIGHT_HAND
}

View File

@@ -1,22 +1,18 @@
package dev.slimevr.vr.processor;
import java.util.List;
import java.util.function.Consumer;
import dev.slimevr.VRServer;
import dev.slimevr.util.ann.VRServerThread;
import dev.slimevr.vr.processor.skeleton.HumanSkeleton;
import dev.slimevr.vr.processor.skeleton.SimpleSkeleton;
import dev.slimevr.vr.processor.skeleton.SkeletonConfig;
import dev.slimevr.vr.processor.skeleton.SkeletonConfigValue;
import dev.slimevr.vr.trackers.HMDTracker;
import dev.slimevr.vr.trackers.ShareableTracker;
import dev.slimevr.vr.trackers.Tracker;
import dev.slimevr.vr.trackers.TrackerRole;
import dev.slimevr.vr.trackers.TrackerStatus;
import dev.slimevr.vr.trackers.*;
import io.eiren.util.ann.ThreadSafe;
import io.eiren.util.collections.FastList;
import java.util.List;
import java.util.function.Consumer;
public class HumanPoseProcessor {
private final VRServer server;

View File

@@ -1,12 +1,11 @@
package dev.slimevr.vr.processor;
import com.jme3.math.Transform;
import io.eiren.util.collections.FastList;
import java.util.List;
import java.util.function.Consumer;
import com.jme3.math.Transform;
import io.eiren.util.collections.FastList;
public class TransformNode {
public final Transform localTransform = new Transform();

View File

@@ -1,26 +1,22 @@
package dev.slimevr.vr.processor.skeleton;
import java.util.List;
import java.util.Map;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import dev.slimevr.VRServer;
import dev.slimevr.util.ann.VRServerThread;
import dev.slimevr.vr.processor.ComputedHumanPoseTracker;
import dev.slimevr.vr.processor.ComputedHumanPoseTrackerPosition;
import dev.slimevr.vr.processor.TransformNode;
import dev.slimevr.vr.trackers.Tracker;
import dev.slimevr.vr.trackers.TrackerPosition;
import dev.slimevr.vr.trackers.TrackerRole;
import dev.slimevr.vr.trackers.TrackerStatus;
import dev.slimevr.vr.trackers.TrackerUtils;
import dev.slimevr.vr.trackers.*;
import io.eiren.util.collections.FastList;
import java.util.List;
import java.util.Map;
public class SimpleSkeleton extends HumanSkeleton implements SkeletonConfigCallback {
public final SkeletonConfig skeletonConfig;
//#region Upper body nodes (torso)
protected final TransformNode hmdNode = new TransformNode("HMD", false);
protected final TransformNode headNode = new TransformNode("Head", false);
@@ -29,9 +25,8 @@ public class SimpleSkeleton extends HumanSkeleton implements SkeletonConfigCallb
protected final TransformNode trackerChestNode = new TransformNode("Chest-Tracker", false);
protected final TransformNode waistNode = new TransformNode("Waist", false);
protected final TransformNode hipNode = new TransformNode("Hip", false);
protected final TransformNode trackerWaistNode = new TransformNode("Waist-Tracker", false);
//#endregion
protected final TransformNode trackerWaistNode = new TransformNode("Waist-Tracker", false);
//#region Lower body nodes (legs)
protected final TransformNode leftHipNode = new TransformNode("Left-Hip", false);
protected final TransformNode leftKneeNode = new TransformNode("Left-Knee", false);
@@ -39,34 +34,26 @@ public class SimpleSkeleton extends HumanSkeleton implements SkeletonConfigCallb
protected final TransformNode leftAnkleNode = new TransformNode("Left-Ankle", false);
protected final TransformNode leftFootNode = new TransformNode("Left-Foot", false);
protected final TransformNode trackerLeftFootNode = new TransformNode("Left-Foot-Tracker", false);
protected final TransformNode rightHipNode = new TransformNode("Right-Hip", false);
protected final TransformNode rightKneeNode = new TransformNode("Right-Knee", false);
protected final TransformNode trackerRightKneeNode = new TransformNode("Right-Knee-Tracker", false);
protected final TransformNode rightAnkleNode = new TransformNode("Right-Ankle", false);
protected final TransformNode rightFootNode = new TransformNode("Right-Foot", false);
protected final TransformNode trackerRightFootNode = new TransformNode("Right-Foot-Tracker", false);
protected float minKneePitch = 0f * FastMath.DEG_TO_RAD;
protected float maxKneePitch = 90f * FastMath.DEG_TO_RAD;
protected float kneeLerpFactor = 0.5f;
//#endregion
//#region Arms (from controllers)
protected final TransformNode leftControllerNodeContrl = new TransformNode("Left-Controller-Contrl", false);
protected final TransformNode rightControllerNodeContrl = new TransformNode("Right-Controller-Contrl", false);
//#endregion
protected final TransformNode leftWristNodeContrl = new TransformNode("Left-Wrist-Contrl", false);
protected final TransformNode rightWristNodeContrl = new TransformNode("Right-Wrist-Contrl", false);
protected final TransformNode leftElbowNodeContrl = new TransformNode("Left-Elbow-Contrl", false);
protected final TransformNode rightElbowNodeContrl = new TransformNode("Right-Elbow-Contrl", false);
protected final TransformNode trackerLeftElbowNodeContrl = new TransformNode("Left-Elbow-Tracker-Contrl", false);
protected final TransformNode trackerRightElbowNodeContrl = new TransformNode("Right-Elbow-Tracker-Contrl", false);
//#endregion
//#region Arms (from HMD)
protected final TransformNode leftShoulderNodeHmd = new TransformNode("Left-Shoulder-Hmd", false);
protected final TransformNode rightShoulderNodeHmd = new TransformNode("Right-Shoulder-Hmd", false);
//#endregion
protected final TransformNode leftElbowNodeHmd = new TransformNode("Left-Elbow-Hmd", false);
protected final TransformNode rightElbowNodeHmd = new TransformNode("Right-Elbow-Hmd", false);
protected final TransformNode trackerLeftElbowNodeHmd = new TransformNode("Left-Elbow-Tracker-Hmd", false);
@@ -77,66 +64,52 @@ public class SimpleSkeleton extends HumanSkeleton implements SkeletonConfigCallb
protected final TransformNode rightHandNodeHmd = new TransformNode("Right-Hand-Hmd", false);
protected final TransformNode trackerLeftHandNodeHmd = new TransformNode("Left-Hand-Tracker-Hmd", false);
protected final TransformNode trackerRightHandNodeHmd = new TransformNode("Right-Hand-Tracker-Hmd", false);
protected final Vector3f hipVector = new Vector3f();
protected final Vector3f ankleVector = new Vector3f();
//#endregion
protected final Quaternion kneeRotation = new Quaternion();
protected float minKneePitch = 0f * FastMath.DEG_TO_RAD;
protected float maxKneePitch = 90f * FastMath.DEG_TO_RAD;
protected float kneeLerpFactor = 0.5f;
//#region Tracker Input
protected Tracker hmdTracker;
protected Tracker neckTracker;
protected Tracker chestTracker;
protected Tracker waistTracker;
protected Tracker hipTracker;
protected Tracker leftKneeTracker;
protected Tracker leftAnkleTracker;
protected Tracker leftFootTracker;
protected Tracker rightKneeTracker;
protected Tracker rightAnkleTracker;
protected Tracker rightFootTracker;
protected Tracker leftControllerTracker;
protected Tracker rightControllerTracker;
protected Tracker leftForearmTracker;
protected Tracker rightForearmTracker;
//#endregion
protected Tracker leftUpperArmTracker;
protected Tracker rightUpperArmTracker;
protected Tracker leftHandTracker;
protected Tracker rightHandTracker;
//#endregion
//#region Tracker Output
protected ComputedHumanPoseTracker computedChestTracker;
protected ComputedHumanPoseTracker computedWaistTracker;
protected ComputedHumanPoseTracker computedLeftKneeTracker;
protected ComputedHumanPoseTracker computedLeftFootTracker;
protected ComputedHumanPoseTracker computedRightKneeTracker;
protected ComputedHumanPoseTracker computedRightFootTracker;
//#endregion
protected ComputedHumanPoseTracker computedLeftElbowTracker;
protected ComputedHumanPoseTracker computedRightElbowTracker;
protected ComputedHumanPoseTracker computedLeftHandTracker;
protected ComputedHumanPoseTracker computedRightHandTracker;
//#endregion
protected boolean extendedPelvisModel = true;
protected boolean extendedKneeModel = false;
public final SkeletonConfig skeletonConfig;
//#region Buffers
private Vector3f posBuf = new Vector3f();
private final Vector3f posBuf = new Vector3f();
private Quaternion rotBuf1 = new Quaternion();
private Quaternion rotBuf2 = new Quaternion();
protected final Vector3f hipVector = new Vector3f();
protected final Vector3f ankleVector = new Vector3f();
protected final Quaternion kneeRotation = new Quaternion();
private final Quaternion rotBuf2 = new Quaternion();
private boolean hasSpineTracker, hasKneeTracker;
//#endregion
@@ -247,6 +220,23 @@ public class SimpleSkeleton extends HumanSkeleton implements SkeletonConfigCallb
}
//#endregion
public static float normalizeRad(float angle) {
return FastMath.normalize(angle, -FastMath.PI, FastMath.PI);
}
public static float interpolateRadians(float factor, float start, float end) {
float angle = FastMath.abs(end - start);
if (angle > FastMath.PI) {
if (end > start) {
start += FastMath.TWO_PI;
} else {
end += FastMath.TWO_PI;
}
}
float val = start + (end - start) * factor;
return normalizeRad(val);
}
//#region Set Trackers
public void setTrackersFromList(List<? extends Tracker> trackers, boolean setHmd) {
if (setHmd) {
@@ -329,11 +319,13 @@ public class SimpleSkeleton extends HumanSkeleton implements SkeletonConfigCallb
setComputedTracker(trackers.get(i));
}
}
//#endregion
public void setComputedTrackersAndFillNull(List<? extends ComputedHumanPoseTracker> trackers, boolean onlyFillWaistAndFeet) {
setComputedTrackers(trackers);
fillNullComputedTrackers(onlyFillWaistAndFeet);
}
//#endregion
public void fillNullComputedTrackers(boolean onlyFillWaistAndFeet) {
if (computedWaistTracker == null) {
@@ -386,7 +378,6 @@ public class SimpleSkeleton extends HumanSkeleton implements SkeletonConfigCallb
}
}
}
//#endregion
//#region Get Trackers
public ComputedHumanPoseTracker getComputedTracker(TrackerRole trackerRole) {
@@ -419,7 +410,6 @@ public class SimpleSkeleton extends HumanSkeleton implements SkeletonConfigCallb
return null;
}
//#endregion
//#region Processing
// Useful for sub-classes that need to return a sub-tracker (like PoseFrameTracker -> TrackerFrame)
@@ -435,6 +425,7 @@ public class SimpleSkeleton extends HumanSkeleton implements SkeletonConfigCallb
updateRootTrackers();
updateComputedTrackers();
}
//#endregion
void updateRootTrackers() {
hmdNode.update();
@@ -630,7 +621,6 @@ public class SimpleSkeleton extends HumanSkeleton implements SkeletonConfigCallb
}
}
}
//#endregion
//#region Knee Model
// Knee basically has only 1 DoF (pitch), average yaw and roll between knee and hip
@@ -652,23 +642,6 @@ public class SimpleSkeleton extends HumanSkeleton implements SkeletonConfigCallb
// Return knee angle into knee rotation
kneeBuf.multLocal(kneeRotation);
}
public static float normalizeRad(float angle) {
return FastMath.normalize(angle, -FastMath.PI, FastMath.PI);
}
public static float interpolateRadians(float factor, float start, float end) {
float angle = FastMath.abs(end - start);
if (angle > FastMath.PI) {
if (end > start) {
start += FastMath.TWO_PI;
} else {
end += FastMath.TWO_PI;
}
}
float val = start + (end - start) * factor;
return normalizeRad(val);
}
//#endregion
//#region Update the output trackers

View File

@@ -1,13 +1,12 @@
package dev.slimevr.vr.processor.skeleton;
import com.jme3.math.Vector3f;
import io.eiren.util.logging.LogManager;
import io.eiren.yaml.YamlFile;
import java.util.EnumMap;
import java.util.Map;
import com.jme3.math.Vector3f;
import io.eiren.util.logging.LogManager;
import io.eiren.yaml.YamlFile;
public class SkeletonConfig {
protected final EnumMap<SkeletonConfigValue, Float> configs = new EnumMap<SkeletonConfigValue, Float>(SkeletonConfigValue.class);
@@ -63,6 +62,35 @@ public class SkeletonConfig {
this(skeletonConfig, autoUpdateOffsets, null);
}
//#region Cast utilities for config reading
private static Float castFloat(Object o) {
if (o == null) {
return null;
} else if (o instanceof Float) {
return (Float) o;
} else if (o instanceof Double) {
return ((Double) o).floatValue();
} else if (o instanceof Byte) {
return (float) (Byte) o;
} else if (o instanceof Integer) {
return (float) (Integer) o;
} else if (o instanceof Long) {
return (float) (Long) o;
} else {
return null;
}
}
private static Boolean castBoolean(Object o) {
if (o == null) {
return null;
} else if (o instanceof Boolean) {
return (Boolean) o;
} else {
return null;
}
}
private void callCallbackOnAll(boolean defaultOnly) {
if (callback == null) {
return;
@@ -324,35 +352,6 @@ public class SkeletonConfig {
public void setConfigs(SkeletonConfig skeletonConfig) {
setConfigs(skeletonConfig.configs, skeletonConfig.toggles);
}
//#region Cast utilities for config reading
private static Float castFloat(Object o) {
if (o == null) {
return null;
} else if (o instanceof Float) {
return (Float) o;
} else if (o instanceof Double) {
return ((Double) o).floatValue();
} else if (o instanceof Byte) {
return (float) (Byte) o;
} else if (o instanceof Integer) {
return (float) (Integer) o;
} else if (o instanceof Long) {
return (float) (Long) o;
} else {
return null;
}
}
private static Boolean castBoolean(Object o) {
if (o == null) {
return null;
} else if (o instanceof Boolean) {
return (Boolean) o;
} else {
return null;
}
}
//#endregion
public void loadFromConfig(YamlFile config) {

View File

@@ -4,9 +4,9 @@ import com.jme3.math.Vector3f;
public interface SkeletonConfigCallback {
public void updateConfigState(SkeletonConfigValue config, float newValue);
void updateConfigState(SkeletonConfigValue config, float newValue);
public void updateToggleState(SkeletonConfigToggle configToggle, boolean newValue);
void updateToggleState(SkeletonConfigToggle configToggle, boolean newValue);
public void updateNodeOffset(SkeletonNodeOffset nodeOffset, Vector3f offset);
void updateNodeOffset(SkeletonNodeOffset nodeOffset, Vector3f offset);
}

View File

@@ -9,17 +9,21 @@ public enum SkeletonConfigToggle {
EXTENDED_KNEE_MODEL("Extended knee model", "extendedKnee", false),
;
public static final SkeletonConfigToggle[] values = values();
private static final String CONFIG_PREFIX = "body.model.";
private static final Map<String, SkeletonConfigToggle> byStringVal = new HashMap<>();
static {
for (SkeletonConfigToggle configVal : values()) {
byStringVal.put(configVal.stringVal.toLowerCase(), configVal);
}
}
public final String stringVal;
public final String configKey;
public final boolean defaultValue;
public static final SkeletonConfigToggle[] values = values();
private static final Map<String, SkeletonConfigToggle> byStringVal = new HashMap<>();
private SkeletonConfigToggle(String stringVal, String configKey, boolean defaultValue) {
SkeletonConfigToggle(String stringVal, String configKey, boolean defaultValue) {
this.stringVal = stringVal;
this.configKey = CONFIG_PREFIX + configKey;
@@ -29,10 +33,4 @@ public enum SkeletonConfigToggle {
public static SkeletonConfigToggle getByStringValue(String stringVal) {
return stringVal == null ? null : byStringVal.get(stringVal.toLowerCase());
}
static {
for (SkeletonConfigToggle configVal : values()) {
byStringVal.put(configVal.stringVal.toLowerCase(), configVal);
}
}
}

View File

@@ -25,22 +25,26 @@ public enum SkeletonConfigValue {
ELBOW_OFFSET(19, "Elbow offset", "elbowOffset", "Elbow offset", 0f, new SkeletonNodeOffset[]{SkeletonNodeOffset.ELBOW_TRACKER}),
;
public static final SkeletonConfigValue[] values = values();
private static final String CONFIG_PREFIX = "body.";
private static final Map<String, SkeletonConfigValue> byStringVal = new HashMap<>();
private static final Map<Number, SkeletonConfigValue> byIdVal = new HashMap<>();
static {
for (SkeletonConfigValue configVal : values()) {
byIdVal.put(configVal.id, configVal);
byStringVal.put(configVal.stringVal.toLowerCase(), configVal);
}
}
public final int id;
public final String stringVal;
public final String configKey;
public final String label;
public final float defaultValue;
public final SkeletonNodeOffset[] affectedOffsets;
public static final SkeletonConfigValue[] values = values();
private static final Map<String, SkeletonConfigValue> byStringVal = new HashMap<>();
private static final Map<Number, SkeletonConfigValue> byIdVal = new HashMap<>();
private SkeletonConfigValue(int id, String stringVal, String configKey, String label, float defaultValue, SkeletonNodeOffset[] affectedOffsets) {
SkeletonConfigValue(int id, String stringVal, String configKey, String label, float defaultValue, SkeletonNodeOffset[] affectedOffsets) {
this.id = id;
this.stringVal = stringVal;
this.configKey = CONFIG_PREFIX + configKey;
@@ -58,11 +62,4 @@ public enum SkeletonConfigValue {
public static SkeletonConfigValue getById(int id) {
return byIdVal.get(id);
}
static {
for (SkeletonConfigValue configVal : values()) {
byIdVal.put(configVal.id, configVal);
byStringVal.put(configVal.stringVal.toLowerCase(), configVal);
}
}
}

View File

@@ -4,9 +4,9 @@ import java.util.function.Consumer;
public interface CalibratingTracker {
public void startCalibration(Consumer<String> calibrationDataConsumer);
void startCalibration(Consumer<String> calibrationDataConsumer);
public void requestCalibrationData(Consumer<String> calibrationDataConsumer);
void requestCalibrationData(Consumer<String> calibrationDataConsumer);
public void uploadNewClibrationData();
void uploadNewClibrationData();
}

View File

@@ -1,10 +1,6 @@
package dev.slimevr.vr.trackers;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.RandomAccess;
import java.util.*;
/**
* If you use this code, please consider notifying isak at du-preez dot com
@@ -27,7 +23,7 @@ public class CircularArrayList<E>
public CircularArrayList(int capacity) {
n = capacity + 1;
buf = new ArrayList<E>(Collections.nCopies(n, (E) null));
buf = new ArrayList<E>(Collections.nCopies(n, null));
}
public int capacity() {

View File

@@ -10,11 +10,11 @@ public class ComputedTracker implements Tracker, TrackerWithTPS {
public final Quaternion rotation = new Quaternion();
protected final String name;
protected final String serial;
protected TrackerStatus status = TrackerStatus.DISCONNECTED;
public TrackerPosition bodyPosition = null;
protected final boolean hasRotation;
protected final boolean hasPosition;
protected final int trackerId;
public TrackerPosition bodyPosition = null;
protected TrackerStatus status = TrackerStatus.DISCONNECTED;
public ComputedTracker(int trackerId, String serial, String name, boolean hasRotation, boolean hasPosition) {
this.name = name;
@@ -133,7 +133,6 @@ public class ComputedTracker implements Tracker, TrackerWithTPS {
return this.trackerId;
}
@Override
public int getTrackerNum() {
return -1;

View File

@@ -5,5 +5,4 @@ public enum DeviceType {
CONTROLLER,
TRACKER,
TRACKING_REFERENCE,
;
}

View File

@@ -3,7 +3,6 @@ package dev.slimevr.vr.trackers;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import dev.slimevr.VRServer;
import dev.slimevr.vr.trackers.udp.Device;
import dev.slimevr.vr.trackers.udp.TrackersUDPServer;
@@ -19,36 +18,33 @@ public class IMUTracker implements Tracker, TrackerWithTPS, TrackerWithBattery {
public final Quaternion rotQuaternion = new Quaternion();
public final Quaternion rotMagQuaternion = new Quaternion();
public final Quaternion rotAdjust = new Quaternion();
public final Device device;
public final int trackerNum;
protected final Quaternion correction = new Quaternion();
protected CircularArrayList<Quaternion> previousRots;
private final Quaternion buffQuat = new Quaternion();
public int movementFilterTickCount = 0;
public float movementFilterAmount = 1f;
protected Quaternion mounting = null;
protected TrackerStatus status = TrackerStatus.OK;
protected final int trackerId;
protected final String name;
protected final String descriptiveName;
protected final TrackersUDPServer server;
protected final VRServer vrserver;
protected float confidence = 0;
protected float batteryVoltage = 0;
protected float batteryLevel = 0;
private final Quaternion buffQuat = new Quaternion();
public int movementFilterTickCount = 0;
public float movementFilterAmount = 1f;
public int calibrationStatus = 0;
public int magCalibrationStatus = 0;
public float magnetometerAccuracy = 0;
protected boolean magentometerCalibrated = false;
public boolean hasNewCorrectionData = false;
protected BufferedTimer timer = new BufferedTimer(1f);
public int ping = -1;
public int signalStrength = -1;
public float temperature = 0;
public final Device device;
public final int trackerNum;
public TrackerPosition bodyPosition = null;
protected CircularArrayList<Quaternion> previousRots;
protected Quaternion mounting = null;
protected TrackerStatus status = TrackerStatus.OK;
protected float confidence = 0;
protected float batteryVoltage = 0;
protected float batteryLevel = 0;
protected boolean magentometerCalibrated = false;
protected BufferedTimer timer = new BufferedTimer(1f);
public IMUTracker(Device device, int trackerId, int trackerNum, String name, String descriptiveName, TrackersUDPServer server, VRServer vrserver) {
this.device = device;
@@ -201,15 +197,15 @@ public class IMUTracker implements Tracker, TrackerWithTPS, TrackerWithBattery {
return batteryLevel;
}
public void setBatteryLevel(float level) {
this.batteryLevel = level;
}
@Override
public float getBatteryVoltage() {
return batteryVoltage;
}
public void setBatteryLevel(float level) {
this.batteryLevel = level;
}
public void setBatteryVoltage(float voltage) {
this.batteryVoltage = voltage;
}
@@ -302,9 +298,15 @@ public class IMUTracker implements Tracker, TrackerWithTPS, TrackerWithBattery {
;
private static final CalibrationAccuracy[] byStatus = new CalibrationAccuracy[4];
static {
for (CalibrationAccuracy ca : values())
byStatus[ca.status] = ca;
}
public final int status;
private CalibrationAccuracy(int status) {
CalibrationAccuracy(int status) {
this.status = status;
}
@@ -313,10 +315,5 @@ public class IMUTracker implements Tracker, TrackerWithTPS, TrackerWithBattery {
return null;
return byStatus[status];
}
static {
for (CalibrationAccuracy ca : values())
byStatus[ca.status] = ca;
}
}
}

View File

@@ -1,11 +1,11 @@
package dev.slimevr.vr.trackers;
import java.nio.ByteBuffer;
import dev.slimevr.VRServer;
import dev.slimevr.vr.trackers.udp.Device;
import dev.slimevr.vr.trackers.udp.TrackersUDPServer;
import java.nio.ByteBuffer;
public class MPUTracker extends IMUTracker {
public ConfigurationData newCalibrationData;

View File

@@ -16,6 +16,6 @@ public class SensorTap {
public enum TapAxis {
X,
Y,
Z;
Z
}
}

View File

@@ -2,5 +2,5 @@ package dev.slimevr.vr.trackers;
public interface ShareableTracker extends Tracker {
public TrackerRole getTrackerRole();
TrackerRole getTrackerRole();
}

View File

@@ -1,58 +1,58 @@
package dev.slimevr.vr.trackers;
import java.util.concurrent.atomic.AtomicInteger;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import dev.slimevr.vr.trackers.udp.Device;
import java.util.concurrent.atomic.AtomicInteger;
public interface Tracker {
public static final AtomicInteger nextLocalTrackerId = new AtomicInteger();
AtomicInteger nextLocalTrackerId = new AtomicInteger();
public boolean getPosition(Vector3f store);
public boolean getRotation(Quaternion store);
public String getName();
public TrackerStatus getStatus();
public void loadConfig(TrackerConfig config);
public void saveConfig(TrackerConfig config);
public float getConfidenceLevel();
public void resetFull(Quaternion reference);
public void resetYaw(Quaternion reference);
public void tick();
public TrackerPosition getBodyPosition();
public void setBodyPosition(TrackerPosition position);
public boolean userEditable();
public boolean hasRotation();
public boolean hasPosition();
public boolean isComputed();
public int getTrackerId();
public int getTrackerNum();
public Device getDevice();
public default String getDescriptiveName() {
return getName();
}
public static int getNextLocalTrackerId() {
static int getNextLocalTrackerId() {
return nextLocalTrackerId.incrementAndGet();
}
boolean getPosition(Vector3f store);
boolean getRotation(Quaternion store);
String getName();
TrackerStatus getStatus();
void loadConfig(TrackerConfig config);
void saveConfig(TrackerConfig config);
float getConfidenceLevel();
void resetFull(Quaternion reference);
void resetYaw(Quaternion reference);
void tick();
TrackerPosition getBodyPosition();
void setBodyPosition(TrackerPosition position);
boolean userEditable();
boolean hasRotation();
boolean hasPosition();
boolean isComputed();
int getTrackerId();
int getTrackerNum();
Device getDevice();
default String getDescriptiveName() {
return getName();
}
}

View File

@@ -1,7 +1,6 @@
package dev.slimevr.vr.trackers;
import com.jme3.math.Quaternion;
import io.eiren.yaml.YamlNode;
public class TrackerConfig {

View File

@@ -10,9 +10,8 @@ public enum TrackerMountingRotation {
BACK(0),
RIGHT(-90);
public final Quaternion quaternion;
public static final TrackerMountingRotation[] values = values();
public final Quaternion quaternion;
TrackerMountingRotation(float angle) {
this.quaternion = new Quaternion().fromAngles(0, angle * FastMath.DEG_TO_RAD, 0);
@@ -25,5 +24,4 @@ public enum TrackerMountingRotation {
}
return null;
}
}

View File

@@ -28,16 +28,29 @@ public enum TrackerPosition {
RIGHT_HAND(19, "body:right_hand", TrackerRole.RIGHT_HAND),
;
public final int id;
public final String designation;
public final TrackerRole trackerRole;
public static final TrackerPosition[] values = values();
private static final Map<Integer, TrackerPosition> byId = new HashMap<>();
private static final Map<String, TrackerPosition> byDesignation = new HashMap<>();
private static final EnumMap<TrackerRole, TrackerPosition> byRole = new EnumMap<>(TrackerRole.class);
private TrackerPosition(int id, String designation, TrackerRole trackerRole) {
static {
for (TrackerPosition tbp : values()) {
byDesignation.put(tbp.designation.toLowerCase(), tbp);
byId.put(tbp.id, tbp);
if (tbp.trackerRole != null) {
TrackerPosition old = byRole.get(tbp.trackerRole);
if (old != null)
throw new AssertionError("Only one tracker position can match tracker role. " + tbp.trackerRole + " is occupied by " + old + " when adding " + tbp);
byRole.put(tbp.trackerRole, tbp);
}
}
}
public final int id;
public final String designation;
public final TrackerRole trackerRole;
TrackerPosition(int id, String designation, TrackerRole trackerRole) {
this.id = id;
this.designation = designation;
this.trackerRole = trackerRole;
@@ -62,17 +75,4 @@ public enum TrackerPosition {
public static TrackerPosition getById(int id) {
return byId.get(id);
}
static {
for (TrackerPosition tbp : values()) {
byDesignation.put(tbp.designation.toLowerCase(), tbp);
byId.put(tbp.id, tbp);
if (tbp.trackerRole != null) {
TrackerPosition old = byRole.get(tbp.trackerRole);
if (old != null)
throw new AssertionError("Only one tracker position can match tracker role. " + tbp.trackerRole + " is occupied by " + old + " when adding " + tbp);
byRole.put(tbp.trackerRole, tbp);
}
}
}
}

View File

@@ -26,15 +26,23 @@ public enum TrackerRole {
GENERIC_CONTROLLER(21, "vive_tracker_handed", "TrackerRole_Handed", DeviceType.CONTROLLER),
;
public static final TrackerRole[] values = values();
private static final TrackerRole[] byId = new TrackerRole[22];
static {
for (TrackerRole tr : values) {
if (byId[tr.id] != null)
throw new AssertionError("Tracker role id " + tr.id + " occupied by " + byId[tr.id] + " when adding " + tr);
byId[tr.id] = tr;
}
}
public final int id;
public final String roleHint;
public final String viveRole;
public final DeviceType deviceType;
public static final TrackerRole[] values = values();
private static final TrackerRole[] byId = new TrackerRole[22];
private TrackerRole(int id, String roleHint, String viveRole, DeviceType deviceType) {
TrackerRole(int id, String roleHint, String viveRole, DeviceType deviceType) {
this.id = id;
this.roleHint = roleHint;
this.viveRole = viveRole;
@@ -44,12 +52,4 @@ public enum TrackerRole {
public static TrackerRole getById(int id) {
return id < 0 || id >= byId.length ? null : byId[id];
}
static {
for (TrackerRole tr : values) {
if (byId[tr.id] != null)
throw new AssertionError("Tracker role id " + tr.id + " occupied by " + byId[tr.id] + " when adding " + tr);
byId[tr.id] = tr;
}
}
}

View File

@@ -9,12 +9,17 @@ public enum TrackerStatus {
OCCLUDED(4, false),
;
private static final TrackerStatus byId[] = new TrackerStatus[5];
private static final TrackerStatus[] byId = new TrackerStatus[5];
static {
for (TrackerStatus st : values())
byId[st.id] = st;
}
public final int id;
public final boolean sendData;
private TrackerStatus(int id, boolean sendData) {
TrackerStatus(int id, boolean sendData) {
this.sendData = sendData;
this.id = id;
}
@@ -24,9 +29,4 @@ public enum TrackerStatus {
return null;
return byId[id];
}
static {
for (TrackerStatus st : values())
byId[st.id] = st;
}
}

View File

@@ -2,7 +2,7 @@ package dev.slimevr.vr.trackers;
public interface TrackerWithBattery {
public float getBatteryLevel();
float getBatteryLevel();
public float getBatteryVoltage();
float getBatteryVoltage();
}

View File

@@ -2,7 +2,7 @@ package dev.slimevr.vr.trackers;
public interface TrackerWithTPS {
public float getTPS();
float getTPS();
public void dataTick();
void dataTick();
}

View File

@@ -1,18 +1,18 @@
package dev.slimevr.vr.trackers.udp;
import dev.slimevr.NetworkProtocol;
import dev.slimevr.vr.trackers.IMUTracker;
import java.net.InetAddress;
import java.net.SocketAddress;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import dev.slimevr.NetworkProtocol;
import dev.slimevr.vr.trackers.IMUTracker;
public class Device {
public static final AtomicInteger nextLocalDeviceId = new AtomicInteger();
public final int id;
public Map<Integer, IMUTracker> sensors = new HashMap<>();
public SocketAddress address;
public InetAddress ipAddress;
@@ -27,7 +27,6 @@ public class Device {
public NetworkProtocol protocol = null;
public int firmwareBuild = 0;
public boolean timedOut = false;
public final int id;
public Device(SocketAddress address, InetAddress ipAddress) {
this.address = address;

View File

@@ -2,15 +2,15 @@ package dev.slimevr.vr.trackers.udp;
public interface SensorSpecificPacket {
public int getSensorId();
/**
* Sensor with id 255 is "global" representing a whole device
*
* @param sensorId
* @return
*/
public static boolean isGlobal(int sensorId) {
static boolean isGlobal(int sensorId) {
return sensorId == 255;
}
int getSensorId();
}

View File

@@ -1,41 +1,25 @@
package dev.slimevr.vr.trackers.udp;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketAddress;
import java.net.SocketTimeoutException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.function.Consumer;
import dev.slimevr.vr.trackers.IMUTracker;
import dev.slimevr.vr.trackers.ReferenceAdjustedTracker;
import dev.slimevr.vr.trackers.Tracker;
import dev.slimevr.vr.trackers.TrackerStatus;
import org.apache.commons.lang3.ArrayUtils;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import dev.slimevr.Main;
import dev.slimevr.NetworkProtocol;
import dev.slimevr.vr.trackers.IMUTracker;
import dev.slimevr.vr.trackers.ReferenceAdjustedTracker;
import dev.slimevr.vr.trackers.Tracker;
import dev.slimevr.vr.trackers.TrackerStatus;
import io.eiren.util.Util;
import io.eiren.util.collections.FastList;
import io.eiren.util.logging.LogManager;
import org.apache.commons.lang3.ArrayUtils;
import java.io.IOException;
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.*;
import java.util.function.Consumer;
/**
* Receives trackers data by UDP using extended owoTrack protocol.
@@ -90,6 +74,19 @@ public class TrackersUDPServer extends Thread {
}
}
private static String packetToString(DatagramPacket packet) {
StringBuilder sb = new StringBuilder();
sb.append("DatagramPacket{");
sb.append(packet.getAddress().toString());
sb.append(packet.getPort());
sb.append(',');
sb.append(packet.getLength());
sb.append(',');
sb.append(ArrayUtils.toString(packet.getData()));
sb.append('}');
return sb.toString();
}
private void setUpNewConnection(DatagramPacket handshakePacket, UDPPacket3Handshake handshake) throws IOException {
LogManager.log.info("[TrackerServer] Handshake received from " + handshakePacket.getAddress() + ":" + handshakePacket.getPort());
InetAddress addr = handshakePacket.getAddress();
@@ -239,7 +236,7 @@ public class TrackersUDPServer extends Thread {
if (conn.serialBuffer.length() > 0) {
if (conn.lastSerialUpdate + 500L < System.currentTimeMillis()) {
serialBuffer2.append('[').append(conn.name).append("] ").append(conn.serialBuffer);
System.out.println(serialBuffer2.toString());
System.out.println(serialBuffer2);
serialBuffer2.setLength(0);
conn.serialBuffer.setLength(0);
}
@@ -419,19 +416,6 @@ public class TrackersUDPServer extends Thread {
}
}
private static String packetToString(DatagramPacket packet) {
StringBuilder sb = new StringBuilder();
sb.append("DatagramPacket{");
sb.append(packet.getAddress().toString());
sb.append(packet.getPort());
sb.append(',');
sb.append(packet.getLength());
sb.append(',');
sb.append(ArrayUtils.toString(packet.getData()));
sb.append('}');
return sb.toString();
}
public List<Device> getConnections() {
return connections;
}

View File

@@ -5,26 +5,6 @@ import java.nio.ByteBuffer;
public abstract class UDPPacket {
public abstract int getPacketId();
public abstract void readData(ByteBuffer buf) throws IOException;
public abstract void writeData(ByteBuffer buf) throws IOException;
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append('{');
sb.append(getPacketId());
if (this instanceof SensorSpecificPacket) {
sb.append(",sensor:");
sb.append(((SensorSpecificPacket) this).getSensorId());
}
sb.append('}');
return sb.toString();
}
/**
* Naively read null-terminated ASCII string from the byte buffer
*
@@ -69,4 +49,23 @@ public abstract class UDPPacket {
buf.put((byte) 0);
}
public abstract int getPacketId();
public abstract void readData(ByteBuffer buf) throws IOException;
public abstract void writeData(ByteBuffer buf) throws IOException;
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append('{');
sb.append(getPacketId());
if (this instanceof SensorSpecificPacket) {
sb.append(",sensor:");
sb.append(((SensorSpecificPacket) this).getSensorId());
}
sb.append('}');
return sb.toString();
}
}

View File

@@ -28,5 +28,4 @@ public class UDPPacket10PingPong extends UDPPacket {
public void writeData(ByteBuffer buf) throws IOException {
buf.putInt(pingId);
}
}

View File

@@ -30,5 +30,4 @@ public class UDPPacket11Serial extends UDPPacket {
public void writeData(ByteBuffer buf) throws IOException {
// Never sent back in current protocol
}
}

View File

@@ -1,10 +1,10 @@
package dev.slimevr.vr.trackers.udp;
import dev.slimevr.vr.trackers.SensorTap;
import java.io.IOException;
import java.nio.ByteBuffer;
import dev.slimevr.vr.trackers.SensorTap;
public class UDPPacket13Tap extends UDPPacket implements SensorSpecificPacket {
public int sensorId;

View File

@@ -31,5 +31,4 @@ public class UDPPacket14Error extends UDPPacket implements SensorSpecificPacket
public int getSensorId() {
return sensorId;
}
}

View File

@@ -1,10 +1,10 @@
package dev.slimevr.vr.trackers.udp;
import dev.slimevr.vr.trackers.TrackerStatus;
import java.io.IOException;
import java.nio.ByteBuffer;
import dev.slimevr.vr.trackers.TrackerStatus;
public class UDPPacket15SensorInfo extends UDPPacket implements SensorSpecificPacket {
public int sensorId;
@@ -14,6 +14,18 @@ public class UDPPacket15SensorInfo extends UDPPacket implements SensorSpecificPa
public UDPPacket15SensorInfo() {
}
public static TrackerStatus getStatus(int sensorStatus) {
switch (sensorStatus) {
case 0:
return TrackerStatus.DISCONNECTED;
case 1:
return TrackerStatus.OK;
case 2:
return TrackerStatus.ERROR;
}
return null;
}
@Override
public int getPacketId() {
return 15;
@@ -36,17 +48,4 @@ public class UDPPacket15SensorInfo extends UDPPacket implements SensorSpecificPa
public int getSensorId() {
return sensorId;
}
public static TrackerStatus getStatus(int sensorStatus) {
switch (sensorStatus) {
case 0:
return TrackerStatus.DISCONNECTED;
case 1:
return TrackerStatus.OK;
case 2:
return TrackerStatus.ERROR;
}
return null;
}
}

View File

@@ -1,18 +1,17 @@
package dev.slimevr.vr.trackers.udp;
import com.jme3.math.Quaternion;
import java.io.IOException;
import java.nio.ByteBuffer;
import com.jme3.math.Quaternion;
public class UDPPacket17RotationData extends UDPPacket implements SensorSpecificPacket {
public static final int DATA_TYPE_NORMAL = 1;
public static final int DATA_TYPE_CORRECTION = 2;
public final Quaternion rotation = new Quaternion();
public int sensorId;
public int dataType;
public final Quaternion rotation = new Quaternion();
public int calibrationInfo;
public UDPPacket17RotationData() {

View File

@@ -1,10 +1,10 @@
package dev.slimevr.vr.trackers.udp;
import com.jme3.math.Quaternion;
import java.io.IOException;
import java.nio.ByteBuffer;
import com.jme3.math.Quaternion;
public class UDPPacket1Rotation extends UDPPacket implements SensorSpecificPacket {
public final Quaternion rotation = new Quaternion();

View File

@@ -27,5 +27,4 @@ public class UDPPacket200ProtocolChange extends UDPPacket {
buf.put((byte) targetProtocol);
buf.put((byte) targetProtocolVersion);
}
}

View File

@@ -31,5 +31,4 @@ public class UDPPacket20Temperature extends UDPPacket implements SensorSpecificP
public int getSensorId() {
return sensorId;
}
}

View File

@@ -3,6 +3,7 @@ package dev.slimevr.vr.trackers.udp;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
public class UDPProtocolParser {
@@ -32,6 +33,12 @@ public class UDPProtocolParser {
private static final byte[] HANDSHAKE_BUFFER = new byte[64];
static {
HANDSHAKE_BUFFER[0] = 3;
byte[] str = "Hey OVR =D 5".getBytes(StandardCharsets.US_ASCII);
System.arraycopy(str, 0, HANDSHAKE_BUFFER, 1, str.length);
}
public UDPProtocolParser() {
}
@@ -105,14 +112,4 @@ public class UDPProtocolParser {
}
return null;
}
static {
try {
HANDSHAKE_BUFFER[0] = 3;
byte[] str = "Hey OVR =D 5".getBytes("ASCII");
System.arraycopy(str, 0, HANDSHAKE_BUFFER, 1, str.length);
} catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
}
}

View File

@@ -1,26 +1,20 @@
package dev.slimevr.websocketapi;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import dev.slimevr.Main;
import dev.slimevr.VRServer;
import dev.slimevr.bridge.Bridge;
import dev.slimevr.vr.trackers.*;
import io.eiren.util.collections.FastList;
import io.eiren.util.logging.LogManager;
import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.json.JSONException;
import org.json.JSONObject;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import dev.slimevr.Main;
import dev.slimevr.VRServer;
import dev.slimevr.vr.trackers.ComputedTracker;
import dev.slimevr.vr.trackers.HMDTracker;
import dev.slimevr.vr.trackers.ShareableTracker;
import dev.slimevr.vr.trackers.Tracker;
import dev.slimevr.vr.trackers.TrackerStatus;
import io.eiren.util.collections.FastList;
import io.eiren.util.logging.LogManager;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
public class WebSocketVRBridge extends WebsocketAPI implements Bridge {
@@ -97,7 +91,7 @@ public class WebSocketVRBridge extends WebsocketAPI implements Bridge {
parseAction(json, conn);
return;
case "config": // TODO Ignore it for now, it should only register HMD in our test case with id 0
LogManager.log.info("[WebSocket] Config received: " + json.toString());
LogManager.log.info("[WebSocket] Config received: " + json);
return;
}
}

View File

@@ -13,18 +13,18 @@ import org.java_websocket.server.WebSocketServer;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.util.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class WebsocketAPI extends WebSocketServer implements ProtocolAPIServer {
private final Map<Integer, GenericConnection> websocketConnections = new HashMap<>();
public final VRServer server;
public final ProtocolAPI protocolAPI;
private final Map<Integer, GenericConnection> websocketConnections = new HashMap<>();
public WebsocketAPI(VRServer server, ProtocolAPI protocolAPI) {
super(new InetSocketAddress(21110), Collections.<Draft>singletonList(new Draft_6455()));
super(new InetSocketAddress(21110), Collections.singletonList(new Draft_6455()));
this.server = server;
this.protocolAPI = protocolAPI;
@@ -36,7 +36,6 @@ public class WebsocketAPI extends WebSocketServer implements ProtocolAPIServer {
LogManager.log.info("[WebSocketAPI] New connection from: " + conn.getRemoteSocketAddress().getAddress().getHostAddress());
this.websocketConnections.put(conn.hashCode(), new WebsocketConnection(conn));
}
@Override

View File

@@ -2,23 +2,22 @@ package dev.slimevr.unit;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import dev.slimevr.vr.processor.TransformNode;
import dev.slimevr.vr.trackers.ComputedTracker;
import dev.slimevr.vr.trackers.ReferenceAdjustedTracker;
import dev.slimevr.vr.trackers.Tracker;
import io.eiren.math.FloatMath;
import io.eiren.util.StringUtils;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
import java.util.function.Function;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
/**
* Tests {@link ReferenceAdjustedTracker#resetFull(Quaternion)}
@@ -39,6 +38,26 @@ public class ReferenceAdjustmentsTests {
))).flatMap(Function.identity()).flatMap(Function.identity());
}
private static String name(int yaw, int pitch, int roll, float[] angles, float[] anglesAdj, float[] anglesDiff) {
return "Rot: " + yaw + "/" + pitch + "/" + roll + ". "
+ "Angles: " + StringUtils.prettyNumber(angles[0] * FastMath.RAD_TO_DEG, 1) + "/" + StringUtils.prettyNumber(anglesAdj[0] * FastMath.RAD_TO_DEG, 1) + ", "
+ StringUtils.prettyNumber(angles[1] * FastMath.RAD_TO_DEG, 1) + "/" + StringUtils.prettyNumber(anglesAdj[1] * FastMath.RAD_TO_DEG, 1) + ", "
+ StringUtils.prettyNumber(angles[2] * FastMath.RAD_TO_DEG, 1) + "/" + StringUtils.prettyNumber(anglesAdj[2] * FastMath.RAD_TO_DEG, 1) + ". Diff: "
+ StringUtils.prettyNumber(anglesDiff[0] * FastMath.RAD_TO_DEG, 1) + ", "
+ StringUtils.prettyNumber(anglesDiff[1] * FastMath.RAD_TO_DEG, 1) + ", "
+ StringUtils.prettyNumber(anglesDiff[2] * FastMath.RAD_TO_DEG, 1);
}
public static Quaternion q(float pitch, float yaw, float roll) {
return new Quaternion().fromAngles(pitch * FastMath.DEG_TO_RAD, yaw * FastMath.DEG_TO_RAD, roll * FastMath.DEG_TO_RAD);
}
public static String toDegs(Quaternion q) {
float[] degs = new float[3];
q.toAngles(degs);
return StringUtils.prettyNumber(degs[0] * FastMath.RAD_TO_DEG, 0) + "," + StringUtils.prettyNumber(degs[1] * FastMath.RAD_TO_DEG, 0) + "," + StringUtils.prettyNumber(degs[2] * FastMath.RAD_TO_DEG, 0);
}
@TestFactory
Stream<DynamicTest> getTestsYaw() {
return getAnglesSet().map((p) ->
@@ -158,26 +177,6 @@ public class ReferenceAdjustmentsTests {
System.out.println("Errors: " + errors + ", successes: " + successes);
}
private static String name(int yaw, int pitch, int roll, float[] angles, float[] anglesAdj, float[] anglesDiff) {
return "Rot: " + yaw + "/" + pitch + "/" + roll + ". "
+ "Angles: " + StringUtils.prettyNumber(angles[0] * FastMath.RAD_TO_DEG, 1) + "/" + StringUtils.prettyNumber(anglesAdj[0] * FastMath.RAD_TO_DEG, 1) + ", "
+ StringUtils.prettyNumber(angles[1] * FastMath.RAD_TO_DEG, 1) + "/" + StringUtils.prettyNumber(anglesAdj[1] * FastMath.RAD_TO_DEG, 1) + ", "
+ StringUtils.prettyNumber(angles[2] * FastMath.RAD_TO_DEG, 1) + "/" + StringUtils.prettyNumber(anglesAdj[2] * FastMath.RAD_TO_DEG, 1) + ". Diff: "
+ StringUtils.prettyNumber(anglesDiff[0] * FastMath.RAD_TO_DEG, 1) + ", "
+ StringUtils.prettyNumber(anglesDiff[1] * FastMath.RAD_TO_DEG, 1) + ", "
+ StringUtils.prettyNumber(anglesDiff[2] * FastMath.RAD_TO_DEG, 1);
}
public static Quaternion q(float pitch, float yaw, float roll) {
return new Quaternion().fromAngles(pitch * FastMath.DEG_TO_RAD, yaw * FastMath.DEG_TO_RAD, roll * FastMath.DEG_TO_RAD);
}
public static String toDegs(Quaternion q) {
float[] degs = new float[3];
q.toAngles(degs);
return StringUtils.prettyNumber(degs[0] * FastMath.RAD_TO_DEG, 0) + "," + StringUtils.prettyNumber(degs[1] * FastMath.RAD_TO_DEG, 0) + "," + StringUtils.prettyNumber(degs[2] * FastMath.RAD_TO_DEG, 0);
}
private static class QuatEqualYawWithEpsilon {
private final Quaternion q;