12 using System.Collections.
Generic;
16 public static class TestHandFactory {
18 #region Test Frame / Hand API
20 public enum UnitType {
29 public static Frame MakeTestFrame(
int frameId,
30 bool includeLeftHand =
true,
31 bool includeRightHand =
true,
33 UnitType unitType = UnitType.LeapUnits) {
35 var testFrame =
new Frame(frameId, 0, 120.0f,
39 testFrame.Hands.Add(MakeTestHand(
true, handPose, frameId, 10, unitType));
41 testFrame.Hands.Add(MakeTestHand(
false, handPose, frameId, 20, unitType));
52 public static Hand MakeTestHand(
bool isLeft, LeapTransform leftHandTransform,
53 int frameId = 0,
int handId = 0,
54 UnitType unitType = UnitType.LeapUnits) {
58 leftHandTransform.translation =
new Vector(-leftHandTransform.translation.x,
59 leftHandTransform.translation.y, leftHandTransform.translation.z);
61 leftHandTransform.rotation =
new LeapQuaternion(-leftHandTransform.rotation.x,
62 leftHandTransform.rotation.y,
63 leftHandTransform.rotation.z,
64 -leftHandTransform.rotation.w);
66 leftHandTransform.MirrorX();
70 var hand = makeLeapSpaceTestHand(frameId, handId, isLeft)
71 .Transform(leftHandTransform);
72 var correctingQuaternion =
Quaternion.Euler(90f, 0f, 180f);
73 var correctingLeapQuaternion =
new LeapQuaternion(correctingQuaternion.x,
74 correctingQuaternion.y,
75 correctingQuaternion.z,
76 correctingQuaternion.w);
78 var transformedHand = hand.Transform(
new LeapTransform(Vector.Zero,
79 correctingLeapQuaternion));
81 if (unitType == UnitType.UnityUnits) {
82 transformedHand.TransformToUnityUnits();
85 return transformedHand;
91 public static Hand MakeTestHand(
bool isLeft,
92 int frameId = 0,
int handId = 0,
93 UnitType unitType = UnitType.LeapUnits) {
94 return MakeTestHand(isLeft, LeapTransform.Identity, frameId, handId, unitType);
101 int frameId = 0,
int handId = 0,
102 UnitType unitType = UnitType.LeapUnits) {
103 return MakeTestHand(isLeft, GetTestPoseLeftHandTransform(pose),
110 #region Test Hand Poses
119 public static LeapTransform GetTestPoseLeftHandTransform(
TestHandPose pose) {
120 LeapTransform transform = LeapTransform.Identity;
123 transform.rotation = angleAxis(180 * Constants.DEG_TO_RAD, Vector.Forward);
124 transform.translation =
new Vector(80f, 120f, 0f);
127 transform.rotation =
Quaternion.Euler(30F, -10F, -20F).ToLeapQuaternion();
128 transform.translation =
new Vector(220f, 270f, 130f);
131 transform.rotation = angleAxis(0f * Constants.DEG_TO_RAD, Vector.Forward)
132 .Multiply(angleAxis(-90f * Constants.DEG_TO_RAD, Vector.Right))
133 .Multiply(angleAxis(180f * Constants.DEG_TO_RAD, Vector.Up));
134 transform.translation =
new Vector(120f, 0f, -170f);
137 transform.rotation = angleAxis(0 * Constants.DEG_TO_RAD, Vector.Forward)
138 .Multiply(angleAxis(140 * Constants.DEG_TO_RAD, Vector.Right))
139 .Multiply(angleAxis(0 * Constants.DEG_TO_RAD, Vector.Up));
140 transform.translation =
new Vector(-120f, 20f, -380f);
141 transform.scale =
new Vector(1, 1, 1);
150 #region Leap Space Hand Generation
152 public static Vector PepperWristOffset =
new Vector(-8.87f, -0.5f, 85.12f);
154 private static Hand makeLeapSpaceTestHand(
int frameId,
int handId,
bool isLeft) {
155 List<Finger> fingers =
new List<Finger>(5);
156 fingers.Add(makeThumb(frameId, handId, isLeft));
157 fingers.Add(makeIndexFinger(frameId, handId, isLeft));
158 fingers.Add(makeMiddleFinger(frameId, handId, isLeft));
159 fingers.Add(makeRingFinger(frameId, handId, isLeft));
160 fingers.Add(makePinky(frameId, handId, isLeft));
162 Vector armWrist =
new Vector(-7.05809944059f, 4.0f, 50.0f);
163 Vector elbow = armWrist + 250f * Vector.Backward;
166 Arm arm =
new Arm(elbow, armWrist,(elbow + armWrist)/2, Vector.Forward,
167 250f, 41f, LeapQuaternion.Identity);
184 LeapQuaternion.Identity,
192 private static LeapQuaternion angleAxis(
float angle, Vector axis) {
193 if (!axis.MagnitudeSquared.NearlyEquals(1.0f)) {
194 throw new ArgumentException(
"Axis must be a unit vector.");
196 float sineHalfAngle = Mathf.Sin(angle/2.0f);
197 LeapQuaternion q =
new LeapQuaternion(sineHalfAngle * axis.x,
198 sineHalfAngle * axis.y,
199 sineHalfAngle * axis.z,
200 Mathf.Cos(angle/2.0f));
204 private static LeapQuaternion rotationBetween(Vector fromDirection, Vector toDirection) {
205 float m = Mathf.Sqrt(2.0f + 2.0f * fromDirection.Dot(toDirection));
206 Vector w = (1.0f / m) * fromDirection.Cross(toDirection);
207 return new LeapQuaternion(w.x, w.y, w.z, 0.5f * m);
210 private static Finger makeThumb(
int frameId,
int handId,
bool isLeft) {
211 Vector position =
new Vector(19.3382610281f, -6.0f, 53.168484654f);
212 Vector forward =
new Vector(0.636329113772f, -0.5f, -0.899787143982f);
213 Vector up =
new Vector(0.804793943718f, 0.447213915513f, 0.390264553767f);
214 float[] jointLengths = {0.0f, 46.22f, 31.57f, 21.67f};
215 return makeFinger(Finger.FingerType.TYPE_THUMB, position, forward, up, jointLengths, frameId, handId, handId + 0, isLeft);
218 private static Finger makeIndexFinger(
int frameId,
int handId,
bool isLeft) {
219 Vector position =
new Vector(23.1812851873f, 2.0f, -23.1493459317f);
220 Vector forward =
new Vector(0.166044313785f, -0.14834045293f, -0.974897120667f);
221 Vector up =
new Vector(0.0249066470677f, 0.988936352868f, -0.1462345681f);
222 float[] jointLengths = {68.12f, 39.78f, 22.38f, 15.82f};
223 return makeFinger(Finger.FingerType.TYPE_INDEX, position, forward, up, jointLengths, frameId, handId, handId + 1, isLeft);
226 private static Finger makeMiddleFinger(
int frameId,
int handId,
bool isLeft) {
227 Vector position =
new Vector(2.78877821918f, 4.0f, -23.252105626f);
228 Vector forward =
new Vector(0.0295207858556f, -0.148340452932f, -0.988495641481f);
229 Vector up =
new Vector(-0.145765270107f, 0.977715980076f, -0.151075968756f);
230 float[] jointLengths = {64.60f, 44.63f, 26.33f, 17.40f};
231 return makeFinger(Finger.FingerType.TYPE_MIDDLE, position, forward, up, jointLengths, frameId, handId, handId + 2, isLeft);
234 private static Finger makeRingFinger(
int frameId,
int handId,
bool isLeft) {
235 Vector position =
new Vector(-17.447168266f, 4.0f, -17.2791440615f);
236 Vector forward =
new Vector(-0.121317937368f, -0.148340347175f, -0.981466810174f);
237 Vector up =
new Vector(-0.216910468316f, 0.968834928679f, -0.119619102602f);
238 float[] jointLengths = {58.00f, 41.37f, 25.65f, 17.30f};
239 return makeFinger(Finger.FingerType.TYPE_RING, position, forward, up, jointLengths, frameId, handId, handId + 3, isLeft);
242 private static Finger makePinky(
int frameId,
int handId,
bool isLeft) {
243 Vector position =
new Vector(-35.3374394559f, 0.0f, -9.72871382551f);
244 Vector forward =
new Vector(-0.259328923438f, -0.105851224797f, -0.959970847306f);
245 Vector up =
new Vector(-0.353350220937f, 0.935459475557f, -0.00769356576168f);
246 float[] jointLengths = {53.69f, 32.74f, 18.11f, 15.96f};
247 return makeFinger(Finger.FingerType.TYPE_PINKY, position, forward, up, jointLengths, frameId, handId, handId + 4, isLeft);
251 private static Finger makeFinger(Finger.FingerType name, Vector position, Vector forward, Vector up,
float[] jointLengths,
252 int frameId,
int handId,
int fingerId,
bool isLeft) {
254 forward = forward.Normalized;
257 Bone[] bones =
new Bone[5];
258 float proximalDistance = -jointLengths[0];
259 Bone metacarpal = makeBone (Bone.BoneType.TYPE_METACARPAL, position + forward * proximalDistance, jointLengths[0], 8f, forward, up, isLeft);
260 proximalDistance += jointLengths[0];
261 bones[0] = metacarpal;
263 Bone proximal = makeBone (Bone.BoneType.TYPE_PROXIMAL, position + forward * proximalDistance, jointLengths[1], 8f, forward, up, isLeft);
264 proximalDistance += jointLengths[1];
267 Bone intermediate = makeBone (Bone.BoneType.TYPE_INTERMEDIATE, position + forward * proximalDistance, jointLengths[2], 8f, forward, up, isLeft);
268 proximalDistance += jointLengths[2];
269 bones[2] = intermediate;
271 Bone distal = makeBone (Bone.BoneType.TYPE_DISTAL, position + forward * proximalDistance, jointLengths[3], 8f, forward, up, isLeft);
274 return new Finger(frameId,
281 jointLengths[1] + jointLengths[2] + jointLengths[3],
290 private static Bone makeBone(Bone.BoneType name, Vector proximalPosition,
float length,
float width, Vector direction, Vector up,
bool isLeft) {
292 LeapQuaternion rotation =
UnityEngine.Quaternion.LookRotation(-direction.ToVector3(), up.ToVector3()).ToLeapQuaternion();
296 proximalPosition + direction * length,
297 Vector.Lerp(proximalPosition, proximalPosition + direction * length, .5f),
312 public static class LeapTestProviderExtensions {
314 public static readonly
float MM_TO_M = 1e-3f;
316 public static LeapTransform GetLeapTransform(Vector3 position, Quaternion rotation) {
317 Vector scale =
new Vector(MM_TO_M, MM_TO_M, MM_TO_M);
318 LeapTransform transform =
new LeapTransform(position.ToVector(), rotation.ToLeapQuaternion(), scale);
323 public static void TransformToUnityUnits(
this Hand hand) {
TestHandFactory.TestHandPose TestHandPose