Improve HMD handling (#801)

This commit is contained in:
Erimel
2023-08-09 13:33:02 -04:00
committed by GitHub
parent f343b0e80c
commit cdb4d15d60
8 changed files with 67 additions and 87 deletions

View File

@@ -38,14 +38,13 @@ import java.util.function.Consumer
typealias SteamBridgeProvider = (
server: VRServer,
hmdTracker: Tracker,
computedTrackers: List<Tracker>,
) -> ISteamVRBridge?
const val SLIMEVR_IDENTIFIER = "dev.slimevr.SlimeVR"
class VRServer @JvmOverloads constructor(
driverBridgeProvider: SteamBridgeProvider = { _, _, _ -> null },
driverBridgeProvider: SteamBridgeProvider = { _, _ -> null },
feederBridgeProvider: (VRServer) -> ISteamVRBridge? = { _ -> null },
serialHandlerProvider: (VRServer) -> SerialHandler = { _ -> SerialHandlerStub() },
// configPath is used by VRWorkout, do not remove!
@@ -56,7 +55,6 @@ class VRServer @JvmOverloads constructor(
@JvmField
val humanPoseManager: HumanPoseManager
val hmdTracker: Tracker
private val trackers: MutableList<Tracker> = FastList()
val trackersServer: TrackersUDPServer
private val bridges: MutableList<Bridge> = FastList()
@@ -109,17 +107,6 @@ class VRServer @JvmOverloads constructor(
tapSetupHandler = TapSetupHandler()
autoBoneHandler = AutoBoneHandler(this)
protocolAPI = ProtocolAPI(this)
hmdTracker = Tracker(
null,
0,
"HMD",
"HMD",
TrackerPosition.HEAD,
null,
hasPosition = true,
hasRotation = true,
isComputed = true
)
humanPoseManager = HumanPoseManager(this)
val computedTrackers = humanPoseManager.computedTrackers
@@ -132,7 +119,7 @@ class VRServer @JvmOverloads constructor(
) { tracker: Tracker -> registerTracker(tracker) }
// Start bridges for SteamVR and Feeder
val driverBridge = driverBridgeProvider(this, hmdTracker, computedTrackers)
val driverBridge = driverBridgeProvider(this, computedTrackers)
if (driverBridge != null) {
tasks.add(Runnable { driverBridge.startBridge() })
bridges.add(driverBridge)
@@ -144,7 +131,7 @@ class VRServer @JvmOverloads constructor(
}
// Create WebSocket server
val wsBridge = WebSocketVRBridge(hmdTracker, computedTrackers, this)
val wsBridge = WebSocketVRBridge(computedTrackers, this)
tasks.add(Runnable { wsBridge.startBridge() })
bridges.add(wsBridge)
@@ -169,7 +156,6 @@ class VRServer @JvmOverloads constructor(
oscHandlers.add(vMCHandler)
oSCRouter = OSCRouter(configManager.vrConfig.oscRouter, oscHandlers)
bvhRecorder = BVHRecorder(this)
registerTracker(hmdTracker)
for (tracker in computedTrackers) {
registerTracker(tracker)
}
@@ -269,7 +255,7 @@ class VRServer @JvmOverloads constructor(
private fun trackerAdded(tracker: Tracker) {
humanPoseManager.trackerAdded(tracker)
updateSkeletonModel()
if (tracker.isComputed && tracker.name != "HMD") {
if (tracker.isComputed) {
vMCHandler.addComputedTracker(tracker)
}
refreshTrackersDriftCompensationEnabled()

View File

@@ -14,11 +14,6 @@ object TrackerUtils {
allTrackers: List<Tracker>,
position: TrackerPosition,
): Tracker? {
if (position == TrackerPosition.HEAD) {
// Prioritize non-computed
val head = getNonInternalNonComputedTrackerForBodyPosition(allTrackers, position)
if (head != null) return head
}
return getNonInternalTrackerForBodyPosition(allTrackers, position)
}

View File

@@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import dev.slimevr.VRServer;
import dev.slimevr.bridge.Bridge;
import dev.slimevr.tracking.trackers.Device;
import dev.slimevr.tracking.trackers.Tracker;
import dev.slimevr.tracking.trackers.TrackerPosition;
import dev.slimevr.tracking.trackers.TrackerStatus;
@@ -20,7 +21,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
public class WebSocketVRBridge extends WebsocketAPI implements Bridge {
private static final String resetSourceName = "WebSocketVRBridge";
private final Tracker hmd;
private final List<Tracker> computedTrackers;
private final List<Tracker> internalTrackers;
private final AtomicBoolean newHMDData = new AtomicBoolean(false);
@@ -39,14 +39,13 @@ public class WebSocketVRBridge extends WebsocketAPI implements Bridge {
true,
true
);
private Tracker hmdTracker;
public WebSocketVRBridge(
Tracker hmd,
List<Tracker> computedTrackers,
VRServer server
) {
super(server, server.protocolAPI);
this.hmd = hmd;
this.computedTrackers = new FastList<>(computedTrackers);
this.internalTrackers = new FastList<>(computedTrackers.size());
for (Tracker t : computedTrackers) {
@@ -71,9 +70,31 @@ public class WebSocketVRBridge extends WebsocketAPI implements Bridge {
@Override
public void dataRead() {
if (newHMDData.compareAndSet(true, false)) {
hmd.setPosition(internalHMDTracker.getPosition());
hmd.setRotation(internalHMDTracker.getRotation());
hmd.dataTick();
if (hmdTracker == null) {
// Create HMD for websocket
Device hmdDevice = server.deviceManager
.createDevice("WebSocketVRBridge", null, null);
hmdTracker = new Tracker(
null,
VRServer.getNextLocalTrackerId(),
"WebSocketHMD",
"WebSocketHMD",
TrackerPosition.HEAD,
null,
true,
true,
false,
true,
false,
true
);
hmdDevice.getTrackers().put(0, hmdTracker);
server.registerTracker(hmdTracker);
}
hmdTracker.setPosition(internalHMDTracker.getPosition());
hmdTracker.setRotation(internalHMDTracker.getRotation());
hmdTracker.dataTick();
}
}

View File

@@ -145,7 +145,6 @@ fun main(args: Array<String>) {
fun provideSteamVRBridge(
server: VRServer,
hmdTracker: Tracker,
computedTrackers: List<Tracker>,
): ISteamVRBridge? {
val driverBridge: SteamVRBridge?
@@ -153,7 +152,6 @@ fun provideSteamVRBridge(
// Create named pipe bridge for SteamVR driver
driverBridge = WindowsNamedPipeBridge(
server,
hmdTracker,
"steamvr",
"SteamVR Driver Bridge",
"""\\.\pipe\SlimeVRDriver""",
@@ -164,7 +162,6 @@ fun provideSteamVRBridge(
try {
linuxBridge = UnixSocketBridge(
server,
hmdTracker,
"steamvr",
"SteamVR Driver Bridge",
Paths.get(OperatingSystem.tempDirectory, "SlimeVRDriver")
@@ -201,29 +198,30 @@ fun provideFeederBridge(
server: VRServer,
): ISteamVRBridge? {
val feederBridge: SteamVRBridge?
if (OperatingSystem.currentPlatform == OperatingSystem.WINDOWS) {
// Create named pipe bridge for SteamVR input
// TODO: how do we want to handle HMD input from the feeder app?
feederBridge = WindowsNamedPipeBridge(
server,
null,
"steamvr_feeder",
"SteamVR Feeder Bridge",
"""\\.\pipe\SlimeVRInput""",
FastList()
)
} else if (OperatingSystem.currentPlatform == OperatingSystem.LINUX) {
feederBridge = UnixSocketBridge(
server,
null,
"steamvr_feeder",
"SteamVR Feeder Bridge",
Paths.get(OperatingSystem.tempDirectory, "SlimeVRInput")
.toString(),
FastList()
)
} else {
feederBridge = null
when (OperatingSystem.currentPlatform) {
OperatingSystem.WINDOWS -> {
// Create named pipe bridge for SteamVR input
feederBridge = WindowsNamedPipeBridge(
server,
"steamvr_feeder",
"SteamVR Feeder Bridge",
"""\\.\pipe\SlimeVRInput""",
FastList()
)
}
OperatingSystem.LINUX -> {
feederBridge = UnixSocketBridge(
server,
"steamvr_feeder",
"SteamVR Feeder Bridge",
Paths.get(OperatingSystem.tempDirectory, "SlimeVRInput")
.toString(),
FastList()
)
}
else -> {
feederBridge = null
}
}
return feederBridge

View File

@@ -5,12 +5,10 @@ import dev.slimevr.bridge.BridgeThread;
import dev.slimevr.bridge.ISteamVRBridge;
import dev.slimevr.desktop.platform.ProtobufMessages.*;
import dev.slimevr.tracking.trackers.Tracker;
import dev.slimevr.tracking.trackers.TrackerRole;
import dev.slimevr.util.ann.VRServerThread;
import io.eiren.util.ann.Synchronize;
import io.eiren.util.ann.ThreadSafe;
import io.eiren.util.collections.FastList;
import io.eiren.util.logging.LogManager;
import io.github.axisangles.ktmath.Quaternion;
import io.github.axisangles.ktmath.Vector3;
@@ -36,13 +34,10 @@ public abstract class ProtobufBridge implements ISteamVRBridge {
private final Map<String, Tracker> remoteTrackersBySerial = new HashMap<>();
@Synchronize("self")
private final Map<Integer, Tracker> remoteTrackersByTrackerId = new HashMap<>();
private final Tracker hmd;
private boolean hadNewData = false;
private Tracker hmdTracker;
public ProtobufBridge(String bridgeName, Tracker hmd) {
public ProtobufBridge(String bridgeName) {
this.bridgeName = bridgeName;
this.hmd = hmd;
}
/**
@@ -83,9 +78,6 @@ public abstract class ProtobufBridge implements ISteamVRBridge {
processMessageReceived(message);
hadNewData = true;
}
if (hadNewData && hmdTracker != null) {
trackerOverrideUpdate(hmdTracker, hmd);
}
}
@VRServerThread
@@ -202,27 +194,17 @@ public abstract class ProtobufBridge implements ISteamVRBridge {
synchronized (remoteTrackersByTrackerId) {
remoteTrackersByTrackerId.put(tracker.getTrackerNum(), tracker);
}
if (trackerAdded.getTrackerRole() == TrackerRole.HMD.getId()) {
hmdTracker = tracker;
} else {
VRServer.Companion.getInstance().registerTracker(tracker);
}
VRServer.Companion.getInstance().registerTracker(tracker);
}
@VRServerThread
protected void userActionReceived(UserAction userAction) {
String resetSourceName = String.format("%s: %s", resetSourceNamePrefix, bridgeName);
switch (userAction.getName()) {
case "calibrate":
LogManager
.warning("[" + bridgeName + "] Received deprecated user action 'calibrate'!");
case "reset":
case "reset" ->
// TODO : Check pose field
VRServer.Companion.getInstance().resetTrackersFull(resetSourceName);
break;
case "fast_reset":
VRServer.Companion.getInstance().resetTrackersYaw(resetSourceName);
break;
case "fast_reset" -> VRServer.Companion.getInstance().resetTrackersYaw(resetSourceName);
}
}
@@ -267,9 +249,6 @@ public abstract class ProtobufBridge implements ISteamVRBridge {
.setStatus(dev.slimevr.tracking.trackers.TrackerStatus.DISCONNECTED);
}
}
if (hmdTracker != null) {
hmd.setStatus(dev.slimevr.tracking.trackers.TrackerStatus.DISCONNECTED);
}
}
@VRServerThread

View File

@@ -23,13 +23,12 @@ public abstract class SteamVRBridge extends ProtobufBridge implements Runnable {
public SteamVRBridge(
VRServer server,
Tracker hmd,
String threadName,
String bridgeName,
String bridgeSettingsKey,
List<Tracker> shareableTrackers
) {
super(bridgeName, hmd);
super(bridgeName);
this.bridgeSettingsKey = bridgeSettingsKey;
this.runnerThread = new Thread(this, threadName);
this.shareableTrackers = shareableTrackers;
@@ -96,7 +95,11 @@ public abstract class SteamVRBridge extends ProtobufBridge implements Runnable {
String displayName;
boolean needsReset;
if (trackerAdded.getTrackerId() == 0) {
displayName = "OpenVR HMD";
if (trackerAdded.getTrackerName().equals("HMD"))
displayName = "SteamVR Driver HMD";
else
displayName = "Feeder App HMD";
// TODO support needsReset = true if HMD isn't assigned to head
needsReset = false;
} else {
displayName = trackerAdded.getTrackerName();

View File

@@ -35,13 +35,12 @@ public class UnixSocketBridge extends SteamVRBridge implements AutoCloseable {
public UnixSocketBridge(
VRServer server,
Tracker hmd,
String bridgeSettingsKey,
String bridgeName,
String socketPath,
List<Tracker> shareableTrackers
) {
super(server, hmd, "Named socket thread", bridgeName, bridgeSettingsKey, shareableTrackers);
super(server, "Named socket thread", bridgeName, bridgeSettingsKey, shareableTrackers);
this.socketPath = socketPath;
this.socketAddress = UnixDomainSocketAddress.of(socketPath);

View File

@@ -55,13 +55,12 @@ public class WindowsNamedPipeBridge extends SteamVRBridge {
public WindowsNamedPipeBridge(
VRServer server,
Tracker hmd,
String bridgeSettingsKey,
String bridgeName,
String pipeName,
List<Tracker> shareableTrackers
) {
super(server, hmd, "Named pipe thread", bridgeName, bridgeSettingsKey, shareableTrackers);
super(server, "Named pipe thread", bridgeName, bridgeSettingsKey, shareableTrackers);
this.pipeName = pipeName;
overlappedWait.hEvent = rxEvent;
}