mirror of
https://github.com/SlimeVR/SlimeVR-Server.git
synced 2026-04-06 02:01:58 +02:00
Compare commits
14 Commits
csv-data-e
...
mitten
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d91838fab | ||
|
|
0236a05f26 | ||
|
|
28deb357da | ||
|
|
4d93f87a01 | ||
|
|
88adfce242 | ||
|
|
3d02795dbc | ||
|
|
7ff50f78eb | ||
|
|
0e3aaf105c | ||
|
|
f638540886 | ||
|
|
343d69d690 | ||
|
|
e2d7d354c6 | ||
|
|
cc6f297b92 | ||
|
|
2add43e71a | ||
|
|
0a493ac345 |
@@ -116,3 +116,9 @@ licensed under `GPL-v3`.
|
||||
## Discord
|
||||
We use discord *a lot* to coordinate and discuss development. Come join us at
|
||||
https://discord.gg/SlimeVR!
|
||||
|
||||
## Use of AI
|
||||
We DO NOT accept contributions that are generated with AI (for example, "vibe-coding").
|
||||
|
||||
If you do use AI, and you believe your usage of AI is reasonable, you must clearly disclose
|
||||
how you used AI in your submission.
|
||||
|
||||
@@ -662,6 +662,8 @@ settings-general-fk_settings-skeleton_settings-impute_hip_from_waist_legs = Impu
|
||||
settings-general-fk_settings-skeleton_settings-interp_hip_legs = Average the hip's yaw and roll with the legs'
|
||||
settings-general-fk_settings-skeleton_settings-interp_knee_tracker_ankle = Average the knee trackers' yaw and roll with the ankles'
|
||||
settings-general-fk_settings-skeleton_settings-interp_knee_ankle = Average the knees' yaw and roll with the ankles'
|
||||
settings-general-fk_settings-skeleton_settings-fingers_mitten = Fingers Mitten Mode
|
||||
|
||||
|
||||
settings-general-fk_settings-self_localization-title = Mocap mode
|
||||
settings-general-fk_settings-self_localization-description = Mocap Mode allows the skeleton to roughly track its own position without a headset or other trackers. Note that this requires feet and head trackers to work and is still experimental.
|
||||
|
||||
@@ -18,6 +18,8 @@ SUBSYSTEMS=="usb", ATTRS{idVendor}=="1A86", ATTRS{idProduct}=="7522", MODE="0660
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1A86", ATTRS{idProduct}=="7523", MODE="0660", TAG+="uaccess"
|
||||
# CH341
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1A86", ATTRS{idProduct}=="5523", MODE="0660", TAG+="uaccess"
|
||||
# CH343
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1A86", ATTRS{idProduct}=="55D3", MODE="0660", TAG+="uaccess"
|
||||
# CH9102x
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1A86", ATTRS{idProduct}=="55D4", MODE="0660", TAG+="uaccess"
|
||||
|
||||
@@ -26,8 +28,10 @@ SUBSYSTEMS=="usb", ATTRS{idVendor}=="1A86", ATTRS{idProduct}=="55D4", MODE="0660
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="10C4", ATTRS{idProduct}=="EA60", MODE="0660", TAG+="uaccess"
|
||||
|
||||
## Espressif
|
||||
# ESP32-C3
|
||||
# ESP32-S3 / ESP32-C3 / ESP32-C5 / ESP32-C6 / ESP32-C61 / ESP32-H2 / ESP32-P4
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="303A", ATTRS{idProduct}=="1001", MODE="0660", TAG+="uaccess"
|
||||
# ESP32-S2
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="303A", ATTRS{idProduct}=="0002", MODE="0660", TAG+="uaccess"
|
||||
|
||||
## FTDI
|
||||
# FT232BM/L/Q, FT245BM/L/Q
|
||||
|
||||
@@ -75,6 +75,7 @@ export type SettingsForm = {
|
||||
usePosition: boolean;
|
||||
enforceConstraints: boolean;
|
||||
correctConstraints: boolean;
|
||||
fingersMitten: boolean;
|
||||
};
|
||||
ratios: {
|
||||
imputeWaistFromChestHip: number;
|
||||
@@ -134,6 +135,7 @@ const defaultValues: SettingsForm = {
|
||||
usePosition: true,
|
||||
enforceConstraints: true,
|
||||
correctConstraints: true,
|
||||
fingersMitten: false,
|
||||
},
|
||||
ratios: {
|
||||
imputeWaistFromChestHip: 0.3,
|
||||
@@ -231,6 +233,7 @@ export function GeneralSettings() {
|
||||
toggles.usePosition = values.toggles.usePosition;
|
||||
toggles.enforceConstraints = values.toggles.enforceConstraints;
|
||||
toggles.correctConstraints = values.toggles.correctConstraints;
|
||||
toggles.fingersMitten = values.toggles.fingersMitten;
|
||||
modelSettings.toggles = toggles;
|
||||
}
|
||||
|
||||
@@ -1036,6 +1039,15 @@ export function GeneralSettings() {
|
||||
'settings-general-fk_settings-skeleton_settings-extended_knees_model'
|
||||
)}
|
||||
/>
|
||||
<CheckBox
|
||||
variant="toggle"
|
||||
outlined
|
||||
control={control}
|
||||
name="toggles.fingersMitten"
|
||||
label={l10n.getString(
|
||||
'settings-general-fk_settings-skeleton_settings-fingers_mitten'
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<div className="flex flex-col pt-2 pb-3 gap-2">
|
||||
|
||||
@@ -38,7 +38,7 @@ export function TrackerBattery({
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
disabled={!charging && (!runtime || debug)}
|
||||
disabled={charging || !runtime || debug}
|
||||
preferedDirection="left"
|
||||
content=<Typography>{percentFormatter.format(value)}</Typography>
|
||||
>
|
||||
|
||||
@@ -199,7 +199,7 @@ export function TrackerSettingsPage() {
|
||||
shakeHighlight={false}
|
||||
/>
|
||||
)}
|
||||
{
|
||||
{tracker?.device?.hardwareInfo?.hardwareIdentifier != 'Unknown' && (
|
||||
<div className="flex flex-col bg-background-70 p-3 rounded-lg gap-2">
|
||||
<Typography
|
||||
variant="section-title"
|
||||
@@ -223,34 +223,38 @@ export function TrackerSettingsPage() {
|
||||
whitespace="whitespace-pre-wrap"
|
||||
textAlign="text-end"
|
||||
>
|
||||
v{tracker?.device?.hardwareInfo?.firmwareVersion}
|
||||
{tracker?.device?.hardwareInfo?.firmwareVersion
|
||||
? `v${tracker?.device?.hardwareInfo?.firmwareVersion}`
|
||||
: '--'}
|
||||
</Typography>
|
||||
</div>
|
||||
<div className="flex justify-between gap-2">
|
||||
<Typography id="tracker-settings-latest-version" />
|
||||
{!updateUnavailable && (
|
||||
<>
|
||||
{currentFirmwareRelease && (
|
||||
<Typography
|
||||
color={
|
||||
needUpdate === 'updated'
|
||||
? undefined
|
||||
: 'text-accent-background-10'
|
||||
}
|
||||
textAlign="text-end"
|
||||
whitespace="whitespace-pre-wrap"
|
||||
>
|
||||
{currentFirmwareRelease.name}
|
||||
</Typography>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{updateUnavailable && (
|
||||
<Typography id="tracker-settings-update-unavailable-v2">
|
||||
No releases found
|
||||
</Typography>
|
||||
)}
|
||||
</div>
|
||||
{!!tracker?.device?.hardwareInfo?.officialBoardType && (
|
||||
<div className="flex justify-between gap-2">
|
||||
<Typography id="tracker-settings-latest-version" />
|
||||
{!updateUnavailable && (
|
||||
<>
|
||||
{currentFirmwareRelease && (
|
||||
<Typography
|
||||
color={
|
||||
needUpdate === 'updated'
|
||||
? undefined
|
||||
: 'text-accent-background-10'
|
||||
}
|
||||
textAlign="text-end"
|
||||
whitespace="whitespace-pre-wrap"
|
||||
>
|
||||
{currentFirmwareRelease.name}
|
||||
</Typography>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{updateUnavailable && (
|
||||
<Typography id="tracker-settings-update-unavailable-v2">
|
||||
No releases found
|
||||
</Typography>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{!updateUnavailable && (
|
||||
<Tooltip
|
||||
@@ -289,7 +293,7 @@ export function TrackerSettingsPage() {
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
)}
|
||||
|
||||
<div className="flex flex-col bg-background-70 p-3 rounded-lg gap-2 overflow-x-auto">
|
||||
<div className="flex justify-between">
|
||||
@@ -317,10 +321,11 @@ export function TrackerSettingsPage() {
|
||||
<div className="flex justify-between">
|
||||
<Typography>{l10n.getString('tracker-infos-url')}</Typography>
|
||||
<Typography>
|
||||
udp://
|
||||
{IPv4.fromNumber(
|
||||
tracker?.device?.hardwareInfo?.ipAddress?.addr || 0
|
||||
).toString()}
|
||||
{tracker?.device?.hardwareInfo?.ipAddress?.addr
|
||||
? `udp://${IPv4.fromNumber(
|
||||
tracker?.device?.hardwareInfo?.ipAddress?.addr || 0
|
||||
).toString()}`
|
||||
: '--'}
|
||||
</Typography>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
|
||||
@@ -129,9 +129,6 @@ export function checkForUpdate(
|
||||
|
||||
if (
|
||||
!device.hardwareInfo?.officialBoardType ||
|
||||
![BoardType.SLIMEVR, BoardType.SLIMEVR_V1_2].includes(
|
||||
device.hardwareInfo.officialBoardType
|
||||
) ||
|
||||
!semver.valid(currentFirmwareRelease.version) ||
|
||||
!semver.valid(device.hardwareInfo.firmwareVersion?.toString() ?? 'none')
|
||||
) {
|
||||
@@ -143,6 +140,14 @@ export function checkForUpdate(
|
||||
currentFirmwareRelease.version
|
||||
);
|
||||
|
||||
if (
|
||||
![BoardType.SLIMEVR, BoardType.SLIMEVR_V1_2].includes(
|
||||
device.hardwareInfo.officialBoardType
|
||||
)
|
||||
) {
|
||||
return canUpdate ? 'unavailable' : 'updated';
|
||||
}
|
||||
|
||||
if (
|
||||
canUpdate &&
|
||||
device.hardwareStatus?.batteryPctEstimate != null &&
|
||||
|
||||
@@ -349,6 +349,9 @@ fun createDeviceData(
|
||||
if (tracker.packetsReceived != null) {
|
||||
HardwareStatus.addPacketsReceived(fbb, tracker.packetsReceived!!)
|
||||
}
|
||||
if (tracker.batteryRemainingRuntime != null) {
|
||||
HardwareStatus.addBatteryRuntimeEstimate(fbb, tracker.batteryRemainingRuntime!!)
|
||||
}
|
||||
|
||||
val hardwareDataOffset = HardwareStatus.endHardwareStatus(fbb)
|
||||
val hardwareInfoOffset = createHardwareInfo(fbb, device)
|
||||
|
||||
@@ -39,24 +39,39 @@ class RPCResetHandler(var rpcHandler: RPCHandler, var api: ProtocolAPI) : ResetL
|
||||
}
|
||||
|
||||
if (req.resetType() == ResetType.Yaw) {
|
||||
if (bodyParts.isEmpty()) {
|
||||
api.server.scheduleResetTrackersYaw(RESET_SOURCE_NAME, ((req.delay() ?: resetsConfig.yawResetDelay) * 1000).toLong())
|
||||
val delay = if (req.hasDelay()) {
|
||||
req.delay()
|
||||
} else {
|
||||
api.server.scheduleResetTrackersYaw(RESET_SOURCE_NAME, ((req.delay() ?: resetsConfig.yawResetDelay) * 1000).toLong(), bodyParts.toList())
|
||||
resetsConfig.yawResetDelay
|
||||
}
|
||||
if (bodyParts.isEmpty()) {
|
||||
api.server.scheduleResetTrackersYaw(RESET_SOURCE_NAME, (delay * 1000).toLong())
|
||||
} else {
|
||||
api.server.scheduleResetTrackersYaw(RESET_SOURCE_NAME, (delay * 1000).toLong(), bodyParts.toList())
|
||||
}
|
||||
}
|
||||
if (req.resetType() == ResetType.Full) {
|
||||
if (bodyParts.isEmpty()) {
|
||||
api.server.scheduleResetTrackersFull(RESET_SOURCE_NAME, ((req.delay() ?: resetsConfig.fullResetDelay) * 1000).toLong())
|
||||
val delay = if (req.hasDelay()) {
|
||||
req.delay()
|
||||
} else {
|
||||
api.server.scheduleResetTrackersFull(RESET_SOURCE_NAME, ((req.delay() ?: resetsConfig.fullResetDelay) * 1000).toLong(), bodyParts.toList())
|
||||
resetsConfig.fullResetDelay
|
||||
}
|
||||
if (bodyParts.isEmpty()) {
|
||||
api.server.scheduleResetTrackersFull(RESET_SOURCE_NAME, (delay * 1000).toLong())
|
||||
} else {
|
||||
api.server.scheduleResetTrackersFull(RESET_SOURCE_NAME, (delay * 1000).toLong(), bodyParts.toList())
|
||||
}
|
||||
}
|
||||
if (req.resetType() == ResetType.Mounting) {
|
||||
if (bodyParts.isEmpty()) {
|
||||
api.server.scheduleResetTrackersMounting(RESET_SOURCE_NAME, ((req.delay() ?: resetsConfig.mountingResetDelay) * 1000).toLong())
|
||||
val delay = if (req.hasDelay()) {
|
||||
req.delay()
|
||||
} else {
|
||||
api.server.scheduleResetTrackersMounting(RESET_SOURCE_NAME, ((req.delay() ?: resetsConfig.mountingResetDelay) * 1000).toLong(), bodyParts.toList())
|
||||
resetsConfig.mountingResetDelay
|
||||
}
|
||||
if (bodyParts.isEmpty()) {
|
||||
api.server.scheduleResetTrackersMounting(RESET_SOURCE_NAME, (delay * 1000).toLong())
|
||||
} else {
|
||||
api.server.scheduleResetTrackersMounting(RESET_SOURCE_NAME, (delay * 1000).toLong(), bodyParts.toList())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,6 +209,7 @@ fun createModelSettings(
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.USE_POSITION),
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.ENFORCE_CONSTRAINTS),
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.CORRECT_CONSTRAINTS),
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.FINGERS_MITTEN),
|
||||
)
|
||||
val ratiosOffset = ModelRatios
|
||||
.createModelRatios(
|
||||
|
||||
@@ -241,6 +241,7 @@ class RPCSettingsHandler(var rpcHandler: RPCHandler, var api: ProtocolAPI) {
|
||||
hpm.setToggle(SkeletonConfigToggles.USE_POSITION, toggles.usePosition())
|
||||
hpm.setToggle(SkeletonConfigToggles.ENFORCE_CONSTRAINTS, toggles.enforceConstraints())
|
||||
hpm.setToggle(SkeletonConfigToggles.CORRECT_CONSTRAINTS, toggles.correctConstraints())
|
||||
hpm.setToggle(SkeletonConfigToggles.FINGERS_MITTEN, toggles.fingersMitten())
|
||||
}
|
||||
|
||||
if (ratios != null) {
|
||||
|
||||
@@ -36,7 +36,7 @@ public class ProvisioningHandler implements SerialListener {
|
||||
this.provisioningTickTimer.scheduleAtFixedRate(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!isRunning)
|
||||
if (!isRunning || provisioningStatus == ProvisioningStatus.DONE)
|
||||
return;
|
||||
provisioningTick();
|
||||
}
|
||||
|
||||
@@ -30,14 +30,18 @@ abstract class SerialHandler {
|
||||
Pair(0x1A86, 0x7523),
|
||||
// CH341
|
||||
Pair(0x1A86, 0x5523),
|
||||
// CH343
|
||||
Pair(0x1A86, 0x55D3),
|
||||
// CH9102x
|
||||
Pair(0x1A86, 0x55D4),
|
||||
// / Silabs
|
||||
// CP210x
|
||||
Pair(0x10C4, 0xEA60),
|
||||
// / Espressif
|
||||
// ESP32-C3
|
||||
// ESP32-S3 / ESP32-C3 / ESP32-C5 / ESP32-C6 / ESP32-C61 / ESP32-H2 / ESP32-P4
|
||||
Pair(0x303A, 0x1001),
|
||||
// ESP32-S2
|
||||
Pair(0x303A, 0x0002),
|
||||
// / FTDI
|
||||
// FT232BM/L/Q, FT245BM/L/Q
|
||||
// FT232RL/Q, FT245RL/Q
|
||||
|
||||
@@ -17,7 +17,8 @@ public enum SkeletonConfigToggles {
|
||||
SELF_LOCALIZATION(10, "Self Localization", "selfLocalization", false),
|
||||
USE_POSITION(11, "Use Position", "usePosition", true),
|
||||
ENFORCE_CONSTRAINTS(12, "Enforce Constraints", "enforceConstraints", true),
|
||||
CORRECT_CONSTRAINTS(13, "Correct Constraints", "correctConstraints", true),;
|
||||
CORRECT_CONSTRAINTS(13, "Correct Constraints", "correctConstraints", true),
|
||||
FINGERS_MITTEN(14, "Fingers Mitten", "fingersMitten", true),;
|
||||
|
||||
public static final SkeletonConfigToggles[] values = values();
|
||||
private static final Map<String, SkeletonConfigToggles> byStringVal = new HashMap<>();
|
||||
|
||||
@@ -197,6 +197,7 @@ class HumanSkeleton(
|
||||
private var forceArmsFromHMD = true
|
||||
private var enforceConstraints = true
|
||||
private var correctConstraints = true
|
||||
private var fingersMitten = true
|
||||
|
||||
// Ratios
|
||||
private var waistFromChestHipAveraging = 0f
|
||||
@@ -1204,6 +1205,8 @@ class HumanSkeleton(
|
||||
SkeletonConfigToggles.ENFORCE_CONSTRAINTS -> enforceConstraints = newValue
|
||||
|
||||
SkeletonConfigToggles.CORRECT_CONSTRAINTS -> correctConstraints = newValue
|
||||
|
||||
SkeletonConfigToggles.FINGERS_MITTEN -> fingersMitten = newValue
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,8 +24,6 @@ class TrackerResetsHandler(val tracker: Tracker) {
|
||||
Math.PI.toFloat(),
|
||||
0f,
|
||||
).toQuaternion()
|
||||
private val QuarterPitch = Quaternion.rotationAroundXAxis(FastMath.HALF_PI)
|
||||
|
||||
private var driftAmount = 0f
|
||||
private var averagedDriftQuat = Quaternion.IDENTITY
|
||||
private var rotationSinceReset = Quaternion.IDENTITY
|
||||
@@ -54,6 +52,16 @@ class TrackerResetsHandler(val tracker: Tracker) {
|
||||
|
||||
// Reference adjustment quats
|
||||
|
||||
/**
|
||||
* Gyro fix is set by full reset. This sets the current y rotation to 0, correcting
|
||||
* for initial yaw rotation and the rotation incurred by mounting orientation. This
|
||||
* is a local offset in rotation and does not affect the axes of rotation.
|
||||
*
|
||||
* This rotation is only used to compute [attachmentFix], otherwise [yawFix] would
|
||||
* correct for the same rotation.
|
||||
*/
|
||||
private var gyroFix = Quaternion.IDENTITY
|
||||
|
||||
/**
|
||||
* Attachment fix is set by full reset. This sets the current x and z rotations to
|
||||
* 0, correcting for initial pitch and roll rotation. This is a global offset in
|
||||
@@ -180,9 +188,12 @@ class TrackerResetsHandler(val tracker: Tracker) {
|
||||
/**
|
||||
* Get the reference adjusted accel.
|
||||
*/
|
||||
// All IMU axis corrections are inverse to undo `adjustToReference` after local yaw offsets are added
|
||||
// Order is VERY important here! Please be extremely careful! >~>
|
||||
fun getReferenceAdjustedAccel(rawRot: Quaternion, accel: Vector3): Vector3 = (adjustToReference(rawRot) * (attachmentFix * mountingOrientation * mountRotFix * tposeDownFix).inv()).sandwich(accel)
|
||||
// TODO: Make this actually adjusted to the corrected IMU heading. The current
|
||||
// implementation for heading correction doesn't appear to be correct and may simply
|
||||
// make acceleration worse, so I'm just leaving this until we work that out. The
|
||||
// output of this will be world space, but with an unknown offset to heading (yaw).
|
||||
// - Butterscotch
|
||||
fun getReferenceAdjustedAccel(rawRot: Quaternion, accel: Vector3): Vector3 = rawRot.sandwich(accel)
|
||||
|
||||
/**
|
||||
* Converts raw or filtered rotation into reference- and
|
||||
@@ -191,17 +202,22 @@ class TrackerResetsHandler(val tracker: Tracker) {
|
||||
*/
|
||||
private fun adjustToReference(rotation: Quaternion): Quaternion {
|
||||
var rot = rotation
|
||||
// Correct for global pitch/roll offset
|
||||
rot *= attachmentFix
|
||||
// Correct for global yaw offset without affecting local yaw so we can change this
|
||||
// later without invalidating local yaw offset corrections
|
||||
// Align heading axis with bone space
|
||||
if (!tracker.isHmd || tracker.trackerPosition != TrackerPosition.HEAD) {
|
||||
rot = mountingOrientation.inv() * rot * mountingOrientation
|
||||
rot *= mountingOrientation
|
||||
}
|
||||
rot = mountRotFix.inv() * rot * mountRotFix
|
||||
// T-pose global correction
|
||||
// Heading correction assuming manual orientation is correct
|
||||
rot = gyroFix * rot
|
||||
// Align attitude axes with bone space
|
||||
rot *= attachmentFix
|
||||
// Secondary heading axis alignment with bone space for automatic mounting
|
||||
// Note: Applying an inverse amount of heading correction corresponding to the
|
||||
// axis alignment quaternion will leave the correction to another variable
|
||||
rot = mountRotFix.inv() * (rot * mountRotFix)
|
||||
// More attitude axes alignment specifically for the t-pose configuration, this
|
||||
// probably shouldn't be a separate variable from attachmentFix?
|
||||
rot *= tposeDownFix
|
||||
// Align local yaw with reference
|
||||
// More heading correction
|
||||
rot = yawFix * rot
|
||||
rot = constraintFix * rot
|
||||
return rot
|
||||
@@ -211,6 +227,8 @@ class TrackerResetsHandler(val tracker: Tracker) {
|
||||
* Converts raw or filtered rotation into zero-reference-adjusted by
|
||||
* applying quaternions produced after full reset and yaw reset only
|
||||
*/
|
||||
// This is essentially just adjustToReference but aligning to quaternion identity
|
||||
// rather than to the bone.
|
||||
private fun adjustToIdentity(rotation: Quaternion): Quaternion {
|
||||
var rot = rotation
|
||||
rot = gyroFixNoMounting * rot
|
||||
@@ -265,23 +283,15 @@ class TrackerResetsHandler(val tracker: Tracker) {
|
||||
lastResetQuaternion = oldRot
|
||||
|
||||
// Adjust raw rotation to mountingOrientation
|
||||
val rotation = tracker.getRawRotation()
|
||||
val mountingAdjustedRotation = tracker.getRawRotation() * mountingOrientation
|
||||
|
||||
// Gyrofix
|
||||
val gyroFix = if (tracker.allowMounting || (tracker.trackerPosition == TrackerPosition.HEAD && !tracker.isHmd)) {
|
||||
if (tracker.isComputed) {
|
||||
fixGyroscope(rotation)
|
||||
if (tracker.allowMounting || (tracker.trackerPosition == TrackerPosition.HEAD && !tracker.isHmd)) {
|
||||
gyroFix = if (tracker.isComputed) {
|
||||
fixGyroscope(tracker.getRawRotation())
|
||||
} else {
|
||||
if (tracker.trackerPosition.isFoot()) {
|
||||
// Feet are rotated by 90 deg pitch, this means we're relying on IMU rotation
|
||||
// to be set correctly here.
|
||||
fixGyroscope(rotation * tposeDownFix * QuarterPitch)
|
||||
} else {
|
||||
fixGyroscope(rotation * tposeDownFix)
|
||||
}
|
||||
fixGyroscope(mountingAdjustedRotation * tposeDownFix)
|
||||
}
|
||||
} else {
|
||||
Quaternion.IDENTITY
|
||||
}
|
||||
|
||||
// Mounting for computed trackers
|
||||
@@ -296,7 +306,7 @@ class TrackerResetsHandler(val tracker: Tracker) {
|
||||
if (resetHmdPitch) {
|
||||
// Reset the HMD's pitch if it's assigned to head and resetHmdPitch is true
|
||||
// Get rotation without yaw (make sure to use the raw rotation directly!)
|
||||
val rotBuf = getYawQuaternion(rotation).inv() * rotation
|
||||
val rotBuf = getYawQuaternion(tracker.getRawRotation()).inv() * tracker.getRawRotation()
|
||||
// Isolate pitch
|
||||
Quaternion(rotBuf.w, -rotBuf.x, 0f, 0f).unit()
|
||||
} else {
|
||||
@@ -304,7 +314,7 @@ class TrackerResetsHandler(val tracker: Tracker) {
|
||||
Quaternion.IDENTITY
|
||||
}
|
||||
} else {
|
||||
(gyroFix * rotation).inv()
|
||||
fixAttachment(mountingAdjustedRotation)
|
||||
}
|
||||
|
||||
// Rotate attachmentFix by 180 degrees as a workaround for t-pose (down)
|
||||
@@ -316,7 +326,7 @@ class TrackerResetsHandler(val tracker: Tracker) {
|
||||
|
||||
// Don't adjust yaw if head and computed
|
||||
if (tracker.trackerPosition != TrackerPosition.HEAD || !tracker.isComputed) {
|
||||
yawFix = gyroFix * reference.project(Vector3.POS_Y).unit()
|
||||
yawFix = fixYaw(mountingAdjustedRotation, reference)
|
||||
tracker.yawResetSmoothing.reset()
|
||||
}
|
||||
|
||||
@@ -360,7 +370,7 @@ class TrackerResetsHandler(val tracker: Tracker) {
|
||||
lastResetQuaternion = oldRot
|
||||
|
||||
val yawFixOld = yawFix
|
||||
yawFix = fixYaw(tracker.getRawRotation(), reference)
|
||||
yawFix = fixYaw(tracker.getRawRotation() * mountingOrientation, reference)
|
||||
tracker.yawResetSmoothing.reset()
|
||||
|
||||
makeIdentityAdjustmentQuatsYaw()
|
||||
@@ -399,9 +409,9 @@ class TrackerResetsHandler(val tracker: Tracker) {
|
||||
constraintFix = Quaternion.IDENTITY
|
||||
|
||||
// Get the current calibrated rotation
|
||||
var rotBuf = adjustToDrift(tracker.getRawRotation())
|
||||
var rotBuf = adjustToDrift(tracker.getRawRotation() * mountingOrientation)
|
||||
rotBuf = gyroFix * rotBuf
|
||||
rotBuf *= attachmentFix
|
||||
rotBuf = mountingOrientation.inv() * rotBuf * mountingOrientation
|
||||
rotBuf = yawFix * rotBuf
|
||||
|
||||
// Adjust buffer to reference
|
||||
@@ -457,22 +467,14 @@ class TrackerResetsHandler(val tracker: Tracker) {
|
||||
mountRotFix = Quaternion.IDENTITY
|
||||
}
|
||||
|
||||
// EulerOrder.YXZ is actually better for gyroscope fix, as it can get yaw at any roll.
|
||||
// Consequentially, instead of the roll being limited, the pitch is limited to
|
||||
// 90 degrees from the yaw plane. This means trackers may be mounted upside down
|
||||
// or with incorrectly configured IMU rotation, but we will need to compensate for
|
||||
// the pitch.
|
||||
private fun fixGyroscope(sensorRotation: Quaternion): Quaternion = getYawQuaternion(sensorRotation, EulerOrder.YXZ).inv()
|
||||
private fun fixGyroscope(sensorRotation: Quaternion): Quaternion = getYawQuaternion(sensorRotation).inv()
|
||||
|
||||
private fun fixAttachment(sensorRotation: Quaternion): Quaternion = (gyroFix * sensorRotation).inv()
|
||||
|
||||
private fun fixYaw(sensorRotation: Quaternion, reference: Quaternion): Quaternion {
|
||||
var rot = sensorRotation * attachmentFix
|
||||
// We need to fix the global yaw offset for the euler yaw calculation
|
||||
if (!tracker.isHmd || tracker.trackerPosition != TrackerPosition.HEAD) {
|
||||
rot = mountingOrientation.inv() * rot * mountingOrientation
|
||||
}
|
||||
rot = mountRotFix.inv() * rot * mountRotFix
|
||||
// TODO: Get diff from ref to rot, use euler angle (YZX) yaw as output.
|
||||
// This prevents pitch and roll from affecting the alignment.
|
||||
var rot = gyroFix * sensorRotation
|
||||
rot *= attachmentFix
|
||||
rot = mountRotFix.inv() * (rot * mountRotFix)
|
||||
rot = getYawQuaternion(rot)
|
||||
return rot.inv() * reference.project(Vector3.POS_Y).unit()
|
||||
}
|
||||
@@ -483,7 +485,7 @@ class TrackerResetsHandler(val tracker: Tracker) {
|
||||
// In both cases, the isolated yaw value changes
|
||||
// with the tracker's roll when pointing forward.
|
||||
// calling twinNearest() makes sure this rotation has the wanted polarity (+-).
|
||||
private fun getYawQuaternion(rot: Quaternion, order: EulerOrder = EulerOrder.YZX): Quaternion = EulerAngles(order, 0f, rot.toEulerAngles(order).y, 0f).toQuaternion().twinNearest(rot)
|
||||
private fun getYawQuaternion(rot: Quaternion): Quaternion = EulerAngles(EulerOrder.YZX, 0f, rot.toEulerAngles(EulerOrder.YZX).y, 0f).toQuaternion().twinNearest(rot)
|
||||
|
||||
private fun makeIdentityAdjustmentQuatsFull() {
|
||||
val sensorRotation = tracker.getRawRotation()
|
||||
|
||||
@@ -11,6 +11,7 @@ import dev.slimevr.tracking.trackers.Tracker
|
||||
import dev.slimevr.tracking.trackers.TrackerStatus
|
||||
import dev.slimevr.tracking.trackers.TrackerUtils
|
||||
import dev.slimevr.tracking.trackers.udp.TrackerDataType
|
||||
import io.github.axisangles.ktmath.Quaternion
|
||||
import solarxr_protocol.datatypes.DeviceIdT
|
||||
import solarxr_protocol.datatypes.TrackerIdT
|
||||
import solarxr_protocol.rpc.*
|
||||
@@ -199,7 +200,8 @@ class TrackingChecklistManager(private val vrServer: VRServer) : VRCConfigListen
|
||||
}
|
||||
// We ask for a full reset if you need to do mounting calibration but cant because you haven't done full reset in a while
|
||||
// or if you have trackers that need reset after re-assigning
|
||||
val needFullReset = (!resetMountingCompleted && !vrServer.serverGuards.canDoMounting) || trackerRequireReset.isNotEmpty()
|
||||
val usingSavedCalibration = vrServer.configManager.vrConfig.resetsConfig.saveMountingReset && imuTrackers.all { it.resetsHandler.mountRotFix != Quaternion.IDENTITY }
|
||||
val needFullReset = (vrServer.configManager.vrConfig.resetsConfig.lastMountingMethod == MountingMethods.AUTOMATIC && !usingSavedCalibration && !resetMountingCompleted && !vrServer.serverGuards.canDoMounting) || trackerRequireReset.isNotEmpty()
|
||||
updateValidity(TrackingChecklistStepId.FULL_RESET, !needFullReset) {
|
||||
it.enabled = imuTrackers.isNotEmpty()
|
||||
if (trackerRequireReset.isNotEmpty()) {
|
||||
|
||||
@@ -93,13 +93,13 @@ class SkeletonResetTests {
|
||||
TrackerPosition.HIP,
|
||||
TrackerPosition.LEFT_LOWER_LEG,
|
||||
TrackerPosition.RIGHT_LOWER_LEG,
|
||||
-> mountRot
|
||||
-> mountRot * Quaternion.SLIMEVR.FRONT
|
||||
|
||||
TrackerPosition.LEFT_UPPER_LEG,
|
||||
TrackerPosition.RIGHT_UPPER_LEG,
|
||||
-> mountRot * Quaternion.SLIMEVR.FRONT
|
||||
-> mountRot
|
||||
|
||||
else -> mountRot * Quaternion.SLIMEVR.FRONT
|
||||
else -> mountRot
|
||||
}
|
||||
val actualMounting = tracker.resetsHandler.mountRotFix
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import dev.slimevr.desktop.platform.ProtobufMessages.*
|
||||
import dev.slimevr.tracking.trackers.Tracker
|
||||
import dev.slimevr.tracking.trackers.TrackerStatus
|
||||
import dev.slimevr.tracking.trackers.TrackerStatus.Companion.getById
|
||||
import dev.slimevr.tracking.trackers.TrackerUtils
|
||||
import dev.slimevr.util.ann.VRServerThread
|
||||
import io.eiren.util.ann.Synchronize
|
||||
import io.eiren.util.ann.ThreadSafe
|
||||
@@ -218,6 +219,11 @@ abstract class ProtobufBridge(@JvmField protected val bridgeName: String) : ISte
|
||||
|
||||
"mounting_reset" -> instance.resetTrackersMounting(resetSourceName)
|
||||
|
||||
"feet_mounting_reset" -> instance.resetTrackersMounting(
|
||||
resetSourceName,
|
||||
TrackerUtils.feetsBodyParts,
|
||||
)
|
||||
|
||||
"pause_tracking" ->
|
||||
instance
|
||||
.togglePauseTracking(resetSourceName)
|
||||
|
||||
@@ -3558,6 +3558,20 @@ public final class ProtobufMessages {
|
||||
* @return The trackerRole.
|
||||
*/
|
||||
int getTrackerRole();
|
||||
|
||||
/**
|
||||
* <code>string manufacturer = 5;</code>
|
||||
*
|
||||
* @return The manufacturer.
|
||||
*/
|
||||
java.lang.String getManufacturer();
|
||||
|
||||
/**
|
||||
* <code>string manufacturer = 5;</code>
|
||||
*
|
||||
* @return The bytes for manufacturer.
|
||||
*/
|
||||
com.google.protobuf.ByteString getManufacturerBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3588,6 +3602,7 @@ public final class ProtobufMessages {
|
||||
private TrackerAdded() {
|
||||
trackerSerial_ = "";
|
||||
trackerName_ = "";
|
||||
manufacturer_ = "";
|
||||
}
|
||||
|
||||
public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
|
||||
@@ -3713,6 +3728,48 @@ public final class ProtobufMessages {
|
||||
return trackerRole_;
|
||||
}
|
||||
|
||||
public static final int MANUFACTURER_FIELD_NUMBER = 5;
|
||||
@SuppressWarnings("serial")
|
||||
private volatile java.lang.Object manufacturer_ = "";
|
||||
|
||||
/**
|
||||
* <code>string manufacturer = 5;</code>
|
||||
*
|
||||
* @return The manufacturer.
|
||||
*/
|
||||
@java.lang.Override
|
||||
public java.lang.String getManufacturer() {
|
||||
java.lang.Object ref = manufacturer_;
|
||||
if (ref instanceof java.lang.String) {
|
||||
return (java.lang.String) ref;
|
||||
} else {
|
||||
com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
|
||||
java.lang.String s = bs.toStringUtf8();
|
||||
manufacturer_ = s;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <code>string manufacturer = 5;</code>
|
||||
*
|
||||
* @return The bytes for manufacturer.
|
||||
*/
|
||||
@java.lang.Override
|
||||
public com.google.protobuf.ByteString getManufacturerBytes() {
|
||||
java.lang.Object ref = manufacturer_;
|
||||
if (ref instanceof java.lang.String) {
|
||||
com.google.protobuf.ByteString b = com.google.protobuf.ByteString
|
||||
.copyFromUtf8(
|
||||
(java.lang.String) ref
|
||||
);
|
||||
manufacturer_ = b;
|
||||
return b;
|
||||
} else {
|
||||
return (com.google.protobuf.ByteString) ref;
|
||||
}
|
||||
}
|
||||
|
||||
private byte memoizedIsInitialized = -1;
|
||||
|
||||
@java.lang.Override
|
||||
@@ -3742,6 +3799,9 @@ public final class ProtobufMessages {
|
||||
if (trackerRole_ != 0) {
|
||||
output.writeInt32(4, trackerRole_);
|
||||
}
|
||||
if (!com.google.protobuf.GeneratedMessage.isStringEmpty(manufacturer_)) {
|
||||
com.google.protobuf.GeneratedMessage.writeString(output, 5, manufacturer_);
|
||||
}
|
||||
getUnknownFields().writeTo(output);
|
||||
}
|
||||
|
||||
@@ -3766,6 +3826,9 @@ public final class ProtobufMessages {
|
||||
size += com.google.protobuf.CodedOutputStream
|
||||
.computeInt32Size(4, trackerRole_);
|
||||
}
|
||||
if (!com.google.protobuf.GeneratedMessage.isStringEmpty(manufacturer_)) {
|
||||
size += com.google.protobuf.GeneratedMessage.computeStringSize(5, manufacturer_);
|
||||
}
|
||||
size += getUnknownFields().getSerializedSize();
|
||||
memoizedSize = size;
|
||||
return size;
|
||||
@@ -3801,6 +3864,11 @@ public final class ProtobufMessages {
|
||||
!= other.getTrackerRole()
|
||||
)
|
||||
return false;
|
||||
if (
|
||||
!getManufacturer()
|
||||
.equals(other.getManufacturer())
|
||||
)
|
||||
return false;
|
||||
if (!getUnknownFields().equals(other.getUnknownFields()))
|
||||
return false;
|
||||
return true;
|
||||
@@ -3821,6 +3889,8 @@ public final class ProtobufMessages {
|
||||
hash = (53 * hash) + getTrackerName().hashCode();
|
||||
hash = (37 * hash) + TRACKER_ROLE_FIELD_NUMBER;
|
||||
hash = (53 * hash) + getTrackerRole();
|
||||
hash = (37 * hash) + MANUFACTURER_FIELD_NUMBER;
|
||||
hash = (53 * hash) + getManufacturer().hashCode();
|
||||
hash = (29 * hash) + getUnknownFields().hashCode();
|
||||
memoizedHashCode = hash;
|
||||
return hash;
|
||||
@@ -3993,6 +4063,7 @@ public final class ProtobufMessages {
|
||||
trackerSerial_ = "";
|
||||
trackerName_ = "";
|
||||
trackerRole_ = 0;
|
||||
manufacturer_ = "";
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -4044,6 +4115,9 @@ public final class ProtobufMessages {
|
||||
if (((from_bitField0_ & 0x00000008) != 0)) {
|
||||
result.trackerRole_ = trackerRole_;
|
||||
}
|
||||
if (((from_bitField0_ & 0x00000010) != 0)) {
|
||||
result.manufacturer_ = manufacturer_;
|
||||
}
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
@@ -4083,6 +4157,11 @@ public final class ProtobufMessages {
|
||||
if (other.getTrackerRole() != 0) {
|
||||
setTrackerRole(other.getTrackerRole());
|
||||
}
|
||||
if (!other.getManufacturer().isEmpty()) {
|
||||
manufacturer_ = other.manufacturer_;
|
||||
bitField0_ |= 0x00000010;
|
||||
onChanged();
|
||||
}
|
||||
this.mergeUnknownFields(other.getUnknownFields());
|
||||
onChanged();
|
||||
return this;
|
||||
@@ -4130,6 +4209,11 @@ public final class ProtobufMessages {
|
||||
bitField0_ |= 0x00000008;
|
||||
break;
|
||||
} // case 32
|
||||
case 42: {
|
||||
manufacturer_ = input.readStringRequireUtf8();
|
||||
bitField0_ |= 0x00000010;
|
||||
break;
|
||||
} // case 42
|
||||
default: {
|
||||
if (!super.parseUnknownField(input, extensionRegistry, tag)) {
|
||||
done = true; // was an endgroup tag
|
||||
@@ -4398,6 +4482,93 @@ public final class ProtobufMessages {
|
||||
return this;
|
||||
}
|
||||
|
||||
private java.lang.Object manufacturer_ = "";
|
||||
|
||||
/**
|
||||
* <code>string manufacturer = 5;</code>
|
||||
*
|
||||
* @return The manufacturer.
|
||||
*/
|
||||
public java.lang.String getManufacturer() {
|
||||
java.lang.Object ref = manufacturer_;
|
||||
if (!(ref instanceof java.lang.String)) {
|
||||
com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
|
||||
java.lang.String s = bs.toStringUtf8();
|
||||
manufacturer_ = s;
|
||||
return s;
|
||||
} else {
|
||||
return (java.lang.String) ref;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <code>string manufacturer = 5;</code>
|
||||
*
|
||||
* @return The bytes for manufacturer.
|
||||
*/
|
||||
public com.google.protobuf.ByteString getManufacturerBytes() {
|
||||
java.lang.Object ref = manufacturer_;
|
||||
if (ref instanceof String) {
|
||||
com.google.protobuf.ByteString b = com.google.protobuf.ByteString
|
||||
.copyFromUtf8(
|
||||
(java.lang.String) ref
|
||||
);
|
||||
manufacturer_ = b;
|
||||
return b;
|
||||
} else {
|
||||
return (com.google.protobuf.ByteString) ref;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <code>string manufacturer = 5;</code>
|
||||
*
|
||||
* @param value The manufacturer to set.
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder setManufacturer(
|
||||
java.lang.String value
|
||||
) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
manufacturer_ = value;
|
||||
bitField0_ |= 0x00000010;
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* <code>string manufacturer = 5;</code>
|
||||
*
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder clearManufacturer() {
|
||||
manufacturer_ = getDefaultInstance().getManufacturer();
|
||||
bitField0_ = (bitField0_ & ~0x00000010);
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* <code>string manufacturer = 5;</code>
|
||||
*
|
||||
* @param value The bytes for manufacturer to set.
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder setManufacturerBytes(
|
||||
com.google.protobuf.ByteString value
|
||||
) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
checkByteStringIsUtf8(value);
|
||||
manufacturer_ = value;
|
||||
bitField0_ |= 0x00000010;
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(builder_scope:messages.TrackerAdded)
|
||||
}
|
||||
|
||||
@@ -8872,53 +9043,55 @@ public final class ProtobufMessages {
|
||||
+
|
||||
"ctionArgumentsEntry\0326\n\024ActionArgumentsEn"
|
||||
+
|
||||
"try\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"f\n\014T"
|
||||
"try\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"|\n\014T"
|
||||
+
|
||||
"rackerAdded\022\022\n\ntracker_id\030\001 \001(\005\022\026\n\016track"
|
||||
+
|
||||
"er_serial\030\002 \001(\t\022\024\n\014tracker_name\030\003 \001(\t\022\024\n"
|
||||
+
|
||||
"\014tracker_role\030\004 \001(\005\"\374\002\n\rTrackerStatus\022\022\n"
|
||||
"\014tracker_role\030\004 \001(\005\022\024\n\014manufacturer\030\005 \001("
|
||||
+
|
||||
"\ntracker_id\030\001 \001(\005\022.\n\006status\030\002 \001(\0162\036.mess"
|
||||
"\t\"\374\002\n\rTrackerStatus\022\022\n\ntracker_id\030\001 \001(\005\022"
|
||||
+
|
||||
"ages.TrackerStatus.Status\0221\n\005extra\030\003 \003(\013"
|
||||
".\n\006status\030\002 \001(\0162\036.messages.TrackerStatus"
|
||||
+
|
||||
"2\".messages.TrackerStatus.ExtraEntry\022;\n\n"
|
||||
".Status\0221\n\005extra\030\003 \003(\0132\".messages.Tracke"
|
||||
+
|
||||
"confidence\030\004 \001(\0162\".messages.TrackerStatu"
|
||||
"rStatus.ExtraEntry\022;\n\nconfidence\030\004 \001(\0162\""
|
||||
+
|
||||
"s.ConfidenceH\000\210\001\001\032,\n\nExtraEntry\022\013\n\003key\030\001"
|
||||
".messages.TrackerStatus.ConfidenceH\000\210\001\001\032"
|
||||
+
|
||||
" \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"E\n\006Status\022\020\n\014DIS"
|
||||
",\n\nExtraEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001("
|
||||
+
|
||||
"CONNECTED\020\000\022\006\n\002OK\020\001\022\010\n\004BUSY\020\002\022\t\n\005ERROR\020\003"
|
||||
"\t:\0028\001\"E\n\006Status\022\020\n\014DISCONNECTED\020\000\022\006\n\002OK\020"
|
||||
+
|
||||
"\022\014\n\010OCCLUDED\020\004\"3\n\nConfidence\022\006\n\002NO\020\000\022\007\n\003"
|
||||
"\001\022\010\n\004BUSY\020\002\022\t\n\005ERROR\020\003\022\014\n\010OCCLUDED\020\004\"3\n\n"
|
||||
+
|
||||
"LOW\020\001\022\n\n\006MEDIUM\020\005\022\010\n\004HIGH\020\nB\r\n\013_confiden"
|
||||
"Confidence\022\006\n\002NO\020\000\022\007\n\003LOW\020\001\022\n\n\006MEDIUM\020\005\022"
|
||||
+
|
||||
"ce\"I\n\007Battery\022\022\n\ntracker_id\030\001 \001(\005\022\025\n\rbat"
|
||||
"\010\n\004HIGH\020\nB\r\n\013_confidence\"I\n\007Battery\022\022\n\nt"
|
||||
+
|
||||
"tery_level\030\002 \001(\002\022\023\n\013is_charging\030\003 \001(\010\"\241\002"
|
||||
"racker_id\030\001 \001(\005\022\025\n\rbattery_level\030\002 \001(\002\022\023"
|
||||
+
|
||||
"\n\017ProtobufMessage\022&\n\010position\030\001 \001(\0132\022.me"
|
||||
"\n\013is_charging\030\003 \001(\010\"\241\002\n\017ProtobufMessage\022"
|
||||
+
|
||||
"ssages.PositionH\000\022+\n\013user_action\030\002 \001(\0132\024"
|
||||
"&\n\010position\030\001 \001(\0132\022.messages.PositionH\000\022"
|
||||
+
|
||||
".messages.UserActionH\000\022/\n\rtracker_added\030"
|
||||
"+\n\013user_action\030\002 \001(\0132\024.messages.UserActi"
|
||||
+
|
||||
"\003 \001(\0132\026.messages.TrackerAddedH\000\0221\n\016track"
|
||||
"onH\000\022/\n\rtracker_added\030\003 \001(\0132\026.messages.T"
|
||||
+
|
||||
"er_status\030\004 \001(\0132\027.messages.TrackerStatus"
|
||||
"rackerAddedH\000\0221\n\016tracker_status\030\004 \001(\0132\027."
|
||||
+
|
||||
"H\000\022$\n\007battery\030\005 \001(\0132\021.messages.BatteryH\000"
|
||||
"messages.TrackerStatusH\000\022$\n\007battery\030\005 \001("
|
||||
+
|
||||
"\022$\n\007version\030\006 \001(\0132\021.messages.VersionH\000B\t"
|
||||
"\0132\021.messages.BatteryH\000\022$\n\007version\030\006 \001(\0132"
|
||||
+
|
||||
"\n\007messageB2\n\034dev.slimevr.desktop.platfor"
|
||||
"\021.messages.VersionH\000B\t\n\007messageB2\n\034dev.s"
|
||||
+
|
||||
"mB\020ProtobufMessagesH\003b\006proto3"
|
||||
"limevr.desktop.platformB\020ProtobufMessage"
|
||||
+
|
||||
"sH\003b\006proto3"
|
||||
};
|
||||
descriptor = com.google.protobuf.Descriptors.FileDescriptor
|
||||
.internalBuildGeneratedFileFrom(
|
||||
@@ -8957,7 +9130,8 @@ public final class ProtobufMessages {
|
||||
internal_static_messages_TrackerAdded_descriptor = getDescriptor().getMessageTypes().get(4);
|
||||
internal_static_messages_TrackerAdded_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable(
|
||||
internal_static_messages_TrackerAdded_descriptor,
|
||||
new java.lang.String[] { "TrackerId", "TrackerSerial", "TrackerName", "TrackerRole", }
|
||||
new java.lang.String[] { "TrackerId", "TrackerSerial", "TrackerName", "TrackerRole",
|
||||
"Manufacturer", }
|
||||
);
|
||||
internal_static_messages_TrackerStatus_descriptor = getDescriptor()
|
||||
.getMessageTypes()
|
||||
|
||||
@@ -147,23 +147,13 @@ abstract class SteamVRBridge(
|
||||
val device = instance.deviceManager
|
||||
.createDevice(
|
||||
trackerAdded.trackerName,
|
||||
trackerAdded.trackerSerial,
|
||||
"OpenVR", // TODO : We need the manufacturer
|
||||
null,
|
||||
trackerAdded.manufacturer.ifEmpty { "OpenVR" },
|
||||
)
|
||||
|
||||
// Display name, needsReset and isHmd
|
||||
val displayName: String
|
||||
val isHmd = if (trackerAdded.trackerId == 0) {
|
||||
displayName = if (trackerAdded.trackerName == "HMD") {
|
||||
"SteamVR Driver HMD"
|
||||
} else {
|
||||
"Feeder App HMD"
|
||||
}
|
||||
true
|
||||
} else {
|
||||
displayName = trackerAdded.trackerName
|
||||
false
|
||||
}
|
||||
val displayName: String = trackerAdded.trackerName
|
||||
val isHmd = trackerAdded.trackerId == 0
|
||||
|
||||
// trackerPosition
|
||||
val role = getById(trackerAdded.trackerRole)
|
||||
|
||||
Submodule solarxr-protocol updated: fa2895b19a...c76469b50a
Reference in New Issue
Block a user