/// <summary>
        /// Loads and instantiates a forearm avatar prefab from Resources/Avatars/Forearms.
        /// The prefab must include the tag "Forearm". Loads by name.
        /// </summary>
        /// <param name="forearmType">The name of the prefab forearm avatar to be loaded.</param>
        /// <returns>The instantiated forearm GameObject.</returns>
        private static GameObject LoadAbleForearm(float lowerArmLength, bool newTracker = true)
        {
            // Add motion tracker and assign as forearm tracker, use as parent
            //GameObject llMotionTrackerGO = AvatarSystem.AddMotionTracker();
            GameObject llMotionTrackerGO = SpawnMotionTracker(newTracker);

            llMotionTrackerGO.tag = "ForearmTracker";
            llMotionTrackerGO.transform.GetChild(1).gameObject.SetActive(false); // Disable marker

            // Load forearm from avatar folder and check whether successfully loaded.
            GameObject forearmPrefab = Resources.Load <GameObject>("Avatars/Forearms/ForearmAble");

            if (forearmPrefab == null)
            {
                throw new System.Exception("The requested socket prefab was not found.");
            }

            // Get parent prosthesis manager
            GameObject prosthesisManagerGO = GameObject.FindGameObjectWithTag("ProsthesisManager");

            // Load forearm object info
            //string objectPath = resourcesDataPath + "/Forearms/ForearmAble.json";
            //string objectDataAsJson = File.ReadAllText(objectPath);
            string objectPath       = "Avatars/Forearms/ForearmAble";
            string objectDataAsJson = Resources.Load <TextAsset>(objectPath).text;

            activeForearmData = JsonUtility.FromJson <AvatarObjectData>(objectDataAsJson);
            if (activeForearmData == null)
            {
                throw new System.Exception("The requested forearm information was not found.");
            }

            // Instantiate with tracker as parent.
            GameObject forearmGO = Object.Instantiate(forearmPrefab, Vector3.zero, forearmPrefab.transform.rotation, llMotionTrackerGO.transform);

            // Make sure the loaded forearm has a the follower script and correct setting
            LimbFollower follower = forearmGO.GetComponent <LimbFollower>();

            // If it wasn't found, then add it.
            if (follower == null)
            {
                follower = forearmGO.AddComponent <LimbFollower>();
            }

            follower.avatarType = AvatarType.AbleBodied;

            // Scale forearm to fit user's hand
            float scaleFactor = lowerArmLength / (2 * activeForearmData.dimensions.x);

            forearmGO.transform.localScale = new Vector3(scaleFactor, scaleFactor, scaleFactor);

            return(forearmGO);
        }
    private void LoadDebugAvatar()
    {
        // Load avatar
        if (avatarType == AvatarType.Transhumeral)
        {
            AvatarSystem.LoadAvatar(SaveSystem.ActiveUser, AvatarType.Transhumeral);

            // Find the residual limb and change the follower
            GameObject   residualLimbGO = GameObject.FindGameObjectWithTag("ResidualLimbAvatar");
            LimbFollower limbFollower   = residualLimbGO.GetComponent <LimbFollower>();
            Destroy(limbFollower);
            AngleFollower angleFollower = residualLimbGO.AddComponent <AngleFollower>();
            angleFollower.fixedTransform = fixedProsthesisPosition;


            // Initialize prosthesis
            GameObject prosthesisManagerGO        = GameObject.FindGameObjectWithTag("ProsthesisManager");
            ConfigurableElbowManager elbowManager = prosthesisManagerGO.AddComponent <ConfigurableElbowManager>();
            elbowManager.InitializeProsthesis(SaveSystem.ActiveUser.upperArmLength, (SaveSystem.ActiveUser.forearmLength + SaveSystem.ActiveUser.handLength / 2.0f));
            // Set the reference generator to jacobian-based.
            elbowManager.ChangeReferenceGenerator("VAL_REFGEN_JACOBIANSYN");
            instructionsText = synergyInstructions;

            // Enable & configure EMG
            if (emgEnable)
            {
                // Create and add sensor
                //EMGWiFiManager emgSensor = new EMGWiFiManager(ip, port, channelSize);
                ThalmicMyobandManager emgSensor = new ThalmicMyobandManager();
                //emgSensor.ConfigureLimits(0, 1023, 0);
                //emgSensor.ConfigureLimits(1, 1023, 0);
                AvatarSystem.AddActiveSensor(emgSensor);
                elbowManager.AddSensor(emgSensor);
                //emgSensor.StartSensorReading();

                // Set active sensor and reference generator to EMG.
                elbowManager.ChangeSensor("VAL_SENSOR_SEMG");
                elbowManager.ChangeReferenceGenerator("VAL_REFGEN_EMGPROP");
                instructionsText = emgInstructions;
            }
        }
        else
        {
            throw new System.NotImplementedException();
        }
    }
        /// <summary>
        /// Loads and instantiates a residual limb avatar prefab from Resources/Avatars/ResidualLimbs.
        /// The prefab must include the tag "ResidualLimbAvatar". Loads by name.
        /// </summary>
        /// <param name="rlType">The name of the prefab residual limb avatar to be loaded.</param>
        /// <returns>The instantiated residual limb GameObject.</returns>
        private static GameObject LoadResidualLimb(string rlType, AvatarType avatarType)
        {
            // Load Avatar object to set as parent.
            GameObject avatarGO = GameObject.FindGameObjectWithTag("Avatar");

            // Load residual limb from avatar folder and check whether successfully loaded.
            GameObject residualLimbPrefab = Resources.Load <GameObject>("Avatars/ResidualLimbs/" + rlType);

            if (residualLimbPrefab == null)
            {
                throw new System.Exception("The requested residual limb prefab was not found.");
            }

            // Load the residual object info.
            //string objectPath = resourcesDataPath + "/ResidualLimbs/" + rlType + ".json";
            //string objectDataAsJson = File.ReadAllText(objectPath);
            string objectPath       = "Avatars/ResidualLimbs/" + rlType;
            string objectDataAsJson = Resources.Load <TextAsset>(objectPath).text;

            activeResidualLimbData = JsonUtility.FromJson <AvatarObjectData>(objectDataAsJson);
            if (activeResidualLimbData == null)
            {
                throw new System.Exception("The requested residual limb information was not found.");
            }

            // Instantiate with tracker as parent.
            GameObject residualLimbGO = Object.Instantiate(residualLimbPrefab, new Vector3(0.0f, -activeResidualLimbData.dimensions.x / 1.0f, 0.0f), Quaternion.identity, avatarGO.transform);

            // Make sure the loaded residual limb has a the follower script and set the offset
            LimbFollower follower = residualLimbGO.GetComponent <LimbFollower>();

            // If it wasn't found, then add it.
            if (follower == null)
            {
                follower = residualLimbGO.AddComponent <LimbFollower>();
            }

            follower.avatarType = avatarType;
            follower.offset     = new Vector3(0.0f, -activeResidualLimbData.dimensions.x / 1.0f, 0.0f);

            return(residualLimbGO);
        }
    /// <summary>
    /// Initializes the ExperimentSystem and its components.
    /// Verifies that all components needed for the experiment are available.
    /// </summary>
    public override void InitialiseExperimentSystems()
    {
        //
        // Set the experiment type and ID
        //
        if (AvatarSystem.AvatarType == AvatarType.AbleBodied)
        {
            experimentType = ExperimentType.TypeOne;
            MonitorManager.DisplayText("Wrong avatar used. Please use a Transhumeral avatar.");
            throw new System.Exception("Able-bodied avatar not suitable for prosthesis training.");
        }
        else if (AvatarSystem.AvatarType == AvatarType.Transhumeral)
        {
            // Check if EMG is available
            bool EMGAvailable = false;
            foreach (ISensor sensor in AvatarSystem.GetActiveSensors())
            {
                if (sensor.GetSensorType().Equals(SensorType.EMGWiFi))
                {
                    EMGAvailable = true;
                    UDPSensorManager udpSensor = (UDPSensorManager)sensor;
                    udpSensor.StartSensorReading();
                }
                else if (sensor.GetSensorType().Equals(SensorType.ThalmicMyo))
                {
                    EMGAvailable = true;
                }
            }
            // Set whether emg or synergy based
            if (EMGAvailable)
            {
                experimentType   = ExperimentType.TypeTwo;
                instructionsText = emgInstructions;
                // Set EMG sensor and reference generator as active.
                // Get prosthesis
                GameObject prosthesisManagerGO = GameObject.FindGameObjectWithTag("ProsthesisManager");
                elbowManager = prosthesisManagerGO.GetComponent <ConfigurableElbowManager>();
                // Set active sensor and reference generator to EMG.
                //elbowManager.ChangeSensor("VAL_SENSOR_SEMG");
                elbowManager.ChangeSensor("VAL_SENSOR_THALMYO");
                elbowManager.ChangeReferenceGenerator("VAL_REFGEN_EMGPROP");
            }
            else
            {
                experimentType   = ExperimentType.TypeThree;
                instructionsText = synergyInstructions;
                // Set VIVE tracker and Jacobian synergy as active.
                // Get prosthesis
                GameObject prosthesisManagerGO = GameObject.FindGameObjectWithTag("ProsthesisManager");
                elbowManager = prosthesisManagerGO.GetComponent <ConfigurableElbowManager>();
                if (elbowManager.GetInterfaceType() == ReferenceGeneratorType.JacobianSynergy)
                {
                    // Set the reference generator to jacobian-based.
                    elbowManager.ChangeSensor("VAL_SENSOR_VIVETRACKER");
                    elbowManager.ChangeReferenceGenerator("VAL_REFGEN_JACOBIANSYN");
                }
                else if (elbowManager.GetInterfaceType() == ReferenceGeneratorType.LinearKinematicSynergy)
                {
                    // Set the reference generator to linear synergy.
                    elbowManager.ChangeSensor("VAL_SENSOR_VIVETRACKER");
                    elbowManager.ChangeReferenceGenerator("VAL_REFGEN_LINKINSYN");
                }
                else
                {
                    throw new System.Exception("The prosthesis interface available is not supported.");
                }
            }

            if (!debug)
            {
                // Find the residual limb and change the follower
                residualLimbGO               = GameObject.FindGameObjectWithTag("ResidualLimbAvatar");
                limbFollower                 = residualLimbGO.GetComponent <LimbFollower>();
                limbFollower.enabled         = false;
                angleFollower                = residualLimbGO.AddComponent <AngleFollower>();
                angleFollower.fixedTransform = fixedProsthesisPosition;
            }
        }
        else
        {
            throw new System.NotImplementedException();
        }

        // Get Raycast Debug info
        // handGO = GameObject.FindGameObjectWithTag("Hand");
        // elbowGO = GameObject.FindGameObjectWithTag("Elbow_Upper");
        // residualLimbGO = GameObject.FindGameObjectWithTag("ResidualLimbAvatar");
    }