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

Add alternative LOSAngularOffsetHandRayPoseSource #625

Merged
merged 3 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
12 changes: 12 additions & 0 deletions org.mixedrealitytoolkit.core/Utilities/StabilizedRay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,18 @@ public StabilizedRay(float halfLife)
HalfLifeDirection = halfLife;
}

/// <summary>
/// StabilizedRay with distinct position and direction half life values.
/// HalfLife closer to zero means lerp closer to one.
/// </summary>
/// <param name="positionHalfLife">The half life used for position decay calculations.</param>
/// <param name="directionHalfLife">The half life used for direction decay calculations.</param>
public StabilizedRay(float positionHalfLife, float directionHalfLife)
{
HalfLifePosition = positionHalfLife;
HalfLifeDirection = directionHalfLife;
}

/// <summary>
/// Add sample to ray stabilizer.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion org.mixedrealitytoolkit.core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "org.mixedrealitytoolkit.core",
"version": "3.1.1-development",
"version": "3.2.0-development",
"description": "A limited collection of common interfaces and utilities that most MRTK packages share. Most implementations of these interfaces are contained in other packages in the MRTK ecosystem.",
"displayName": "MRTK Core Definitions",
"msftFeatureCategory": "MRTK3",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Copyright (c) Mixed Reality Toolkit Contributors
// Licensed under the BSD 3-Clause

using System;
using UnityEngine;
using UnityEngine.XR;

namespace MixedReality.Toolkit.Input
{
/// <summary>
/// A pose source which represents a hand ray. This hand ray is constructed by deriving it from a
/// line of sight (LOS) head to knuckle vector with angular offset applied.
/// </summary>
[Serializable]
public class LOSAngularOffsetHandRayPoseSource : HandBasedPoseSource
{
[SerializeField]
[Tooltip("The half life used for the position of the StabilizedRay. A value of 0 means no stabilization/smoothing.")]
private float stabilizedPositionHalfLife = .01f;

[SerializeField]
[Tooltip("The half life used for the direction of the StabilizedRay. A value of 0 means no stabilization/smoothing.")]
private float stabilizedDirectionHalfLife = .05f;

/// <summary>
/// The StabilizedRay used in hand ray stabilization calculations.
/// </summary>
protected Lazy<StabilizedRay> StabilizedHandRay { get; private set; }

/// <summary>
/// A cache of the knuckle joint pose returned by the hands aggregator.
/// </summary>
private HandJointPose knuckle;

private const float HeadCenterOffset = .09f;
private readonly Vector2 MinMaxYawAngleOffset = new Vector2(-12f, -35f);
private readonly Vector2 MinMaxPitchAngleOffset = new Vector2(-24f, -85f);
private const float MinMaxAngleAdjustHandProximity = .5f;

public LOSAngularOffsetHandRayPoseSource()
{
StabilizedHandRay = new Lazy<StabilizedRay>(() =>
{
return new StabilizedRay(stabilizedPositionHalfLife, stabilizedDirectionHalfLife);
});
}

/// <summary>
/// Tries to get the pose of the hand ray in world space by deriving it from a
/// line of sight head to knuckle vector with angular offset applied.
/// </summary>
public override bool TryGetPose(out Pose pose)
{
XRNode? handNode = Hand.ToXRNode();

bool poseRetrieved = handNode.HasValue;
poseRetrieved &= XRSubsystemHelpers.HandsAggregator?.TryGetJoint(TrackedHandJoint.IndexProximal, handNode.Value, out knuckle) ?? false;

if (poseRetrieved)
{
pose = CalculateHandRay(knuckle.Position, Camera.main.transform, Hand);
}
else
{
pose = Pose.identity;
}

return poseRetrieved;
}

private Pose CalculateHandRay(Vector3 handJointPosition, Transform headTransform, Handedness hand)
{
// Approximate head center to reduce the head rotation wobble effect on the hand ray.
Vector3 headCenter = headTransform.position - headTransform.forward * HeadCenterOffset;
Vector3 headToJoint = handJointPosition - headCenter;

// Adjust yaw and pitch angle offsets to more closely approximate the original hand ray orientation behavior affected by hand proximity.
float t = Mathf.InverseLerp(MinMaxAngleAdjustHandProximity, 0, headToJoint.magnitude);
float yawOffset = Mathf.Lerp(MinMaxYawAngleOffset.x, MinMaxYawAngleOffset.y, t) * (hand == Handedness.Right ? 1.0f : -1.0f);
float pitchOffset = Mathf.Lerp(MinMaxPitchAngleOffset.x, MinMaxPitchAngleOffset.y, t);

Quaternion rayRotation = Quaternion.LookRotation(headToJoint, headTransform.up) * Quaternion.Euler(pitchOffset, yawOffset, 0);

if (stabilizedPositionHalfLife > 0 || stabilizedDirectionHalfLife > 0)
{
StabilizedHandRay.Value.AddSample(new Ray(handJointPosition, rayRotation * Vector3.forward));

return new Pose(StabilizedHandRay.Value.StabilizedPosition, Quaternion.LookRotation(StabilizedHandRay.Value.StabilizedDirection, headTransform.up));
}
else
{
return new Pose(handJointPosition, rayRotation);
}
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion org.mixedrealitytoolkit.input/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "org.mixedrealitytoolkit.input",
"version": "3.1.0-development",
"version": "3.2.0-development",
whebertML marked this conversation as resolved.
Show resolved Hide resolved
"description": "This package contains custom interactors and controllers that build on the foundation established by Unity's XR Interaction Toolkit. In addition, it contains hand joint aggregation and simulation subsystems, which allows for a single API for both real, device-driven hands and simulated hands. \n\nThe vast majority of actual input processing is not done by this package; instead, MRTK builds on the input data and interaction fundamentals already provided by the Unity Input System and XR Interaction Toolkit. \n\nWhen using MRTK Input in a project, it is not strictly necessary to have your package take a dependency on MRTK Input; the custom interactors in this package are fully compatible with the vanilla XRI APIs, and will both parse and generate all the same events and interactions that other XRI interactors will.",
"displayName": "MRTK Input",
"msftFeatureCategory": "MRTK3",
Expand Down