public static void UpdateOpenClose(bool isRight, SG_HandAnimator animater, bool calibrating, SGCore.Kinematics.HandInterpolator poseInterp, float normalizedTime01) { if (animater != null && calibrating && poseInterp != null) { SGCore.Kinematics.Vect3D[][] handAngles = SGCore.Kinematics.Values.FillZero(5, 3); for (int f = 0; f < 5; f++) { if (f == 0) { handAngles[f][0].x = poseInterp.CalculateAngle(SGCore.Kinematics.ThumbMovement.T_CMC_Twist, normalizedTime01); handAngles[f][0].z = poseInterp.CalculateAngle(SGCore.Kinematics.ThumbMovement.T_CMC_Abd, normalizedTime01); handAngles[f][0].y = poseInterp.CalculateAngle(SGCore.Kinematics.ThumbMovement.T_CMC_Flex, normalizedTime01); handAngles[f][1].y = poseInterp.CalculateAngle(SGCore.Kinematics.ThumbMovement.T_MCP_Flex, normalizedTime01); handAngles[f][2].y = poseInterp.CalculateAngle(SGCore.Kinematics.ThumbMovement.T_IP_Flex, normalizedTime01); } else { SGCore.Finger finger = (SGCore.Finger)f; handAngles[f][0].z = poseInterp.CalculateAngle(finger, SGCore.Kinematics.FingerMovement.F_MCP_Abd, normalizedTime01); handAngles[f][0].y = poseInterp.CalculateAngle(finger, SGCore.Kinematics.FingerMovement.F_MCP_Flex, normalizedTime01); handAngles[f][1].y = poseInterp.CalculateAngle(finger, SGCore.Kinematics.FingerMovement.F_PIP_Flex, normalizedTime01); handAngles[f][2].y = poseInterp.CalculateAngle(finger, SGCore.Kinematics.FingerMovement.F_DIP_Flex, normalizedTime01); } } animater.UpdateHand(new SG_HandPose(SGCore.HandPose.FromHandAngles(handAngles, isRight))); } }
/// <summary> Convert a fingle finger's flexion range and current flexion into a string representation. </summary> /// <param name="flexion"></param> /// <param name="finger"></param> /// <returns></returns> public string ToRangeString(float flexion, SGCore.Finger finger) { float min = GetMinFlexion(finger); float max = GetMaxFlexion(finger); return(ToBlockString(flexion, min, max, stringSteps)); }
/// <summary> Utility function te reiteve the maximum flexion fo a finger </summary> /// <param name="finger"></param> /// <returns></returns> public float GetMaxFlexion(SGCore.Finger finger) { switch (finger) { case SGCore.Finger.Thumb: return(thumbFlexMax); case SGCore.Finger.Index: return(indexFlexMax); case SGCore.Finger.Middle: return(middleFlexMax); case SGCore.Finger.Ring: return(ringFlexMax); case SGCore.Finger.Pinky: return(pinkyFlexMax); } return(1); }
/// <summary> Send an impact vibration to this script's connected glove, based on a speed in m/s. Checks for SG_RigidBodies. </summary> /// <param name="impactVelocity"></param> public void SendImpactFeedback(float impactVelocity, Collider col) { if (handLocation != SG_HandSection.Unknown && impactVelocity >= minImpactSpeed) { SG_TrackedBody rbScript; if (col == null || (col != null && !SG_TrackedBody.GetTrackedBodyScript(col, out rbScript))) //we either don't have a collider, or we do, but it doesn't have a RigidBody script. { int impactLevel; //evaluate the intensity if (impactVelocity > maxImpactSpeed || minImpactSpeed >= maxImpactSpeed) { impactLevel = maxBuzzLevel; } else { //map the impact parameters on the speed. float mapped = Mathf.Clamp01(SG_Util.Map(impactVelocity, minImpactSpeed, maxImpactSpeed, 0, 1)); //we're actually start at minBuzzLevel; that's when you can start to feel the Sense Glove vibrations impactLevel = (int)(SG_Util.Map(impactProfile.Evaluate(mapped), 0, 1, minBuzzLevel, maxBuzzLevel)); } //actually send the effect if (linkedGlove != null && vibrationTime > 0) { if (handLocation == SG_HandSection.Wrist) //it's a wrist. { linkedGlove.SendCmd(new SGCore.Haptics.TimedThumpCmd(impactLevel, vibrationTime)); } else //finger { SGCore.Finger finger = (SGCore.Finger)handLocation; //can do this since the finger indices match SGCore.Haptics.SG_TimedBuzzCmd buzzCmd = new SGCore.Haptics.SG_TimedBuzzCmd(finger, impactLevel, vibrationTime); linkedGlove.SendCmd(buzzCmd); } cooldownTimer = 0; //reset cooldown for this finger. } } } }