mirror of
https://github.com/SlimeVR/SlimeVR-Server.git
synced 2026-04-06 02:01:58 +02:00
Improve HMD handling (#801)
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user