Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic motion compensation #1045

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions gui/public/i18n/en/translation.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ body_part-LEFT_HAND = Left hand
body_part-LEFT_UPPER_LEG = Left thigh
body_part-LEFT_LOWER_LEG = Left ankle
body_part-LEFT_FOOT = Left foot
body_part-PLAYSPACE = Playspace (motion compensation)

## Proportions
skeleton_bone-NONE = None
Expand Down
3 changes: 3 additions & 0 deletions gui/src/components/commons/BodyPartIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ export const mapPart: Record<
<UpperLegIcon width={width} flipped></UpperLegIcon>
),
[BodyPart.WAIST]: ({ width }) => <WaistIcon width={width}></WaistIcon>,
[BodyPart.PLAYSPACE]: ({ width }) => (
<SlimeVRIcon width={width}></SlimeVRIcon>
), // TODO
};

export function BodyPartIcon({
Expand Down
10 changes: 10 additions & 0 deletions gui/src/components/onboarding/BodyAssignment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,16 @@ export function BodyAssignment({
onClick={() => onRoleSelected(SIDES[right].foot)}
direction="left"
/>
{advanced && (
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[BodyPart.PLAYSPACE]?.label}
td={trackerPartGrouped[BodyPart.PLAYSPACE]}
role={BodyPart.PLAYSPACE}
onClick={() => onRoleSelected(BodyPart.PLAYSPACE)}
direction="left"
/>
)}
</div>
</div>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ export const mapPart: Record<
<FootIcon width={width} flipped></FootIcon>
),
[BodyPart.WAIST]: ({ width }) => <FootIcon width={width}></FootIcon>,
[BodyPart.PLAYSPACE]: ({ width }) => <FootIcon width={width}></FootIcon>,
};

export function MountingBodyPartIcon({
Expand Down
3 changes: 3 additions & 0 deletions gui/src/utils/skeletonHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ export class BoneKind extends Bone {

get boneColor(): Color {
switch (this.boneT.bodyPart) {
case BodyPart.PLAYSPACE:
case BodyPart.NONE:
throw 'Unexpected body part';
case BodyPart.HEAD:
Expand Down Expand Up @@ -230,6 +231,7 @@ export class BoneKind extends Bone {

static children(part: BodyPart): BodyPart[] {
switch (part) {
case BodyPart.PLAYSPACE:
case BodyPart.NONE:
throw 'Unexpected body part';
case BodyPart.HEAD:
Expand Down Expand Up @@ -283,6 +285,7 @@ export class BoneKind extends Bone {

static parent(part: BodyPart): BodyPart | null {
switch (part) {
case BodyPart.PLAYSPACE:
case BodyPart.NONE:
throw 'Unexpected body part';
case BodyPart.HEAD:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,19 @@ class Bone(val boneType: BoneType) {
fun getLocalRotation(): Quaternion = headNode.localTransform.rotation

/**
* Sets the global rotation of the bone
* Sets the global rotation of the bone with the rotationOffset
*/
fun setRotation(rotation: Quaternion) {
headNode.localTransform.rotation = rotation * rotationOffset
}

/**
* Sets the global rotation of the bone
*/
fun setRawRotation(rotation: Quaternion) {
headNode.localTransform.rotation = rotation
}

/**
* Returns the global position of the head of the bone
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ class HumanPoseManager(val server: VRServer?) {
*/
val trackersToReset: List<Tracker?>
get() =
server?.allTrackers ?: skeleton.localTrackers
server?.allTrackers ?: skeleton.trackersToReset

/**
* @return the head bone, which is the root of the skeleton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ class HumanSkeleton(
var rightHandTracker: Tracker? = null
var leftShoulderTracker: Tracker? = null
var rightShoulderTracker: Tracker? = null
var playspaceTracker: Tracker? = null

// Output trackers
var computedHeadTracker: Tracker? = null
Expand Down Expand Up @@ -278,6 +279,7 @@ class HumanSkeleton(
rightHandTracker = getTrackerForSkeleton(trackers, TrackerPosition.RIGHT_HAND)
leftShoulderTracker = getTrackerForSkeleton(trackers, TrackerPosition.LEFT_SHOULDER)
rightShoulderTracker = getTrackerForSkeleton(trackers, TrackerPosition.RIGHT_SHOULDER)
playspaceTracker = getTrackerForSkeleton(trackers, TrackerPosition.PLAYSPACE)

// Check for specific conditions and store them in booleans.
hasSpineTracker = upperChestTracker != null || chestTracker != null || waistTracker != null || hipTracker != null
Expand Down Expand Up @@ -354,18 +356,45 @@ class HumanSkeleton(
*/
@VRServerThread
fun updatePose() {
// Check taps for resets
tapDetectionManager.update()

// Do FK
updateTransforms()

// Update bones and output trackers
updateBones()
updateComputedTrackers()

// Don't run post-processing if the tracking is paused
if (pauseTracking) return

// Run Legtweaks
legTweaks.tweakLegs()

// Run Mocap mode
localizer.update()

// Run Vive hip emulation
viveEmulation.update()

// Playspace motion compensation
playspaceTracker?.let {
if (it.hasRotation) {
val motionCompensationRotOffset = it.getRotation().inv()
for (bone in allBones) {
bone.setRawRotation(motionCompensationRotOffset * bone.getLocalRotation())
}
}
if (it.hasPosition) {
// TODO motion compensate for position as well?
// headBone.setPosition(headBone.getPosition() - it.position)
}

// Update bones and output trackers
updateBones()
updateComputedTrackers()
}
}

/**
Expand All @@ -390,6 +419,7 @@ class HumanSkeleton(

// Spine
updateSpineTransforms()

// Left leg
updateLegTransforms(
leftUpperLegBone,
Expand All @@ -401,6 +431,7 @@ class HumanSkeleton(
leftLowerLegTracker,
leftFootTracker,
)

// Right leg
updateLegTransforms(
rightUpperLegBone,
Expand All @@ -412,6 +443,7 @@ class HumanSkeleton(
rightLowerLegTracker,
rightFootTracker,
)

// Left arm
updateArmTransforms(
isTrackingLeftArmFromController,
Expand All @@ -426,6 +458,7 @@ class HumanSkeleton(
leftLowerArmTracker,
leftHandTracker,
)

// Right arm
updateArmTransforms(
isTrackingRightArmFromController,
Expand Down Expand Up @@ -982,6 +1015,34 @@ class HumanSkeleton(
rightHandBone,
)

/**
* Returns an array of all the bones, trackers or not
*/
private val allBones: Array<Bone>
get() = arrayOf(
headBone,
neckBone,
headTrackerBone,
upperChestBone,
chestBone,
chestTrackerBone,
waistBone,
hipBone,
hipTrackerBone,
leftHipBone,
rightHipBone,
leftUpperLegBone,
leftKneeTrackerBone,
rightUpperLegBone,
rightKneeTrackerBone,
leftLowerLegBone,
rightLowerLegBone,
leftFootBone,
leftFootTrackerBone,
rightFootBone,
rightFootTrackerBone,
) + allArmBones

/**
* Returns all the arm bones, tracker or not.
*/
Expand Down Expand Up @@ -1023,7 +1084,7 @@ class HumanSkeleton(
*/
val isTrackingRightArmFromController: Boolean
get() = rightHandTracker != null && rightHandTracker!!.hasPosition && !forceArmsFromHMD
val localTrackers: List<Tracker?>
val trackersToReset: List<Tracker?>
get() = listOf(
neckTracker,
chestTracker,
Expand All @@ -1046,22 +1107,23 @@ class HumanSkeleton(
)

fun resetTrackersFull(resetSourceName: String?) {
val trackersToReset = humanPoseManager.trackersToReset

// Resets all axis of the trackers with the HMD as reference.
var referenceRotation = IDENTITY
// Reset the head tracker from identity if needed, else store its rotation
headTracker?.let {
if (it.needsReset) {
it.resetsHandler.resetFull(referenceRotation)
} else {
referenceRotation = it.getRotation()
}
}
// Resets the trackers with the HMD as reference.
for (tracker in trackersToReset) {
if (tracker != null && tracker.needsReset) {
tracker.resetsHandler.resetFull(referenceRotation)
}
}
// Reset the playspace tracker from identity rotation
playspaceTracker?.resetsHandler?.resetFull(IDENTITY)

// Tell floorclip to reset its floor level on the next update
// of the computed trackers
Expand All @@ -1075,53 +1137,53 @@ class HumanSkeleton(

@VRServerThread
fun resetTrackersYaw(resetSourceName: String?) {
val trackersToReset = humanPoseManager.trackersToReset

// Resets the yaw of the trackers with the head as reference.
var referenceRotation = IDENTITY
// Reset the head tracker from identity if needed, else store its rotation
headTracker?.let {
if (it.needsReset) {
it.resetsHandler.resetYaw(referenceRotation)
} else {
referenceRotation = it.getRotation()
}
}
// Resets the trackers with the HMD as reference.
for (tracker in trackersToReset) {
if (tracker != null && tracker.needsReset) {
tracker.resetsHandler.resetYaw(referenceRotation)
}
}
// Reset the playspace tracker from identity rotation
playspaceTracker?.resetsHandler?.resetYaw(IDENTITY)

legTweaks.resetBuffer()
LogManager.info(String.format("[HumanSkeleton] Reset: yaw (%s)", resetSourceName))
}

@VRServerThread
fun resetTrackersMounting(resetSourceName: String?) {
val trackersToReset = humanPoseManager.trackersToReset

// Resets the mounting orientation of the trackers with the HMD as
// reference.
var referenceRotation = IDENTITY
// Reset the head tracker from identity if needed, else store its rotation
headTracker?.let {
if (it.needsMounting) {
it.resetsHandler.resetMounting(referenceRotation)
} else {
referenceRotation = it.getRotation()
}
}
// Resets the trackers with the HMD as reference.
for (tracker in trackersToReset) {
if (tracker != null && tracker.needsMounting) {
tracker.resetsHandler.resetMounting(referenceRotation)
}
}

legTweaks.resetBuffer()
localizer.reset()
LogManager.info(String.format("[HumanSkeleton] Reset: mounting (%s)", resetSourceName))
}

@VRServerThread
fun clearTrackersMounting(resetSourceName: String?) {
val trackersToReset = humanPoseManager.trackersToReset
headTracker?.let {
if (it.needsMounting) it.resetsHandler.clearMounting()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ enum class TrackerPosition(
RIGHT_HAND("body:right_hand", TrackerRole.RIGHT_HAND, BodyPart.RIGHT_HAND),
LEFT_SHOULDER("body:left_shoulder", TrackerRole.LEFT_SHOULDER, BodyPart.LEFT_SHOULDER),
RIGHT_SHOULDER("body:right_shoulder", TrackerRole.RIGHT_SHOULDER, BodyPart.RIGHT_SHOULDER),
PLAYSPACE("body:playspace", null, BodyPart.PLAYSPACE),
;

/**
Expand Down