Пример #1
0
    public override void HandleSessionInitialisation()
    {
        base.HandleSessionInitialisation();

        // New file for the performance data logger
        performanceDataLogger.CloseLog();
        performanceDataLogger.AddNewLogFile(AvatarSystem.AvatarType.ToString(), sessionNumber, ablebodiedPerformanceDataFormat); // Add file

        // Clear ball
        gridManager.ResetBallSelection();
    }
    /// <summary>
    /// Handles procedures performed when initialising the next iteration.
    /// Updates iteration number, session number, resets the task time, and starts a new data log by default.
    /// Extend this method by doing your own implementation, with base.HandleSessionInitialisation() being called at the start.
    /// </summary>
    public override void HandleSessionInitialisation()
    {
        base.HandleSessionInitialisation();

        #region Iteration settings
        // Set iterations variables for flow control.
        targetNumber = poseListManager.TargetNumber;
        iterationsPerSession[sessionNumber - 1] = targetNumber * iterationsPerTarget;


        // Create the list of target indexes and shuffle it.
        targetOrder.Clear(); //clear the target order
        for (int i = 0; i < targetNumber; i++)
        {
            for (int j = 0; j < iterationsPerTarget; j++)
            {
                targetOrder.Add(i);
                Debug.Log(targetOrder[targetOrder.Count - 1]);
            }
        }

        targetOrder.Shuffle();

        // New file for the performance data logger
        performanceDataLogger.CloseLog();
        performanceDataLogger.AddNewLogFile(AvatarSystem.AvatarType.ToString(), sessionNumber, performanceDataFormat); // Add file

        // Display task text
        StartCoroutine(DisplayTaskText(targetOrder[0]));


        if (debug)
        {
            foreach (int target in targetOrder)
            {
                Debug.Log("Pose:" + target);
            }
        }
        #endregion
    }
    /// <summary>
    /// Initializes the ExperimentSystem and its components.
    /// Verifies that all components needed for the experiment are available.
    /// This must be done in Start.
    /// Extend this method by doing your own implementation, with base.InitExperimentSystem() being called at the start.
    /// </summary>
    public override void InitialiseExperimentSystems()
    {
        // Set data format
        taskDataFormat = ablebodiedDataFormat;

        // Lefty sign

        /*
         * if (SaveSystem.ActiveUser.lefty)
         *  leftySign = -1.0f;
         */
        // Audio
        audio      = GetComponent <AudioSource>();
        audio.clip = testAudioClip;

        #region Modify base
        // Then run the base initialisation which is needed, with a small modification
        //
        // Set the experiment name only when debugging. Take  the name from the gameobject + Debug
        //
        if (debug)
        {
            ExperimentSystem.SetActiveExperimentID(this.gameObject.name + "_Debug");
        }

        // Make sure flow control is initialised
        sessionNumber   = 1;
        iterationNumber = 1;

        //
        // Create the default data loggers
        //
        taskDataLogger = new DataStreamLogger("TaskData/" + AvatarSystem.AvatarType.ToString());
        ExperimentSystem.AddExperimentLogger(taskDataLogger);
        taskDataLogger.AddNewLogFile(sessionNumber, iterationNumber, taskDataFormat); // Add file

        // Send the player to the experiment centre position
        TeleportToStartPosition();
        #endregion

        #region Initialize EMG sensors
        //Initialse Delsys EMG sensor
        delsysEMG.Init();
        delsysEMG.Connect();
        delsysEMG.StartAcquisition();

        #endregion


        #region Initialize world positioning

        // Set the subject physiological data for grid
        gridManager.ConfigUserData();

        gridManager.ConfigGridPositionFactors(gridCloseDistanceFactor, gridMidDistanceFactor, gridFarDistanceFactor, gridHeightFactor);

        #endregion

        #region  Initialize motion sensors
        //
        // Add arm motion trackers for able-bodied case.
        //
        // Lower limb motion tracker
        GameObject llMotionTrackerGO = GameObject.FindGameObjectWithTag("ForearmTracker");
        lowerArmTracker = new VIVETrackerManager(llMotionTrackerGO.transform);
        ExperimentSystem.AddSensor(lowerArmTracker);

        // Upper limb motion tracker
        GameObject ulMotionTrackerGO = AvatarSystem.AddMotionTracker();
        upperArmTracker = new VIVETrackerManager(ulMotionTrackerGO.transform);
        ExperimentSystem.AddSensor(upperArmTracker);

        if (!debug)
        {
            // Shoulder acromium head tracker
            GameObject motionTrackerGO1 = AvatarSystem.AddMotionTracker();
            shoulderTracker = new VIVETrackerManager(motionTrackerGO1.transform);
            ExperimentSystem.AddSensor(shoulderTracker);
            // C7 tracker
            GameObject motionTrackerGO2 = AvatarSystem.AddMotionTracker();
            c7Tracker = new VIVETrackerManager(motionTrackerGO2.transform);
            ExperimentSystem.AddSensor(c7Tracker);
        }



        //
        // Hand tracking sensor
        //
        GameObject handGO = GameObject.FindGameObjectWithTag("Hand");
        handTracker = new VirtualPositionTracker(handGO.transform);
        ExperimentSystem.AddSensor(handTracker);

        #endregion
    }
    /// <summary>
    /// Initializes the ExperimentSystem and its components.
    /// Verifies that all components needed for the experiment are available.
    /// This must be done in Start.
    /// Extend this method by doing your own implementation, with base.InitExperimentSystem() being called at the start.
    /// </summary>
    public override void InitialiseExperimentSystems()
    {
        // Set data format
        taskDataFormat = ablebodiedDataFormat;

        // Lefty sign

        /*
         * if (SaveSystem.ActiveUser.lefty)
         *  leftySign = -1.0f;
         */
        // Audio
        audio      = GetComponent <AudioSource>();
        audio.clip = testAudioClip;

        #region Modify base
        // Then run the base initialisation which is needed, with a small modification
        //
        // Set the experiment name only when debugging. Take  the name from the gameobject + Debug
        //
        if (debug)
        {
            ExperimentSystem.SetActiveExperimentID(this.gameObject.name + "_Debug");
        }

        // Make sure flow control is initialised
        sessionNumber   = 1;
        iterationNumber = 1;

        //
        // Create the default data loggers
        //
        taskDataLogger = new DataStreamLogger("TaskData/" + AvatarSystem.AvatarType.ToString());
        ExperimentSystem.AddExperimentLogger(taskDataLogger);
        taskDataLogger.AddNewLogFile(sessionNumber, iterationNumber, taskDataFormat); // Add file

        //
        // Create the performance data loggers
        //
        performanceDataLogger = new DataStreamLogger("PerformanceData");
        ExperimentSystem.AddExperimentLogger(performanceDataLogger);
        performanceDataLogger.AddNewLogFile(AvatarSystem.AvatarType.ToString(), sessionNumber, performanceDataFormat); // Add file

        // Send the player to the experiment centre position
        TeleportToStartPosition();
        #endregion

        #region Initialize EMG sensors
        //Initialise Delsys EMG sensor
        delsysEMG.Init();
        delsysEMG.Connect();


        #endregion


        #region  Initialize motion sensors
        //
        // Add arm motion trackers for able-bodied case.
        //
        // Lower limb motion tracker
        GameObject llMotionTrackerGO = GameObject.FindGameObjectWithTag("ForearmTracker");
        lowerArmTracker = new VIVETrackerManager(llMotionTrackerGO.transform);
        ExperimentSystem.AddSensor(lowerArmTracker);

        // Upper limb motion tracker
        GameObject ulMotionTrackerGO = AvatarSystem.AddMotionTracker();
        upperArmTracker = new VIVETrackerManager(ulMotionTrackerGO.transform);
        ExperimentSystem.AddSensor(upperArmTracker);

        if (!debug)
        {
            // Shoulder acromium head tracker
            GameObject motionTrackerGO1 = AvatarSystem.AddMotionTracker();
            shoulderTracker = new VIVETrackerManager(motionTrackerGO1.transform);
            ExperimentSystem.AddSensor(shoulderTracker);
            // C7 tracker
            GameObject motionTrackerGO2 = AvatarSystem.AddMotionTracker();
            c7Tracker = new VIVETrackerManager(motionTrackerGO2.transform);
            ExperimentSystem.AddSensor(c7Tracker);
        }



        //
        // Hand tracking sensor
        //
        GameObject handGO = GameObject.FindGameObjectWithTag("Hand");
        handTracker = new VirtualPositionTracker(handGO.transform);
        ExperimentSystem.AddSensor(handTracker);

        #endregion

        //
        // Target ADL poses
        //
        poseListManager.AddPose("Rest", restAudioClip);
        poseListManager.AddPose("Reach Mug", reachMugAudioClip);
        poseListManager.AddPose("Mug to Mouth", mug2MouthAudioClip);
        poseListManager.AddPose("Drink with Mug", drinkAudioClip);
        poseListManager.AddPose("Reach Key", reachKeyAudioClip);
        poseListManager.AddPose("Turn Key", turnKeyAudioClip);


        // Start EMG readings
        delsysEMG.StartAcquisition();
    }
Пример #5
0
    /// <summary>
    /// Initializes the ExperimentSystem and its components.
    /// Verifies that all components needed for the experiment are available.
    /// This must be done in Start.
    /// Extend this method by doing your own implementation, with base.InitExperimentSystem() being called at the start.
    /// </summary>
    public override void InitialiseExperimentSystems()
    {
        //
        // Set the experiment type configuration
        //
        // Type one if able-bodied subject
        if (AvatarSystem.AvatarType == AvatarType.AbleBodied)
        {
            experimentType        = ExperimentType.TypeOne; // Able-bodied experiment type
            taskDataFormat        = ablebodiedDataFormat;
            performanceDataFormat = ablebodiedPerformanceDataFormat;
        }
        // Type two if prosthetic (Adaptive Synergy)
        else if (AvatarSystem.AvatarType == AvatarType.Transhumeral)
        {
            experimentType        = ExperimentType.TypeTwo; // Able-bodied experiment type
            taskDataFormat        = prostheticDataFormat;
            performanceDataFormat = prostheticPerformanceDataFormat;
        }
        // Then run the base initialisation which is needed, with a small modification
        //
        // Set the experiment name only when debugging. Take  the name from the gameobject + Debug
        //
        if (debug)
        {
            ExperimentSystem.SetActiveExperimentID(this.gameObject.name + "_Debug");
        }

        // Make sure flow control is initialised
        sessionNumber   = 1;
        iterationNumber = 1;

        //
        // Create the default data loggers
        //
        taskDataLogger = new DataStreamLogger("TaskData/" + AvatarSystem.AvatarType.ToString());
        ExperimentSystem.AddExperimentLogger(taskDataLogger);
        taskDataLogger.AddNewLogFile(sessionNumber, iterationNumber, taskDataFormat); // Add file

        // Restart UDP threads
        foreach (ISensor sensor in AvatarSystem.GetActiveSensors())
        {
            if (sensor is UDPSensorManager udpSensor)
            {
                //Debug.Log(wifiSensor.RunThread);
                udpSensor.StartSensorReading();
                //Debug.Log(wifiSensor.RunThread);
            }
        }

        // Send the player to the experiment centre position
        TeleportToStartPosition();

        startPosPhoto.SetActive(false);

        //
        // Create the performance data loggers
        //
        performanceDataLogger = new DataStreamLogger("PerformanceData");
        ExperimentSystem.AddExperimentLogger(performanceDataLogger);
        performanceDataLogger.AddNewLogFile(AvatarSystem.AvatarType.ToString(), sessionNumber, performanceDataFormat); // Add file

        if (SaveSystem.ActiveUser.lefty)
        {
            leftySign = -1.0f;
        }

        //
        // Iterations configuration
        //
        // Set iterations variables for flow control.
        targetNumber = gridRows * gridColumns;
        for (int i = 0; i < iterationsPerSession.Count; i++)
        {
            iterationsPerSession[i] = targetNumber * iterationsPerTarget;
        }

        // Create the list of target indexes and shuffle it.
        for (int i = 0; i < targetNumber; i++)
        {
            for (int j = 0; j < iterationsPerTarget; j++)
            {
                targetOrder.Add(i);
            }
        }
        targetOrder.Shuffle();

        //
        // Initialize world positioning
        //
        // Get user physiological data.
        float subjectHeight    = SaveSystem.ActiveUser.height;
        float subjectArmLength = SaveSystem.ActiveUser.upperArmLength + SaveSystem.ActiveUser.forearmLength + (SaveSystem.ActiveUser.handLength / 2);

        // Set the grid distance from subject
        gridManager.transform.position = new Vector3((-gridReachMultiplier * subjectArmLength) - 0.1f, gridHeightMultiplier * subjectHeight, 0.0f);

        //
        // Add arm motion trackers for able-bodied case.
        //
        if (experimentType == ExperimentType.TypeOne)
        {
            // Lower limb motion tracker
            GameObject llMotionTrackerGO = GameObject.FindGameObjectWithTag("ForearmTracker");
            lowerArmTracker = new VIVETrackerManager(llMotionTrackerGO.transform);
            ExperimentSystem.AddSensor(lowerArmTracker);

            // Upper limb motion tracker
            GameObject ulMotionTrackerGO = AvatarSystem.AddMotionTracker();
            upperArmTracker = new VIVETrackerManager(ulMotionTrackerGO.transform);
            ExperimentSystem.AddSensor(upperArmTracker);
        }
        else if (experimentType == ExperimentType.TypeTwo)
        {
            // Get active sensors from avatar system and get the vive tracker being used for the UA
            foreach (ISensor sensor in AvatarSystem.GetActiveSensors())
            {
                if (sensor is VIVETrackerManager)
                {
                    upperArmTracker = (VIVETrackerManager)sensor;
                }
            }
            if (upperArmTracker == null)
            {
                throw new System.NullReferenceException("The residual limb tracker was not found.");
            }

            // Set VIVE tracker and Linear synergy as active.
            // Get prosthesis
            prosthesisManagerGO = GameObject.FindGameObjectWithTag("ProsthesisManager");
            elbowManager        = prosthesisManagerGO.GetComponent <ConfigurableElbowManager>();
            // Set the reference generator to linear synergy.
            elbowManager.ChangeSensor("VAL_SENSOR_VIVETRACKER");
            elbowManager.ChangeReferenceGenerator("VAL_REFGEN_LINKINSYN");

            // Create the personalisation algorithm object
            elbowManager.SetSynergy(theta);
            float[]   ditherFrequency = { Mathf.PI / 4, 2 * Mathf.PI / 4 };
            float[]   observerGain    = { 0.3840f, 0.6067f, -0.2273f, -0.8977f, -1.0302f };
            float[][] A = new float[2][];
            A[0] = new float[2] {
                1.3130f, -0.8546f
            };
            A[1] = new float[2] {
                1.0f, 0.0f
            };
            float[] B = { 1.0f, 0.0f };
            float[] C = { 0.0131f, -0.0131f };
            float   D = 0.0f;
            personaliser = new TransCyberHPIPersonalisation(ditherAmplitude, 0, ditherFrequency, observerGain, 1, optimiserGain, 0.1f, A, B, C, D, theta, 0.1f, 3.0f);
        }

        if (evaluatorType == EvaluatorType.Compensation)
        {
            // Performance evaluation objects
            evaluator    = new UpperBodyCompensationMotionPM(0.5f, 0.5f);
            shDataBuffer = new List <Vector3>();
            c7DataBuffer = new List <Vector3>();
        }
        else if (evaluatorType == EvaluatorType.KinematicEnergy)
        {
            throw new System.NotImplementedException("KE method not yet implemented");
        }

        // Debug?
        if (!debug)
        {
            // Shoulder acromium head tracker
            GameObject motionTrackerGO1 = AvatarSystem.AddMotionTracker();
            shoulderTracker = new VIVETrackerManager(motionTrackerGO1.transform);
            ExperimentSystem.AddSensor(shoulderTracker);
            // C7 tracker
            GameObject motionTrackerGO2 = AvatarSystem.AddMotionTracker();
            c7Tracker = new VIVETrackerManager(motionTrackerGO2.transform);
            ExperimentSystem.AddSensor(c7Tracker);
        }

        //
        // Hand tracking sensor
        //
        GameObject handGO = GameObject.FindGameObjectWithTag("Hand");

        handTracker = new VirtualPositionTracker(handGO.transform);
        ExperimentSystem.AddSensor(handTracker);

        // Spawn grid
        gridManager.SpawnGrid(gridRows, gridColumns, gridSpacing);
    }
Пример #6
0
    // Update is called once per frame
    void Update()
    {
        switch (experimentState)
        {
        /*
         *************************************************
         *  HelloWorld
         *************************************************
         */
        // Welcome subject to the virtual world.
        case ExperimentState.Welcome:
            if (WaitFlag)
            {
                HudManager.ClearText();
                experimentState = ExperimentState.Initialising;
            }
            else
            {
                HudManager.DisplayText("Welcome!");
            }
            break;

        /*
         *************************************************
         *  InitializingApplication
         *************************************************
         */
        // Perform initialization functions before starting experiment.
        case ExperimentState.Initialising:
            //
            // Perform experiment initialization procedures
            //
            // Enable colliders
            AvatarSystem.EnableAvatarColliders();
            // Initialize arm guide
            guideManager.Initialize(startAngleList[angleNumber - 1], endAngleList[angleNumber - 1], movementTimeList[timeNumber - 1]);
            guideManager.GoToStart();

            //
            // Initialize data logs
            //
            motionLogger.AddNewLogFile(startAngleList[angleNumber - 1] + "_" + endAngleList[angleNumber - 1] + "_" + movementTimeList[timeNumber - 1], iterationNumber, motionDataFormat);

            //
            // Go to training
            //
            experimentState = ExperimentState.Training;
            break;

        /*
         *************************************************
         *  Practice
         *************************************************
         */
        // Perform initialization functions before starting experiment.
        case ExperimentState.Training:
            //
            // Guide subject through training
            //

            //
            // Go to instructions
            //
            experimentState = ExperimentState.Instructions;
            break;

        /*
         *************************************************
         *  GivingInstructions
         *************************************************
         */
        case ExperimentState.Instructions:
            HudManager.DisplayText(movementTimeList[timeNumber - 1] + " sec. movement.", 2.0f);
            // Skip instructions when repeating sessions
            if (SkipInstructions)
            {
                //hudManager.DisplayText("Move to guide", 2.0f);
                experimentState = ExperimentState.WaitingForStart;
                break;
            }

            //
            // Give instructions
            //

            //
            // Go to waiting for start
            //
            experimentState = ExperimentState.WaitingForStart;
            break;

        /*
         *************************************************
         *  WaitingForStart
         *************************************************
         */
        case ExperimentState.WaitingForStart:

            // Check if pause requested
            UpdatePause();
            switch (waitState)
            {
            // Waiting for subject to grab the object.
            case WaitState.Waiting:
                if (guideManager.StartGuiding())
                {
                    //StopAllCoroutines();
                    HudManager.ClearText();
                    taskTime = 0.0f;
                    HUDCountDown(3);
                    experimentState = ExperimentState.PerformingTask;
                }
                break;

            default:
                break;
            }
            break;

        /*
         *************************************************
         *  PerformingTask
         *************************************************
         */
        case ExperimentState.PerformingTask:
            // Task performance is handled deterministically in FixedUpdate.
            break;

        /*
         *************************************************
         *  AnalizingResults
         *************************************************
         */
        case ExperimentState.AnalizingResults:
            HudManager.DisplayText("Rest your arm.", 5.0f);
            // Allow 3 seconds after task end to do calculations
            SetWaitFlag(5.0f);

            //
            // Data analysis and calculations
            //

            //
            // Adaptive system update (when available)
            //

            //
            // Data logging and log management
            //
            motionLogger.CloseLog();

            //
            // Flow managment
            //

            // Rest for some time when required
            if (IsRestTime())
            {
                HudManager.ClearText();
                HudManager.DisplayText("Rest your arm.", 2.0f);
                SetWaitFlag(RestTime);
                experimentState = ExperimentState.Resting;
                break;
            }
            else if (IsEndOfExperiment())
            {
                experimentState = ExperimentState.End;
                break;
            }
            // Check whether the new session condition is met
            else if (IsEndOfSession())
            {
                //
                // Update iterations and flow control
                //
                iterationNumber++;
                timeIterations++;
                totalIterations++;
                // Go to next
                experimentState = ExperimentState.InitializingNext;
                break;
            }
            else
            {
                experimentState = ExperimentState.UpdatingApplication;
            }
            break;

        /*
         *************************************************
         *  UpdatingApplication
         *************************************************
         */
        case ExperimentState.UpdatingApplication:
            if (WaitFlag)
            {
                //
                // Update iterations and flow control
                //
                iterationNumber++;
                timeIterations++;
                totalIterations++;

                //
                // Update experiment object
                //
                guideManager.GoToStart();

                //
                // Update log requirements
                //
                motionLogger.AddNewLogFile(startAngleList[angleNumber - 1] + "_" + endAngleList[angleNumber - 1] + "_" + movementTimeList[timeNumber - 1], iterationNumber, motionDataFormat);

                //
                // Go to start of next iteration
                //
                HudManager.DisplayText("Move to guide", 2.0f);
                experimentState = ExperimentState.WaitingForStart;
            }
            break;

        /*
         *************************************************
         *  InitializingNext
         *************************************************
         */
        case ExperimentState.InitializingNext:
            if (WaitFlag)
            {
                //
                // Perform session closure procedures
                //

                //
                // Initialize new session variables and flow control
                //
                iterationNumber = 1;
                sessionNumber++;
                // Still doing the angle repetitions for the same time
                if (timeIterations < timeIterationLimit)
                {
                    angleNumber++;
                }
                // Done all the angle repetitions for the given time, reset and go to next time
                else
                {
                    angleNumber    = 1;
                    timeIterations = 1;
                    timeNumber++;
                }

                //
                // Update experiment object
                //
                guideManager.GoToStart();
                //
                // Initialize data logging
                //

                experimentState = ExperimentState.Initialising;     // Initialize next session
            }
            break;

        /*
         *************************************************
         *  Resting
         *************************************************
         */
        case ExperimentState.Resting:
            //
            // Check for session change or end request from experimenter
            //
            if (UpdateNext())
            {
                ConfigureNextSession();
                break;
            }
            else if (UpdateEnd())
            {
                EndExperiment();
                break;
            }
            //
            // Restart after flag is set by wait coroutine
            //
            if (WaitFlag)
            {
                if (IsEndOfExperiment())
                {
                    experimentState = ExperimentState.End;
                    break;
                }
                // Check whether the new session condition is met
                else if (IsEndOfSession())
                {
                    //
                    // Update iterations and flow control
                    //
                    iterationNumber++;
                    timeIterations++;
                    totalIterations++;
                    // Go to next
                    experimentState = ExperimentState.InitializingNext;
                    break;
                }
                else
                {
                    HudManager.DisplayText("Get ready!", 3.0f);
                    SetWaitFlag(3.0f);
                    experimentState = ExperimentState.UpdatingApplication;
                }
                break;
            }
            break;

        /*
         *************************************************
         *  Paused
         *************************************************
         */
        case ExperimentState.Paused:
            //
            // Check for session change or end request from experimenter
            //
            UpdatePause();
            if (UpdateNext())
            {
                ConfigureNextSession();
                break;
            }
            else if (UpdateEnd())
            {
                EndExperiment();
                break;
            }
            break;

        /*
         *************************************************
         *  End
         *************************************************
         */
        case ExperimentState.End:
            //
            // Update log data and close logs.
            //

            HudManager.DisplayText("Experiment end, thanks!", 5.0f);
            //
            // Return to main menu
            //
            break;

        default:
            break;
        }

        //
        // Update information displayed on monitor
        //
        string experimentInfoText = "Experiment info: \n";

        experimentInfoText += "Iteration: " + iterationNumber + "/" + iterationsPerAngle + ".\n";
        experimentInfoText += "Session: " + sessionNumber + "/" + startAngleList.Count * movementTimeList.Count + ".\n";
        InstructionManager.DisplayText(experimentInfoText);

        //
        // Update information displayed for debugging purposes
        //
        if (debug)
        {
            string debugText = "Debug info: \n";
            debugText += experimentState.ToString() + ".\n";
            if (experimentState == ExperimentState.WaitingForStart)
            {
                debugText += waitState.ToString() + ".\n";
            }
            debugText += "Angle number:" + angleNumber + ".\n";
            debugText += "Time iterations:" + timeIterations + ".\n";
            InstructionManager.DisplayText(debugText + "\n" + experimentInfoText);
        }
    }