Skip to content

Commit 9e8f1d6

Browse files
committed
Merge branch 'release/5.6.0' into 'main'
Release 5.6.0 See merge request xr/integrations/unityplugin!199
2 parents aac368d + 9fdd8a6 commit 9e8f1d6

File tree

78 files changed

+15357
-677
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+15357
-677
lines changed

Packages/Tracking Preview/AggregationProviders.meta

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
/******************************************************************************
2+
* Copyright (C) Ultraleap, Inc. 2011-2021. *
3+
* *
4+
* Use subject to the terms of the Apache License 2.0 available at *
5+
* http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
6+
* between Ultraleap and you, your company or other organization. *
7+
******************************************************************************/
8+
9+
using Leap.Unity.Encoding;
10+
using System.Collections;
11+
using System.Collections.Generic;
12+
using UnityEngine;
13+
14+
15+
namespace Leap.Unity
16+
{
17+
18+
/// <summary>
19+
/// John's and Flo's aggregation code. An example of how aggregation could be implemented.
20+
/// only works for the first two hands it sees (of the same chirality)
21+
/// </summary>
22+
public class AggregationProviderAngularInterpolation : LeapAggregatedProviderBase
23+
{
24+
25+
private Vector3 tempHandPalmPosition;
26+
private Vector3 midDevicePointPosition;
27+
private Vector3 midDevicePointForward;
28+
private Vector3 midDevicePointUp;
29+
30+
public float cam1Aplha;
31+
public float cam2Aplha;
32+
33+
public float leftAngle;
34+
public float rightAngle;
35+
36+
public float maxInterpolationAngle = 60;
37+
38+
public Transform midpointDevices; //used to calculate relative angle and weight hands accordingly. Transform should face direction that bisects FOV of devices
39+
40+
41+
protected override Frame MergeFrames(Frame[] frames)
42+
{
43+
Frame mergedFrame = frames[0];
44+
Hand[] mergedHands = MergeHands(frames);
45+
mergedFrame.Hands = mergedHands == null ? new List<Hand>() : new List<Hand>(MergeHands(frames));
46+
return mergedFrame;
47+
}
48+
49+
private Hand[] MergeHands(Frame[] frames)
50+
{
51+
/*
52+
* This function returns one set of hands from multiple Leap Providers, weighing their influence using hands' positions relative to devices.
53+
*/
54+
55+
if (frames.Length == 0) Debug.Log("frames has a length of 0");
56+
//sort Left and Right hands (some values may be null since never know how many hands are visible, but we clean it up at the end)
57+
Hand[] LeftHands = new Hand[providers.Length];
58+
Hand[] RightHands = new Hand[providers.Length];
59+
Hand[] mergedHands;
60+
for (int i = 0; i < frames.Length; i++)
61+
{
62+
if (frames[i].Hands == null) Debug.Log("hand is null in frame " + i);
63+
//frame_timestamps = new List<long>();
64+
//frame_timestamps.Add(providers[i].CurrentFrame.Timestamp);
65+
foreach (Hand tempHand in frames[i].Hands)
66+
{
67+
if (tempHand.IsLeft)
68+
LeftHands[i] = tempHand;
69+
else
70+
RightHands[i] = tempHand;
71+
}
72+
}
73+
74+
//combine hands using relative angle between devices:
75+
Hand confidentLeft = AngularInterpolate(LeftHands, ref cam1Aplha, ref leftAngle);
76+
Hand confidentRight = AngularInterpolate(RightHands, ref cam2Aplha, ref rightAngle);
77+
78+
//clean up and return hand arrays with only valid hands
79+
#region Clean hand arrays
80+
if (confidentLeft != null && confidentRight != null)
81+
{
82+
mergedHands = new Hand[2];
83+
mergedHands[0] = confidentLeft;
84+
mergedHands[1] = confidentRight;
85+
}
86+
else if (confidentLeft == null && confidentRight == null)
87+
{
88+
mergedHands = null;
89+
}
90+
else
91+
{
92+
mergedHands = new Hand[1];
93+
if (confidentLeft != null)
94+
mergedHands[0] = confidentLeft;
95+
else
96+
mergedHands[0] = confidentRight;
97+
}
98+
#endregion
99+
100+
return mergedHands;
101+
}
102+
103+
public static float AngleSigned(Vector3 v1, Vector3 v2, Vector3 n)
104+
{
105+
// v1 = average palm position
106+
// v2 = device midpoint up vector
107+
// n = device midpoint forward vector
108+
109+
return Mathf.Atan2(
110+
Vector3.Dot(n, Vector3.Cross(v1, v2)),
111+
Vector3.Dot(v1, v2)) * Mathf.Rad2Deg;
112+
113+
114+
}
115+
116+
private Hand AngularInterpolate(Hand[] handList, ref float alpha, ref float angle)
117+
{
118+
/*
119+
* Combines list of hands (of one chiarality) into one Leap.Hand, by weighing the relative angle to the devices
120+
*/
121+
122+
/*
123+
* TODO: fix handoff of hand when changing providers, check if chirality changed, etc
124+
* */
125+
126+
//find average palm position since we don't exactly know which provider is closest to reality:
127+
#region PreProcess Raw Hand Data
128+
Hand tempHand = null;
129+
int numValidHands = 0;
130+
foreach (Hand hand in handList)
131+
{
132+
if (hand != null && hand.Confidence > 0.98f && hand.TimeVisible > 0.5f) //only use hands with high confidence to avoid when hand is barely in view
133+
{
134+
if (tempHand == null)
135+
{
136+
tempHand = new Hand();
137+
tempHand.CopyFrom(hand);
138+
}
139+
else
140+
{
141+
Leap.Vector nH = hand.PalmPosition;
142+
Leap.Vector tH = tempHand.PalmPosition;
143+
tempHand.PalmPosition = new Leap.Vector(aprxAvg(nH.x, tH.x), aprxAvg(nH.y, tH.y), aprxAvg(nH.z, tH.z));
144+
//tempHand.PalmPosition = hand.PalmPosition;
145+
146+
147+
}
148+
numValidHands++;
149+
}
150+
}
151+
152+
if (tempHand != null)
153+
{
154+
tempHandPalmPosition = tempHand.PalmPosition.ToVector3();
155+
}
156+
#endregion
157+
158+
if (numValidHands > 0)
159+
{
160+
161+
//calculate angle between midpoint between devices(i.e. providers):
162+
Vector3 devicesMiddle = Vector3.zero;
163+
Vector3 devicesAvgForward = Vector3.zero;
164+
for (int i = 0; i < providers.Length; i++)
165+
{
166+
devicesAvgForward += providers[i].transform.forward;
167+
devicesMiddle += providers[i].transform.position;
168+
}
169+
devicesAvgForward = devicesAvgForward / providers.Length;
170+
devicesMiddle = devicesMiddle / providers.Length;
171+
172+
midpointDevices.position = devicesMiddle;
173+
midpointDevices.forward = devicesAvgForward;
174+
175+
midDevicePointPosition = midpointDevices.position;
176+
midDevicePointForward = midpointDevices.forward;
177+
midDevicePointUp = midpointDevices.up;
178+
179+
Vector3 angleCalculationHandPosition = tempHand.PalmPosition.ToVector3();
180+
181+
angle = AngleSigned(angleCalculationHandPosition, midpointDevices.position + midpointDevices.up, midpointDevices.forward);
182+
//Debug.Log(angle);
183+
184+
alpha = Mathf.Clamp(angle, -maxInterpolationAngle / 2, maxInterpolationAngle / 2);
185+
alpha = ((alpha + (maxInterpolationAngle / 2)) / (maxInterpolationAngle)); //normalize to a 0-1 scale
186+
187+
//Interpolate using alpha:
188+
Hand interpolateHand = new Hand();
189+
190+
if (numValidHands == 1)
191+
{
192+
interpolateHand.CopyFrom(tempHand);
193+
}
194+
else if (numValidHands > 1) //Note: this implementation only works with first 2 hands:
195+
{
196+
VectorHand vectorInterpolatedHand = new VectorHand();
197+
vectorInterpolatedHand.FillLerped(new VectorHand(handList[0]), new VectorHand(handList[1]), alpha);
198+
vectorInterpolatedHand.Decode(interpolateHand);
199+
}
200+
201+
tempHand = interpolateHand;
202+
}
203+
204+
return tempHand;
205+
}
206+
207+
private float aprxAvg(float avg, float new_sample)
208+
{
209+
/*
210+
* Utility function of running average
211+
*/
212+
213+
avg -= avg / 2;
214+
avg += new_sample / 2;
215+
216+
return avg;
217+
}
218+
219+
public void OnDrawGizmos()
220+
{
221+
if (tempHandPalmPosition != null)
222+
{
223+
Gizmos.DrawSphere(tempHandPalmPosition, 0.01f);
224+
}
225+
226+
midDevicePointForward.Normalize();
227+
Gizmos.DrawSphere(midDevicePointPosition, 0.01f);
228+
Gizmos.DrawSphere(midDevicePointForward + midDevicePointPosition, 0.02f);
229+
230+
Gizmos.color = Color.yellow;
231+
Gizmos.DrawLine(midDevicePointPosition, midDevicePointForward);
232+
233+
Gizmos.color = Color.green;
234+
midDevicePointUp.Normalize();
235+
Gizmos.DrawSphere(midDevicePointUp, 0.01f);
236+
Gizmos.DrawSphere(midDevicePointUp + midDevicePointPosition, 0.02f);
237+
Gizmos.DrawLine(midDevicePointPosition, midDevicePointUp);
238+
239+
var leftLimit = Quaternion.Euler(0, 0, -maxInterpolationAngle * 0.5f) * midDevicePointUp;
240+
Gizmos.DrawLine(midDevicePointPosition, leftLimit);
241+
242+
var rightLimit = Quaternion.Euler(0, 0, maxInterpolationAngle * 0.5f) * midDevicePointUp;
243+
Gizmos.DrawLine(midDevicePointPosition, rightLimit);
244+
}
245+
}
246+
}

Packages/Tracking Preview/AggregationProviders/AggregationProviderAngularInterpolation.cs.meta

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)