Skip to content

Commit 28deb35

Browse files
Revert TrackerResetsHandler & add comments (#1748)
1 parent 4d93f87 commit 28deb35

2 files changed

Lines changed: 52 additions & 50 deletions

File tree

server/core/src/main/java/dev/slimevr/tracking/trackers/TrackerResetsHandler.kt

Lines changed: 49 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ class TrackerResetsHandler(val tracker: Tracker) {
2424
Math.PI.toFloat(),
2525
0f,
2626
).toQuaternion()
27-
private val QuarterPitch = Quaternion.rotationAroundXAxis(FastMath.HALF_PI)
28-
2927
private var driftAmount = 0f
3028
private var averagedDriftQuat = Quaternion.IDENTITY
3129
private var rotationSinceReset = Quaternion.IDENTITY
@@ -54,6 +52,16 @@ class TrackerResetsHandler(val tracker: Tracker) {
5452

5553
// Reference adjustment quats
5654

55+
/**
56+
* Gyro fix is set by full reset. This sets the current y rotation to 0, correcting
57+
* for initial yaw rotation and the rotation incurred by mounting orientation. This
58+
* is a local offset in rotation and does not affect the axes of rotation.
59+
*
60+
* This rotation is only used to compute [attachmentFix], otherwise [yawFix] would
61+
* correct for the same rotation.
62+
*/
63+
private var gyroFix = Quaternion.IDENTITY
64+
5765
/**
5866
* Attachment fix is set by full reset. This sets the current x and z rotations to
5967
* 0, correcting for initial pitch and roll rotation. This is a global offset in
@@ -180,9 +188,12 @@ class TrackerResetsHandler(val tracker: Tracker) {
180188
/**
181189
* Get the reference adjusted accel.
182190
*/
183-
// All IMU axis corrections are inverse to undo `adjustToReference` after local yaw offsets are added
184-
// Order is VERY important here! Please be extremely careful! >~>
185-
fun getReferenceAdjustedAccel(rawRot: Quaternion, accel: Vector3): Vector3 = (adjustToReference(rawRot) * (attachmentFix * mountingOrientation * mountRotFix * tposeDownFix).inv()).sandwich(accel)
191+
// TODO: Make this actually adjusted to the corrected IMU heading. The current
192+
// implementation for heading correction doesn't appear to be correct and may simply
193+
// make acceleration worse, so I'm just leaving this until we work that out. The
194+
// output of this will be world space, but with an unknown offset to heading (yaw).
195+
// - Butterscotch
196+
fun getReferenceAdjustedAccel(rawRot: Quaternion, accel: Vector3): Vector3 = rawRot.sandwich(accel)
186197

187198
/**
188199
* Converts raw or filtered rotation into reference- and
@@ -191,17 +202,22 @@ class TrackerResetsHandler(val tracker: Tracker) {
191202
*/
192203
private fun adjustToReference(rotation: Quaternion): Quaternion {
193204
var rot = rotation
194-
// Correct for global pitch/roll offset
195-
rot *= attachmentFix
196-
// Correct for global yaw offset without affecting local yaw so we can change this
197-
// later without invalidating local yaw offset corrections
205+
// Align heading axis with bone space
198206
if (!tracker.isHmd || tracker.trackerPosition != TrackerPosition.HEAD) {
199-
rot = mountingOrientation.inv() * rot * mountingOrientation
207+
rot *= mountingOrientation
200208
}
201-
rot = mountRotFix.inv() * rot * mountRotFix
202-
// T-pose global correction
209+
// Heading correction assuming manual orientation is correct
210+
rot = gyroFix * rot
211+
// Align attitude axes with bone space
212+
rot *= attachmentFix
213+
// Secondary heading axis alignment with bone space for automatic mounting
214+
// Note: Applying an inverse amount of heading correction corresponding to the
215+
// axis alignment quaternion will leave the correction to another variable
216+
rot = mountRotFix.inv() * (rot * mountRotFix)
217+
// More attitude axes alignment specifically for the t-pose configuration, this
218+
// probably shouldn't be a separate variable from attachmentFix?
203219
rot *= tposeDownFix
204-
// Align local yaw with reference
220+
// More heading correction
205221
rot = yawFix * rot
206222
rot = constraintFix * rot
207223
return rot
@@ -211,6 +227,8 @@ class TrackerResetsHandler(val tracker: Tracker) {
211227
* Converts raw or filtered rotation into zero-reference-adjusted by
212228
* applying quaternions produced after full reset and yaw reset only
213229
*/
230+
// This is essentially just adjustToReference but aligning to quaternion identity
231+
// rather than to the bone.
214232
private fun adjustToIdentity(rotation: Quaternion): Quaternion {
215233
var rot = rotation
216234
rot = gyroFixNoMounting * rot
@@ -265,23 +283,15 @@ class TrackerResetsHandler(val tracker: Tracker) {
265283
lastResetQuaternion = oldRot
266284

267285
// Adjust raw rotation to mountingOrientation
268-
val rotation = tracker.getRawRotation()
286+
val mountingAdjustedRotation = tracker.getRawRotation() * mountingOrientation
269287

270288
// Gyrofix
271-
val gyroFix = if (tracker.allowMounting || (tracker.trackerPosition == TrackerPosition.HEAD && !tracker.isHmd)) {
272-
if (tracker.isComputed) {
273-
fixGyroscope(rotation)
289+
if (tracker.allowMounting || (tracker.trackerPosition == TrackerPosition.HEAD && !tracker.isHmd)) {
290+
gyroFix = if (tracker.isComputed) {
291+
fixGyroscope(tracker.getRawRotation())
274292
} else {
275-
if (tracker.trackerPosition.isFoot()) {
276-
// Feet are rotated by 90 deg pitch, this means we're relying on IMU rotation
277-
// to be set correctly here.
278-
fixGyroscope(rotation * tposeDownFix * QuarterPitch)
279-
} else {
280-
fixGyroscope(rotation * tposeDownFix)
281-
}
293+
fixGyroscope(mountingAdjustedRotation * tposeDownFix)
282294
}
283-
} else {
284-
Quaternion.IDENTITY
285295
}
286296

287297
// Mounting for computed trackers
@@ -296,15 +306,15 @@ class TrackerResetsHandler(val tracker: Tracker) {
296306
if (resetHmdPitch) {
297307
// Reset the HMD's pitch if it's assigned to head and resetHmdPitch is true
298308
// Get rotation without yaw (make sure to use the raw rotation directly!)
299-
val rotBuf = getYawQuaternion(rotation).inv() * rotation
309+
val rotBuf = getYawQuaternion(tracker.getRawRotation()).inv() * tracker.getRawRotation()
300310
// Isolate pitch
301311
Quaternion(rotBuf.w, -rotBuf.x, 0f, 0f).unit()
302312
} else {
303313
// Don't reset the HMD at all
304314
Quaternion.IDENTITY
305315
}
306316
} else {
307-
(gyroFix * rotation).inv()
317+
fixAttachment(mountingAdjustedRotation)
308318
}
309319

310320
// Rotate attachmentFix by 180 degrees as a workaround for t-pose (down)
@@ -316,7 +326,7 @@ class TrackerResetsHandler(val tracker: Tracker) {
316326

317327
// Don't adjust yaw if head and computed
318328
if (tracker.trackerPosition != TrackerPosition.HEAD || !tracker.isComputed) {
319-
yawFix = gyroFix * reference.project(Vector3.POS_Y).unit()
329+
yawFix = fixYaw(mountingAdjustedRotation, reference)
320330
tracker.yawResetSmoothing.reset()
321331
}
322332

@@ -360,7 +370,7 @@ class TrackerResetsHandler(val tracker: Tracker) {
360370
lastResetQuaternion = oldRot
361371

362372
val yawFixOld = yawFix
363-
yawFix = fixYaw(tracker.getRawRotation(), reference)
373+
yawFix = fixYaw(tracker.getRawRotation() * mountingOrientation, reference)
364374
tracker.yawResetSmoothing.reset()
365375

366376
makeIdentityAdjustmentQuatsYaw()
@@ -399,9 +409,9 @@ class TrackerResetsHandler(val tracker: Tracker) {
399409
constraintFix = Quaternion.IDENTITY
400410

401411
// Get the current calibrated rotation
402-
var rotBuf = adjustToDrift(tracker.getRawRotation())
412+
var rotBuf = adjustToDrift(tracker.getRawRotation() * mountingOrientation)
413+
rotBuf = gyroFix * rotBuf
403414
rotBuf *= attachmentFix
404-
rotBuf = mountingOrientation.inv() * rotBuf * mountingOrientation
405415
rotBuf = yawFix * rotBuf
406416

407417
// Adjust buffer to reference
@@ -457,22 +467,14 @@ class TrackerResetsHandler(val tracker: Tracker) {
457467
mountRotFix = Quaternion.IDENTITY
458468
}
459469

460-
// EulerOrder.YXZ is actually better for gyroscope fix, as it can get yaw at any roll.
461-
// Consequentially, instead of the roll being limited, the pitch is limited to
462-
// 90 degrees from the yaw plane. This means trackers may be mounted upside down
463-
// or with incorrectly configured IMU rotation, but we will need to compensate for
464-
// the pitch.
465-
private fun fixGyroscope(sensorRotation: Quaternion): Quaternion = getYawQuaternion(sensorRotation, EulerOrder.YXZ).inv()
470+
private fun fixGyroscope(sensorRotation: Quaternion): Quaternion = getYawQuaternion(sensorRotation).inv()
471+
472+
private fun fixAttachment(sensorRotation: Quaternion): Quaternion = (gyroFix * sensorRotation).inv()
466473

467474
private fun fixYaw(sensorRotation: Quaternion, reference: Quaternion): Quaternion {
468-
var rot = sensorRotation * attachmentFix
469-
// We need to fix the global yaw offset for the euler yaw calculation
470-
if (!tracker.isHmd || tracker.trackerPosition != TrackerPosition.HEAD) {
471-
rot = mountingOrientation.inv() * rot * mountingOrientation
472-
}
473-
rot = mountRotFix.inv() * rot * mountRotFix
474-
// TODO: Get diff from ref to rot, use euler angle (YZX) yaw as output.
475-
// This prevents pitch and roll from affecting the alignment.
475+
var rot = gyroFix * sensorRotation
476+
rot *= attachmentFix
477+
rot = mountRotFix.inv() * (rot * mountRotFix)
476478
rot = getYawQuaternion(rot)
477479
return rot.inv() * reference.project(Vector3.POS_Y).unit()
478480
}
@@ -483,7 +485,7 @@ class TrackerResetsHandler(val tracker: Tracker) {
483485
// In both cases, the isolated yaw value changes
484486
// with the tracker's roll when pointing forward.
485487
// calling twinNearest() makes sure this rotation has the wanted polarity (+-).
486-
private fun getYawQuaternion(rot: Quaternion, order: EulerOrder = EulerOrder.YZX): Quaternion = EulerAngles(order, 0f, rot.toEulerAngles(order).y, 0f).toQuaternion().twinNearest(rot)
488+
private fun getYawQuaternion(rot: Quaternion): Quaternion = EulerAngles(EulerOrder.YZX, 0f, rot.toEulerAngles(EulerOrder.YZX).y, 0f).toQuaternion().twinNearest(rot)
487489

488490
private fun makeIdentityAdjustmentQuatsFull() {
489491
val sensorRotation = tracker.getRawRotation()

server/core/src/test/java/dev/slimevr/unit/SkeletonResetTests.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,13 @@ class SkeletonResetTests {
9393
TrackerPosition.HIP,
9494
TrackerPosition.LEFT_LOWER_LEG,
9595
TrackerPosition.RIGHT_LOWER_LEG,
96-
-> mountRot
96+
-> mountRot * Quaternion.SLIMEVR.FRONT
9797

9898
TrackerPosition.LEFT_UPPER_LEG,
9999
TrackerPosition.RIGHT_UPPER_LEG,
100-
-> mountRot * Quaternion.SLIMEVR.FRONT
100+
-> mountRot
101101

102-
else -> mountRot * Quaternion.SLIMEVR.FRONT
102+
else -> mountRot
103103
}
104104
val actualMounting = tracker.resetsHandler.mountRotFix
105105

0 commit comments

Comments
 (0)