예제 #1
0
        private void ShowInstruction()
        {
            Debug.Log($"Calibrating pose {currentPose} for {lrName} hand");
            handAnimator.SetInteger("handState", (int)currentPose);
            currentStep = Step.Wait;
            switch (currentPose)
            {
            case Pose.HandOpen:
                TutorialSteps.Instance.audioManager.ScheduleAudioClip(audioClips.handOpen, queue: false);
                TutorialSteps.PublishNotification($"Open your {lrName} hand", Mathf.Max(audioClips.handOpen.length, calibrationParams.waitTime + calibrationParams.dwellTime));
                break;

            case Pose.HandClosed:
                TutorialSteps.Instance.audioManager.ScheduleAudioClip(audioClips.handClosed, queue: false);
                TutorialSteps.PublishNotification($"Make a fist with your {lrName} hand", Mathf.Max(audioClips.handClosed.length, calibrationParams.waitTime + calibrationParams.dwellTime));
                break;

            //case Pose.FingersExt:
            //    TutorialSteps.Instance.audioManager.ScheduleAudioClip(fingersExt, queue: false);
            //    SendToast($"Extend your {right} fingers", waitTime + dwellTime);
            //    break;
            //case Pose.FingersFlexed:
            //    TutorialSteps.Instance.audioManager.ScheduleAudioClip(fingersFlexed, queue: false);
            //    SendToast($"Flex your {right} fingers", waitTime + dwellTime);
            //    break;
            case Pose.ThumbUp:
                TutorialSteps.Instance.audioManager.ScheduleAudioClip(audioClips.thumbUp, queue: false);
                TutorialSteps.PublishNotification("Give me a thumbs up", Mathf.Max(audioClips.thumbUp.length, calibrationParams.waitTime + calibrationParams.dwellTime));
                break;

            case Pose.ThumbFlex:
                TutorialSteps.Instance.audioManager.ScheduleAudioClip(audioClips.thumbFlex, queue: false);
                TutorialSteps.PublishNotification($"Flex your {lrName} thumb", Mathf.Max(audioClips.thumbFlex.length, calibrationParams.waitTime + calibrationParams.dwellTime));
                break;

            case Pose.AbdOut:
                TutorialSteps.Instance.audioManager.ScheduleAudioClip(audioClips.abdOut, queue: false);
                TutorialSteps.PublishNotification($"Move your {lrName} thumb out", Mathf.Max(audioClips.abdOut.length, calibrationParams.waitTime + calibrationParams.dwellTime));
                break;

            //case Pose.NoThumbAbd:
            //    TutorialSteps.Instance.audioManager.ScheduleAudioClip(noThumbAbd, queue: false);
            //    SendToast($"Move your {right} thumb up", waitTime + dwellTime);
            //    break;
            default:
                Debug.LogError($"Pose unknown: {currentPose}");
                break;
            }
        }
예제 #2
0
        // Update is called once per frame
        void Update()
        {
            // load old calibration if existing
            if (interpolator == null &&
                hand.IsLinked &&
                hand.GetInterpolationProfile(out interpolator))
            {
                poses = LoadProfiles();
                Debug.Log($"Connected {(isRight ? "right" : "left")} Hand");
            }

            // only start the calibration, if the SenseGlove could be found and the calibrating flag was set
            if (calibrating && hand.IsLinked)
            {
                switch (currentStep)
                {
                // 1. show instruction
                case Step.ShowInstruction:
                {
                    virtualHand.SetActive(true);
                    ShowInstruction();
                    break;
                }

                // 2. wait
                case Step.Wait:
                {
                    calibrationParams.waitTimer.LetTimePass(Time.deltaTime);
                    poseStore.Clear();
                    break;
                }

                // 3. dwell
                case Step.Dwell:
                {
                    if (TutorialSteps.Instance.audioManager.IsAudioPlaying())
                    {
                        break;
                    }
                    calibrationParams.dwellTimer.LetTimePass(Time.deltaTime);
                    completionWidget.active   = true;
                    completionWidget.text     = "calibrating";
                    completionWidget.progress = calibrationParams.dwellTimer.GetFraction();

                    poseStore.AddPose(GetCurrentPoseValues());
                    float error = poseStore.ComputeError();
                    if (error > calibrationParams.maxError)
                    {
                        const string warningText = "Finger position changed too much, retry";
                        Debug.LogWarning(warningText);

                        poseStore.Clear();
                        calibrationParams.dwellTimer.ResetTimer();
                    }
                    break;
                }

                // 3.5 finish calibration & init testing phase
                case Step.TestInit:
                {
                    hand.SaveHandCalibration();
                    virtualHand.SetActive(false);
                    Debug.Log($"Saved Calibration Profiles for {lrName} hand");

                    TutorialSteps.Instance.audioManager.ScheduleAudioClip(audioClips.test, queue: false);
                    TutorialSteps.PublishNotification($"{lrName} thumbs up to continue", audioClips.test.length + testParams.dwellTime);
                    handAnimator.SetInteger("handState", (int)Pose.ThumbUp);

                    currentStep = Step.Test;
                    goto case Step.Test;
                }

                // 4. test calibration
                case Step.Test:
                {
                    if (TutorialSteps.Instance.audioManager.IsAudioPlaying())
                    {
                        break;
                    }
                    PoseBuffer buffer = new PoseBuffer(bufferSize: 2);
                    buffer.AddPose(poseValues[(int)Pose.ThumbUp]);
                    buffer.AddPose(GetCurrentPoseValues());
                    float error = buffer.ComputeError();
                    testParams.dwellTimer.LetTimePass(Time.deltaTime);
                    if (error > testParams.maxError)
                    {
                        testParams.dwellTimer.ResetTimer();
                    }

                    completionWidget.text     = "hold";
                    completionWidget.active   = true;
                    completionWidget.progress = testParams.dwellTimer.GetFraction();
                    break;
                }

                // 5. calibration done
                case Step.Done:
                {
                    calibrating             = false;
                    completionWidget.active = false;
                    doneCallbacks.Call(currentStep);
                    break;
                }

                default: break;
                }
            }
        }
예제 #3
0
        void Start()
        {
            currentState = State.START;

            StateManager.Instance.onStateChangeTo[StateManager.States.HUD].Add((s) => StopCalibration(), once: true);

            // get objectives
            foreach (var comp in PlayerRig.Instance.gameObject.GetComponentsInChildren <XROffset>())
            {
                if (comp.isRight)
                {
                    rightHandObjective = comp.transform;
                    rightHand          = comp.orientation.target;
                }
                else
                {
                    leftHandObjective = comp.transform;
                    leftHand          = comp.orientation.target;
                }
            }
            // get arms
            leftShoulder  = GameObject.Find("shoulder_left_axis0").transform;
            rightShoulder = GameObject.Find("shoulder_right_axis0").transform;

            #region StateDefinitions
            stateMachine.onEnter[State.START] = (state) =>
            {
                TutorialSteps.Instance.audioManager.ScheduleAudioClip(armLengthAudioClips.start,
                                                                      onEnd: () => Next());
            };

            stateMachine.onEnter[State.RIGHT_SHOULDER_TOUCH] = (state) =>
            {
                TutorialSteps.Instance.audioManager.ScheduleAudioClip(armLengthAudioClips.touch_right,
                                                                      onStart: () =>
                {
                    TutorialSteps.PublishNotification("Touch your right shoulder with your left arm");
                    rightShoulderVolume.StartWaiting();
                }, queue: true);
                rightShoulderVolume.OnDone((b) =>
                {
                    leftArmTouchpoint.position = new Vector3(
                        leftHandObjective.position.x,
                        leftShoulder.position.y,
                        leftShoulder.position.z
                        );
                    Next();
                }, once: true);
            };
            stateMachine.onExit[State.RIGHT_SHOULDER_TOUCH] = (state) =>
            {
                rightShoulderVolume.StopWaiting();
            };

            stateMachine.onEnter[State.LEFT_SHOULDER_TOUCH] = (state) =>
            {
                TutorialSteps.Instance.audioManager.ScheduleAudioClip(armLengthAudioClips.touch_left,
                                                                      onStart: () =>
                {
                    TutorialSteps.PublishNotification("Touch your left shoulder with your right arm");
                    leftShoulderVolume.StartWaiting();
                });
                leftShoulderVolume.OnDone((b) =>
                {
                    rightArmTouchpoint.position = new Vector3(
                        rightHandObjective.position.x,
                        rightShoulder.position.y,
                        rightShoulder.position.z
                        );
                    Next();
                }, once: true);
            };
            stateMachine.onExit[State.LEFT_SHOULDER_TOUCH] = (state) =>
            {
                leftShoulderVolume.StopWaiting();
            };


            stateMachine.onEnter[State.LEFT_SCALE] = (state) =>
            {
                TutorialSteps.Instance.audioManager.ScheduleAudioClip(armLengthAudioClips.scale_left);
                TutorialSteps.PublishNotification("Strech your left arm fully");
                TutorialSteps.PublishNotification("Left thumbs up to calibrate");
                UserInteractionManager.Instance.Confirm((b) =>
                {
                    FitLeft();
                    Next();
                }, left: true, once: true);
            };

            stateMachine.onEnter[State.RIGHT_SCALE] = (state) =>
            {
                TutorialSteps.Instance.audioManager.ScheduleAudioClip(armLengthAudioClips.scale_right);
                TutorialSteps.PublishNotification("Strech your right arm fully");
                TutorialSteps.PublishNotification("Right thumbs up to calibrate");
                UserInteractionManager.Instance.Confirm((b) =>
                {
                    FitRight();
                    Next();
                }, left: false, once: true);
            };

            stateMachine.onEnter[State.DONE] = (state) =>
            {
                Save();
                onDoneCallbacks.Call(State.DONE);
            };
            #endregion

            Load();
        }