/// <summary> /// Coroutine for the welcome text. /// Implement your welcome loop here. /// </summary> /// <returns>Yield instruction</returns> public override IEnumerator WelcomeLoop() { // First flag that we are in the welcome routine welcomeDone = false; inWelcome = true; welcomeDone = true; HudManager.DisplayText("Look to the top right. Instructions will be displayed there."); InstructionManager.DisplayText("Hi " + SaveSystem.ActiveUser.name + "! Welcome to the virtual world. \n\n (Press the trigger button to continue...)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Make sure you are standing on top of the green circle. \n\n (Press the trigger button to continue...)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Test audio. \n\n (If you can hear the audio, press the trigger button to continue...)"); audio.loop = true; audio.volume = 0.4f; audio.Play(); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. audio.loop = false; audio.Stop(); audio.volume = 1.0f; // // Hud intro InstructionManager.DisplayText("Alright " + SaveSystem.ActiveUser.name + ", let me introduce you to your assistant, the Heads Up Display (HUD)." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Look at the HUD around your left eye. It's saying hi!"); HudManager.DisplayText("Hi! I'm HUD!" + "\n (Press trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. HudManager.DisplayText("I'm here to help!" + "\n (Press trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. HudManager.DisplayText("Look at the screen.", 3); // // Experiment overall intro InstructionManager.DisplayText("Alright " + SaveSystem.ActiveUser.name + ", let me explain what we are doing today." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Today, the experiment will require you to reach to the targets in front of you." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("You will do 2 sessions, 1st 90 iterations and 2nd 270 iterations " + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("A 60 sec rest occurs every 35 iterations" + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. // Now that you are done, set the flag to indicate we are done. welcomeDone = true; }
/// <summary> /// Coroutine for the welcome text. /// Implement your welcome loop here. /// </summary> /// <returns>Yield instruction</returns> public override IEnumerator WelcomeLoop() { // First flag that we are in the welcome routine welcomeDone = false; inWelcome = true; // HudManager.DisplayText("Look to the top right."); InstructionManager.DisplayText("Hi " + SaveSystem.ActiveUser.name + "! Welcome to the virtual world. \n\n (Press the trigger button to continue...)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Make sure you are standing on top of the green circle. \n\n (Press the trigger button to continue...)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. // Now that you are done, set the flag to indicate we are done. welcomeDone = true; }
/// <summary> /// Coroutine for the experiment training. /// Implement your training loop here. /// </summary> /// <returns>Yield instruction</returns> public override IEnumerator TrainingLoop() { // First flag that we are in the training routine trainingDone = false; inTraining = true; // Only run the training loop when requested, for instance some session may require different session. if (trainingPerSession[sessionNumber - 1] == 1) { // InstructionManager.DisplayText("This is training. You'll probably want to guide your subject through the task here! \n Press the trigger button to continue..."); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. // InstructionManager.DisplayText("Like... Punch the Cube!"); yield return(new WaitForSecondsRealtime(5.0f)); HudManager.DisplayText("What Cube???", 2.0f); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. // HudManager.DisplayText("On your left, quick!!", 5.0f); if (isCubeAvailable != true) { isCubeAvailable = true; cubeGO.SetActive(true); } yield return(new WaitForSecondsRealtime(5.0f)); HudManager.DisplayText("And it's gone...", 3.0f); isCubeAvailable = false; cubeGO.SetActive(false); yield return(new WaitForSecondsRealtime(5.0f)); // HudManager.DisplayText("Look to the screen."); InstructionManager.DisplayText("It's revolutionary ain't it! \n Press the trigger button to continue..."); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. } // Now that you are done, set the flag to indicate we are done. trainingDone = true; }
/// <summary> /// Coroutine for the experiment instructions. /// Implement your instructions loop here. /// </summary> /// <returns>Yield instruction</returns> public override IEnumerator InstructionsLoop() { // First flag that we are in the instructions routine instructionsDone = false; inInstructions = true; // InstructionManager.DisplayText("These are the isntructions. You can use other conditions to wait, not only the trigger press! e.g. 10 seconds."); HudManager.DisplayText("You can use the HUD too!"); yield return(new WaitForSecondsRealtime(10.0f)); // Wait for some time. // HudManager.DisplayText("And get their attention!", 5.0f); InstructionManager.DisplayText("It's exciting! \n Press the trigger button to continue..."); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. // Now that you are done, set the flag to indicate we are done. instructionsDone = true; }
/// <summary> /// Coroutine for the welcome text. /// Implement your welcome loop here. /// </summary> /// <returns>Yield instruction</returns> public override IEnumerator WelcomeLoop() { // First flag that we are in the welcome routine welcomeDone = false; inWelcome = true; // HudManager.DisplayText("Look to the top right."); InstructionManager.DisplayText("This is the welcome. Here you can write a welcome for your subject! \n Press the trigger button to continue..."); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. // HudManager.ClearText(); InstructionManager.DisplayText("It's awesome! \n Press the trigger button to continue..."); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. // Now that you are done, set the flag to indicate we are done. welcomeDone = true; }
/// <summary> /// Coroutine for the experiment instructions. /// Implement your instructions loop here. /// </summary> /// <returns>Yield instruction</returns> public override IEnumerator InstructionsLoop() { // First flag that we are in the instructions routine instructionsDone = false; inInstructions = true; //Instructions if (sessionNumber == 1) // first session { InstructionManager.DisplayText("Alright, the sphere targets should have spawned for you." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("In the 1st session, you will need to reach to the spheres using your index finger." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("If you are ready, let's start training!" + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. } else if (sessionNumber == 2) // second session { InstructionManager.DisplayText("You've finished the 1st session, well done. Let's start the second session" + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("The sphere targets have been replaced by bottle targets and a bottle has been placed in your hand." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("In the 2nd session, you will need to match bothe the target locations and orientations ." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("If you are ready, let's start training!" + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. } // Now that you are done, set the flag to indicate we are done. instructionsDone = true; }
/// <summary> /// Coroutine for the experiment training. /// Implement your training loop here. /// </summary> /// <returns>Yield instruction</returns> public override IEnumerator TrainingLoop() { // First flag that we are in the training routine trainingDone = false; inTraining = true; if (sessionNumber == 1) { InstructionManager.DisplayText("Let's start training then!" + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. // // HUD Colours InstructionManager.DisplayText("First, let's tell you about the colour of the HUD. It will tell you what you need to do." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("<Red>: for returning back and adjusting your start position." + "\n\n (Press the trigger)"); HudManager.DisplayText("I'm red!"); HudManager.colour = HUDManager.HUDColour.Red; yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("<Orange>: for waiting for the countdown." + "\n\n (Press the trigger)"); HudManager.DisplayText("I'm orange!"); HudManager.colour = HUDManager.HUDColour.Orange; yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("<Blue>: for reaching for the target.!" + "\n\n (Press the trigger)"); HudManager.DisplayText("I'm blue!"); HudManager.colour = HUDManager.HUDColour.Blue; yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("You need to hold on you reaching position for a while until the HUD says 'Well Done', like" + "\n\n (Press the trigger)"); HudManager.colour = HUDManager.HUDColour.Red; HudManager.DisplayText("Well Done"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. HudManager.ClearText(); HudManager.colour = HUDManager.HUDColour.Red; // // Reaching practice InstructionManager.DisplayText("Next, the colour of the targets will tell you the status of the target." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("<Blue>: the target is selected as the next target." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("<Green>: you have successfully reached the selected one." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. // // Explain routine InstructionManager.DisplayText("Alright, let's explain the task routine." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("The task routine is: first keep your start position for 3 seconds, and HUD will tell you when to go." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Then reach to the target in <blue> using your index finger." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Finally, when you reach, hold on for a while, until you hear 'Return' and HUD says 'Well done'." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. // // Important messages InstructionManager.DisplayText("Important!: Keep your final reaching position when you hear 'Hold', like !!! " + "\n\n (Press the trigger to play)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. audio.clip = holdAudioClip; audio.Play(0); HudManager.DisplayText("Hold on for a while!!"); InstructionManager.DisplayText("Important!: Keep your final reaching position when you hear 'Hold', like !!! " + "\n\n (Press the trigger to continue)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Important!: Do not return until HUD says 'Well Done' and you hear 'Return', like !!! " + "\n\n (Press the trigger to play)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. audio.clip = returnAudioClip; audio.Play(0); HudManager.DisplayText("Well done!!"); InstructionManager.DisplayText("Important!: Do not return until HUD says 'Well Done' and you hear 'Return', like !!! " + "\n\n (Press the trigger to continue)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. // // Have a try InstructionManager.DisplayText("Ok, let's have a try of a routine." + "\n\n (Press the trigger)"); HudManager.ClearText(); HudManager.colour = HUDManager.HUDColour.Red; yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. // // Start position InstructionManager.DisplayText("First, let's show you the start position." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. // // Start position InstructionManager.DisplayText("Your upper arm and elbow should point downards." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Try it. The HUD displays: (current upper and fore arm angle/the desired one)"); //startPosPhoto.SetActive(true); //startPosPhoto.transform.Rotate(new Vector3(0.0f, 90.0f, 0.0f), Space.World); yield return(new WaitUntil(() => IsReadyToStart())); //startPosPhoto.SetActive(false); HudManager.ClearText(); //Start practice gridManager.SelectTarget(0); InstructionManager.DisplayText("The sphere that you need to reach will turn blue. Don't reach now." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("You'll have to wait for a three second countdown. Look at the sphere and get ready!" + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. HudManager.colour = HUDManager.HUDColour.Orange; HUDCountDown(1); yield return(new WaitUntil(() => CountdownDone)); // And wait InstructionManager.DisplayText("Reach for it by index finger!!"); HudManager.DisplayText("Reach for it by index finger!!"); HudManager.colour = HUDManager.HUDColour.Blue; yield return(new WaitUntil(() => IsTaskDone())); // Signal the subject that the task is done HudManager.DisplayText("Hold on your current position!"); yield return(new WaitForSecondsRealtime(1.0f)); audio.clip = returnAudioClip; audio.Play(); HudManager.colour = HUDManager.HUDColour.Red; HudManager.DisplayText("Well done (you can return to start position)!"); // Reset flags hasReached = false; taskComplete = false; HudManager.DisplayText("You can relax now. Look to the top right.", 3); // // End InstructionManager.DisplayText("Important: Do not return until you hear 'Return' and HUD says 'Well Done' !!! " + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Otherwise, you look ready to go! Good luck!" + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. } if (sessionNumber == 2) { InstructionManager.DisplayText("Let's start training then!" + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. // // Reaching practice InstructionManager.DisplayText("Everthing is the same except you need to match the orientations." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Ok, let's have a try." + "\n\n (Press the trigger)"); HudManager.ClearText(); HudManager.colour = HUDManager.HUDColour.Red; yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. //Start practice gridManager.SelectTarget(2); InstructionManager.DisplayText("The sphere that you need to reach will turn blue. Do not reach now." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("You'll have to wait for a three second countdown. Look at the sphere and get ready!" + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. HudManager.colour = HUDManager.HUDColour.Orange; HUDCountDown(3); yield return(new WaitUntil(() => CountdownDone)); // And wait InstructionManager.DisplayText("Reach for it!!"); HudManager.DisplayText("Reach for it!!"); HudManager.colour = HUDManager.HUDColour.Blue; yield return(new WaitUntil(() => IsTaskDone())); // Signal the subject that the task is done HudManager.DisplayText("Hold on!"); yield return(new WaitForSecondsRealtime(1.0f)); HudManager.colour = HUDManager.HUDColour.Red; HudManager.DisplayText("Well done (you can return to start position)!"); // Reset flags hasReached = false; taskComplete = false; HudManager.DisplayText("You can relax now. Look to the top right.", 3); // // End InstructionManager.DisplayText("Important: Hold your final reaching position until you hear 'Return' and HUD says 'Well Done' !!! " + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Otherwise, you look ready to go! Good luck!" + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. } // Now that you are done, set the flag to indicate we are done. trainingDone = true; }
/// <summary> /// Coroutine for the welcome text. /// Implement your welcome loop here. /// </summary> /// <returns>Yield instruction</returns> public override IEnumerator WelcomeLoop() { // First flag that we are in the welcome routine welcomeDone = false; inWelcome = true; HudManager.DisplayText("Look to the top right. Instructions will be displayed there."); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. //HudManager.DisplayText("Look to the top right. Instructions will be displayed there."); InstructionManager.DisplayText("Hi " + SaveSystem.ActiveUser.name + "! Welcome to the virtual world. \n\n (Press the trigger button to continue...)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Make sure you are standing on top of the green circle. \n\n (Press the trigger button to continue...)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Test audio. \n\n (If you can hear the audio, press the trigger button to continue...)"); audio.loop = true; audio.volume = 0.4f; audio.Play(); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. audio.loop = false; audio.Stop(); audio.volume = 1.0f; // // Hud intro InstructionManager.DisplayText("Alright " + SaveSystem.ActiveUser.name + ", let me introduce you to your assistant, the Heads Up Display (HUD)." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Look at the HUD around your left eye. It's saying hi!"); HudManager.DisplayText("Hi! I'm HUD!" + "\n (Press trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. HudManager.DisplayText("I'm here to help!" + "\n (Press trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. HudManager.DisplayText("Look at the screen.", 3); // // Experiment overall intro InstructionManager.DisplayText("Alright " + SaveSystem.ActiveUser.name + ", let me explain what we are doing today." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Today, the experiment will require you to reach to the targets in front of you." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("You will do 2 sessions, 1st 90 iterations and 2nd 270 iterations " + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("A 60 sec rest occurs every 35 iterations" + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. // // Generate the targets InstructionManager.DisplayText("First, let's set up the experiment targets for you. \n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Extend your arms naturally forward and the desired joint positions will be shown on the HUD. \n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("HUD Format: SH - Shoulder, EB - Elbow and in the bracket (current joint angle / the desired one)"); for (int i = 0; i < shoulderDesiredPos.Length; i++) { for (int j = 0; j < elbowDesiredPos.Length; j++) { //yield return new WaitUntil(() => IsAtRightPosition(shoulderDesiredPos[i], elbowDesiredPos[j], 2.0f)); if (i % 2 == 0) { yield return(new WaitUntil(() => IsAtRightPosition(shoulderDesiredPos[i], elbowDesiredPos[j], 2.0f))); } else { yield return(new WaitUntil(() => IsAtRightPosition(shoulderDesiredPos[i], elbowDesiredPos[elbowDesiredPos.Length - 1 - j], 2.0f))); } GameObject[] hand = GameObject.FindGameObjectsWithTag("IndexFingerCollider"); //Debug.Log(indexFinger[0].transform.position.ToString("F3")); Vector3 location = Quaternion.Euler(0, this.worldOrientation, 0) * hand[0].transform.position; // Add the index finger location gridManager.AddTargetLocation(location); } } gridManager.AddTargetRotation(new Vector3(0.0f, 0.0f, 0.0f)); gridManager.AddTargetRotation(new Vector3(45.0f, 0.0f, 0.0f)); gridManager.AddTargetRotation(new Vector3(-45.0f, 0.0f, 0.0f)); // Now that you are done, set the flag to indicate we are done. welcomeDone = true; }
/// <summary> /// Coroutine for the experiment training. /// Implement your training loop here. /// </summary> /// <returns>Yield instruction</returns> public override IEnumerator TrainingLoop() { // First flag that we are in the training routine trainingDone = false; inTraining = true; // Only run the training loop when requested, for instance some session may require different session. if (trainingPerSession[sessionNumber - 1] == 1) { // Hud intro InstructionManager.DisplayText("Alright " + SaveSystem.ActiveUser.name + ", let's show you the ropes." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Let me introduce you to your assistant, the Heads Up Display (HUD)." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Say hi!"); HudManager.DisplayText("Hi! I'm HUD!" + "\n (Press trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. HudManager.DisplayText("I'm here to help!" + "\n (Press trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. HudManager.DisplayText("Look at the screen.", 3); InstructionManager.DisplayText("Let's start training then!" + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. // Type instructions if (experimentType == ExperimentType.TypeOne) { InstructionManager.DisplayText("First, we'll show you the start position." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. } else if (experimentType == ExperimentType.TypeTwo) { InstructionManager.DisplayText("First, we'll show how to use the prosthesis." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("When the prosthesis is not enabled, the HUD centre will turn yellow." + "\n\n (Press the trigger)"); HudManager.centreColour = HUDManager.HUDCentreColour.Yellow; HudManager.DisplayText("\n <- Like so."); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. HudManager.ClearText(); InstructionManager.DisplayText("To activate the prosthesis, press the circle button."); yield return(new WaitUntil(() => elbowManager.IsEnabled)); // And wait for the subject to enable it. HudManager.DisplayText("\n <- I'll be transparent!"); InstructionManager.DisplayText("Try moving it around." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Nice! Let's deactivate the prosthesis for now." + "\n\n (Press the trigger)"); yield return(new WaitUntil(() => !elbowManager.IsEnabled)); // And wait for the subject to disable it. InstructionManager.DisplayText("Now, we'll show you the start position." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. } // // Start position InstructionManager.DisplayText("Your upper arm should be relaxed pointing downards while your elbow should be bent 90 degrees." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Like so:" + "\n Try it."); startPosPhoto.SetActive(true); yield return(new WaitUntil(() => IsReadyToStart())); startPosPhoto.SetActive(false); HudManager.ClearText(); // // HUD Colours InstructionManager.DisplayText("The colour of the HUD will tell you what you need to do." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Red for adjusting your start position." + "\n\n (Press the trigger)"); HudManager.DisplayText("I'm red!"); HudManager.colour = HUDManager.HUDColour.Red; yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Orange for waiting for the countdown." + "\n\n (Press the trigger)"); HudManager.DisplayText("I'm orange!"); HudManager.colour = HUDManager.HUDColour.Orange; yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Blue for reaching for the sphere!" + "\n\n (Press the trigger)"); HudManager.DisplayText("I'm blue!"); HudManager.colour = HUDManager.HUDColour.Blue; yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Green for returning to the start position." + "\n\n (Press the trigger)"); HudManager.DisplayText("I'm green!"); HudManager.colour = HUDManager.HUDColour.Green; // // Practice yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Now, let's practice reaching for a target!" + "\n\n (Press the trigger)"); HudManager.ClearText(); HudManager.colour = HUDManager.HUDColour.Red; yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("The sphere that you need to reach will turn blue." + "\n\n (Press the trigger)"); gridManager.SelectBall(0); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("You'll have to wait for a three second countdown. Look at the sphere and get ready!" + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. HudManager.colour = HUDManager.HUDColour.Orange; HUDCountDown(3); yield return(new WaitUntil(() => CountdownDone)); // And wait InstructionManager.DisplayText("Reach for it!!"); HudManager.DisplayText("Reach for it!!"); HudManager.colour = HUDManager.HUDColour.Blue; yield return(new WaitUntil(() => IsTaskDone())); // Signal the subject that the task is done HudManager.colour = HUDManager.HUDColour.Green; // Reset flags hasReached = false; taskComplete = false; HudManager.DisplayText("You can relax now.", 3); // // End InstructionManager.DisplayText("Make sure you hold your position until the HUD turns green before moving back to the start position." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Otherwise, you look ready to go! Good luck!" + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. } // Now that you are done, set the flag to indicate we are done. trainingDone = true; }
/// <summary> /// Coroutine for the experiment instructions. /// Implement your instructions loop here. /// </summary> /// <returns>Yield instruction</returns> public override IEnumerator InstructionsLoop() { // First flag that we are in the instructions routine instructionsDone = false; inInstructions = true; // InstructionManager.DisplayText("Alright " + SaveSystem.ActiveUser.name + ", let me explain what we are doing today." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Today you are doing the " + AvatarSystem.AvatarType + " version of the experiment, which means..." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. // Type instructions if (experimentType == ExperimentType.TypeOne) { InstructionManager.DisplayText("You'll be reaching for a bunch of floating colorful spheres!" + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("You should see 9 spheres arranged in a 3x3 matrix. They should all be reachable, if not, please let me know." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("You are not allowed to step! So if they are too far away, I'll adjust them." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("You'll have to touch each sphere a total of " + iterationsPerTarget + " times." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("The order will be random; however, you'll be shown which one to touch before each reach." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("You don't need to do anything special, just reach as you normally would, comfortably." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. } else if (experimentType == ExperimentType.TypeTwo) { InstructionManager.DisplayText("You'll be reaching for a single floating colorful sphere while using a smart prosthesis!" + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("You'll have to reach for the sphere a total of " + iterationsPerTarget + " times." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("At the beginning it might be a bit difficult to reach and you'll need to compensate with your upper body." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("You should not step though!" + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("However, after each reach, the prosthesis will learn from your movement and adjust itself." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("After a few reachs it should be a piece of cake." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. } else { throw new System.Exception("The experiment type is not valid. Place: Instructions"); } InstructionManager.DisplayText("There is no break in this experiment, but if you feel tired or any discomfort let me know immediately and we'll take a break or stop." + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Remember you are in VR, so the objects you see are not actually there. So... Don't lean on them!" + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("Also, objects you can't see may be around you, so don't go running around. You'll have a chance to explore at the end. :)" + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. InstructionManager.DisplayText("If you are ready, let's start training!" + "\n\n (Press the trigger)"); yield return(WaitForSubjectAcknowledgement()); // And wait for the subject to cycle through them. // Now that you are done, set the flag to indicate we are done. instructionsDone = true; }
private void FixedUpdate() { // // Tasks performed determinalistically throughout the experiment // E.g. data gathering. // switch (experimentState) { case ExperimentState.PerformingTask: // // Gather data while experiment is in progress // string displayData = "Training time elapsed: " + taskTime.ToString() + " seconds."; // Read from all user sensors foreach (ISensor sensor in AvatarSystem.GetActiveSensors()) { if (sensor.GetSensorType().Equals(SensorType.EMGWiFi)) { displayData += "\n" + sensor.GetSensorType().ToString() + " Command:"; float[] sensorData = sensor.GetAllProcessedData(); foreach (float element in sensorData) { displayData += "\n" + element.ToString(); } } else if (sensor.GetSensorType().Equals(SensorType.VirtualEncoder)) { displayData += "\n" + sensor.GetSensorType().ToString() + " Command:"; float[] sensorData = sensor.GetAllProcessedData(); foreach (float element in sensorData) { displayData += "\n" + element.ToString(); } } } InstructionManager.DisplayText(displayData); //hudManager.DisplayText(logData); // // Append data to lists // taskTime += Time.fixedDeltaTime; // // Raycast debug // // Vector3 shoulderToElbow = elbowGO.transform.position - residualLimbGO.transform.position; // Vector3 shoulderToHand = handGO.transform.position - (residualLimbGO.transform.position - 0.25f * shoulderToElbow); // Debug.DrawRay(residualLimbGO.transform.position - 0.2f * shoulderToElbow, shoulderToHand, Color.magenta); // // Save log and reset flags when successfully compeleted task // if (IsTaskDone()) { // // Perform data management, such as appending data to lists for analysis // // // Save logger for current experiment and change to data analysis // //ExperimentSystem.GetActiveLogger(1).CloseLog(); // // Clear data management buffers // experimentState = ExperimentState.AnalizingResults; break; } // Check if requested to end training UpdateEnd(); break; default: break; } }
// Update is called once per frame void Update() { switch (experimentState) { /* ************************************************* * HelloWorld ************************************************* */ // Welcome subject to the virtual world. case ExperimentState.Welcome: if (WaitFlag) { if (debug) { TeleportToStartPosition(); } HudManager.ClearText(); experimentState = ExperimentState.Initialising; } else { HudManager.DisplayText("Welcome!"); InstructionManager.DisplayText("Hello world!"); } break; /* ************************************************* * InitializingApplication ************************************************* */ // Perform initialization functions before starting experiment. case ExperimentState.Initialising: // // Perform experiment initialization procedures // // // Initialize data logs // // // 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: // Skip instructions when repeating sessions if (SkipInstructions) { HudManager.DisplayText("Move to start", 2.0f); // Turn targets clear experimentState = ExperimentState.WaitingForStart; break; } // // Give instructions // // // Go to waiting for start // HudManager.DisplayText("Move to start", 2.0f); // Turn targets clear experimentState = ExperimentState.WaitingForStart; break; /* ************************************************* * WaitingForStart ************************************************* */ case ExperimentState.WaitingForStart: // Show status to subject infoText = GetInfoText(); InstructionManager.DisplayText(infoText); // Check if pause requested UpdatePause(); switch (waitState) { // Waiting for subject to get to start position. case WaitState.Waiting: if (IsReadyToStart()) { startEnable = true; // Select target gridManager.SelectBall(iterationNumber - 1); waitState = WaitState.Countdown; } break; // HUD countdown for reaching action. case WaitState.Countdown: // If all is good and haven't started counting, start. if (startEnable && !counting && !CountdownDone) { // Manage countdown HudManager.ClearText(); StopHUDCountDown(); counting = true; HUDCountDown(3); } // If all is good and the countdownDone flag is raised, switch to reaching. else if (CountdownDone) { // Reset flags startEnable = false; counting = false; countdownDone = false; // Continue experimentState = ExperimentState.PerformingTask; waitState = WaitState.Waiting; break; } // If hand goes out of target reset countdown and wait for position else if (!IsReadyToStart() && !CountdownDone) { StopHUDCountDown(); startEnable = false; counting = false; countdownDone = false; // Clear ball gridManager.ResetBallSelection(); // Indicate to move back HudManager.DisplayText("Move to start", 2.0f); waitState = WaitState.Waiting; break; } break; default: break; } break; /* ************************************************* * PerformingTask ************************************************* */ case ExperimentState.PerformingTask: // Task performance is handled deterministically in FixedUpdate. break; /* ************************************************* * AnalizingResults ************************************************* */ case ExperimentState.AnalizingResults: // Allow 3 seconds after task end to do calculations SetWaitFlag(3.0f); // // Data analysis and calculations // // // System update // // // Data logging // // // Flow managment // // Rest for some time when required if (IsRestTime()) { SetWaitFlag(RestTime); experimentState = ExperimentState.Resting; } // Check whether the new session condition is met else if (IsEndOfSession()) { experimentState = ExperimentState.InitializingNext; } // Check whether the experiment end condition is met else if (IsEndOfExperiment()) { experimentState = ExperimentState.End; } else { experimentState = ExperimentState.UpdatingApplication; } break; /* ************************************************* * UpdatingApplication ************************************************* */ case ExperimentState.UpdatingApplication: if (WaitFlag) { // // Update iterations and flow control // iterationNumber++; completedIterations++; // // Update log requirements // // // // Go to start of next iteration experimentState = ExperimentState.WaitingForStart; } break; /* ************************************************* * InitializingNext ************************************************* */ case ExperimentState.InitializingNext: // // Perform session closure procedures // // // Initialize new session variables and flow control // iterationNumber = 1; sessionNumber++; skipInstructions = true; // // Initialize data logging // ExperimentSystem.GetActiveLogger(1).AddNewLogFile(sessionNumber, iterationNumber, "Data format"); 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) { HudManager.DisplayText("Get ready to restart!", 3.0f); SetWaitFlag(5.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. // // // Return to main menu // default: break; } // // Update information displayed on monitor // // // Update information displayed for debugging purposes // if (debug) { debugText.text = experimentState.ToString() + "\n"; if (experimentState == ExperimentState.WaitingForStart) { debugText.text += waitState.ToString() + "\n"; } float qShoulder = Mathf.Rad2Deg * (upperArmTracker.GetProcessedData(5) + Mathf.PI); // Offsetting to horizontal position being 0. float qElbow = Mathf.Rad2Deg * (lowerArmTracker.GetProcessedData(5)) - qShoulder; // Offsetting to horizontal position being 0. debugText.text += qShoulder.ToString() + "\n"; debugText.text += qElbow.ToString() + "\n"; } }
// 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); } }