void initVariables()
{
    trial.init(parameters);
}
Beispiel #2
0
/*** FUNCTIONS FOR TRIAL MODE DRAWING ***/
void advanceTrial()
{
    if ( trial.isEmpty() )
    {
#ifdef WIN32
        for (int i=0; i<3; i++)
        {
            Beep(220,440);
            totalTimer.sleep(20);
        }
#endif
        exit(0);
    }

    switch (trialMode)
    {
    case FIXATIONMODE:
    {
#ifdef WIN32
        Beep(440,440);
#endif
        totalTimer.start();
        stimulusTimer.start();
        //clearAndWait(2);
        trialMode=STIMULUSMODE;
    }
    break;
    case STIMULUSMODE:
    {
#ifdef WIN32
        Beep(440,440);
#endif
        trialMode=PROBEMODE;
        totalTimer.start();
        stimulusTimer.start();
    }
    break;
    case PROBEMODE:
    {
#ifdef WIN32
        Beep(880,440);
#endif
        resetPointStrip();
        responseTimer.start();
        totalTimer.start();
        trialMode=FIXATIONMODE;
    }
    }
    resetPointStrip();
    factors = trial.getNext();
    trialNumber++;
    responseFile << setw(6) << left <<
                 trialNumber << "\t" <<
                 factors["Tilt"] << "\t"  <<
                 factors["Slant"] << "\t" <<
                 factors["Def"] << "\t" <<
                 factors["FlowDirection"] << "\t" <<
                 factors["FlowIncrement"] << "\t" << endl;

    double responseTime=responseTimer.getElapsedTimeInMilliSec();
    timeFrame=0.0; //this put the stimulus in the center each central time mouse is clicked in
}
// Funzione di callback per gestire pressioni dei tasti
void handleKeypress(unsigned char key, int x, int y)
{   switch (key)
    {   //Quit program
	case 'x':
		// Facendo cosi si cancella lo stimolo durante il movimento (SINCRONO) del monitor.
		// Si imposta il isStimulusDrawn a FALSE e si riaggiorna la schermata con una drawGLScene()
		// infine si muove il monitor, la chiamata blocca il programma per x secondi, si 
		// simula lo spostamento dello schermo di proiezione ed infine si reimposta isStimulusDrawn a TRUE
		// cosi' la prossima chiamata di drawStimulus() lo disegna correttamente a schermo. Provare per credere...
		factors = trial.getNext();
		isStimulusDrawn=false;
		drawGLScene();
		initProjectionScreen(factors["AbsDepth"]);
		isStimulusDrawn=true;
		break;
	case 'i':
		visibleInfo=!visibleInfo;
		break;
	case 'm':
		interoculardistance += 0.5;
	break;
	case 'n':
		interoculardistance -= 0.5;
	break;
	case 'd':
		visibleFingers=!visibleFingers;
	break;
	case '+':
	{
		// Il trucco per avanzare alla modalita' trial successiva: incrementi di uno e poi tieni il resto della 
		// divisione per due, in questo caso ad esempio sara' sempre:
		// 0,1,0,1,0,1
		// se metti il resto della divisione per 3 invece la variabile trialMode sar'
		// 0,1,2,0,1,2
		// ogni ciclo della variabile trialMode normalmente e' un trial (1)
		// puoi anche definire una funzione void advanceTrial() che si occupa di andare al trial successivo,
		// deve contenere una chiamata alla BalanceFactor::getNext() cosi' passi alla nuova lista di fattori
		// Ad esempio
		// trialMode++;
		// trialMode=trialMode%3;
	}
	break;
	case 'Q':
	case 'q':
    case 27:	//corrisponde al tasto ESC
    {   
		// Ricorda quando chiami una funzione exit() di chiamare prima cleanup cosi
		// spegni l'Optotrak ed i markers (altrimenti loro restano accesi e li rovini) 
		cleanup();
        exit(0);
    }
    break;
    case ' ':
    {
        // Here we record the head shape - coordinates of eyes and markers, but centered in (0,0,0)
        if ( headCalibrationDone==0 && allVisiblePatch )
        {
            headEyeCoords.init(markers[1].p-Vector3d(230,0,0),markers[1].p, markers[5].p,markers[6].p,markers[7].p,interoculardistance );
            headCalibrationDone=1;
			beepOk(0);
            break;
        }
        // Second calibration, you must look a fixed fixation point
        if ( headCalibrationDone==1 && allVisiblePatch )
        {
            headEyeCoords.init( headEyeCoords.getP1(),headEyeCoords.getP2(), markers[5].p, markers[6].p,markers[7].p,interoculardistance );
            headCalibrationDone=2;
            break;
        }
    }
    break;
	case 'f':
	case 'F':
		{
		// Here we record the finger tip physical markers
		if ( allVisiblePlatform && (fingerCalibrationDone==0) )
			{
			//platformFingers=markers[1].p;
			platformIndex=markers[1].p;
			platformThumb=markers[2].p;
			fingerCalibrationDone=1;
			beepOk(0);
			break;
			}
		if ( (fingerCalibrationDone==1) && allVisibleFingers )
			{
			thumbCoords.init(platformThumb, markers.at(15).p, markers.at(17).p, markers.at(18).p);
			indexCoords.init(platformIndex, markers.at(13).p, markers.at(14).p, markers.at(16).p );
			fingerCalibrationDone=2;
			beepOk(0);
			break;
			}
		if ( fingerCalibrationDone==2  && allVisibleFingers )
			{
			physicalRigidBodyTip = index;
			fingerCalibrationDone=3;
			fingerDistance = (thumb-index).norm();
			visibleInfo=!visibleInfo;
			drawTheVoid();
			initTrial();
			break;
			}
		}
		break;
    // Enter key: press to make the final calibration
    case 13:
    {
        if ( headCalibrationDone == 2 && allVisiblePatch )
        {
            headEyeCoords.init( headEyeCoords.getP1(),headEyeCoords.getP2(), markers[5].p, markers[6].p,markers[7].p,interoculardistance );
            headCalibrationDone=3;
        }
    }
    break;
      case '2':
      {  
	  }
      break;
      case '8':
      {  
      }
      break;
      case '4':
      {  
      }
      break;
      case '6':
      {  
      }
      break;
	  // In genere a me piace attaccare al tasto p una funzione che stampi 
	  // le tue variabili di interesse su standard output ad esempio la lista dei fattori attuali con nome
    case 'p':
	{
		for (map<string,double>::iterator iter = factors.begin(); iter!=factors.end(); ++iter )
		{
			cout << iter->first << " " << iter->second << endl;
		}
	}
	break;
	}

}
// Funzione di callback per gestire pressioni dei tasti
void handleKeypress(unsigned char key, int x, int y)
{   switch (key)
    {   
		case 'i':
			visibleInfo=!visibleInfo;
		break;
		case 'm':
		{
			interoculardistance += 0.5;
			headEyeCoords.setInterOcularDistance(interoculardistance);
		}
		break;
		case 'n':
		{
			interoculardistance -= 0.5;
			headEyeCoords.setInterOcularDistance(interoculardistance);
		}
		break;
		case 'Q':
		case 'q':
		case 27:	//corrisponde al tasto ESC
		{   
			// Ricorda quando chiami una funzione exit() di chiamare prima cleanup cosi
			// spegni l'Optotrak ed i markers (altrimenti loro restano accesi e li rovini) 
			cleanup();
			exit(0);
		}
		break;
		case 'f':
		case 'F':
		{
			if(condition == 1)
			{
				// Here we record the finger tip physical markers
				if ( allVisiblePlatform && fingerCalibrationDone==0 )
				{
					fingerCalibrationDone=1;
					calibration_fingers(fingerCalibrationDone);
					beepOk(0);
					break;
				}
				if ( (fingerCalibrationDone==1) && allVisibleFingers )
				{
					fingerCalibrationDone=2;
					calibration_fingers(fingerCalibrationDone);
					beepOk(0);
					break;
				}
				if ( fingerCalibrationDone==2  && allVisibleFingers )
				{
					fingerCalibrationDone=3;
					beepOk(0);
					visibleInfo=false;
					drawGLScene();

					// prepare the object
					// check where top and bottom surfaces are
					whereTop = markers[4].p.transpose();
					whereBottom = markers[3].p.transpose();
					// what's next distance Z?
					absDepth = trial.getCurrent()["AbsDepth"];
					// bring screen at Z
					initProjectionScreen(absDepth);
					// bring object at Z, with size 2 cm
					Vector3d moveBack(0.0,whereTop.y()-50.0,absDepth);
					moveObjectAbsolute(moveBack, whereBottom, 5000);
					break;
				}
			} else
				beepOk(1);
		}
		break;
		case '0':
		{
			if(condition == 0)
			{
				experimentBegun = true;
				whereTop = markers[4].p.transpose();
				visibleInfo=false;
				initTrial();
			}
			else
				beepOk(1);
		}
		break;
		case 13:
		{
			if(condition == 1 && trialNumber == 0)
			{
				experimentBegun = true;
				initTrial();
			}
		}
		break;
	}
}
Beispiel #5
0
void update(int value)
{
    // Conta i cicli di presentazione dello stimolo
    if ( (sumOutside > str2num<int>(parameters.find("StimulusCycles")) ) &&  (trialMode == STIMULUSMODE) )
    {
        sumOutside=0;
        trialMode++;
        trialMode=trialMode%4;
    }

    if (conditionInside && (sumOutside*2 > str2num<int>(parameters.find("FixationCycles"))) && (trialMode ==FIXATIONMODE )  )
    {
        sumOutside=0;
        trialMode++;
        trialMode=trialMode%4;
        stimulusDuration.start();
    }
    if ( trialMode == STIMULUSMODE )
        stimulusFrames++;
    if ( trialMode == FIXATIONMODE )
        stimulusFrames=0;

    Screen screenPassive;

    screenPassive.setWidthHeight(SCREEN_WIDE_SIZE, SCREEN_WIDE_SIZE*SCREEN_HEIGHT/SCREEN_WIDTH);
    screenPassive.setOffset(alignmentX,alignmentY);
    screenPassive.setFocalDistance(0);
    screenPassive.transform(headEyeCoords.getRigidStart().getFullTransformation()*Translation3d(center));

    camPassive.init(screenPassive);
    camPassive.setDrySimulation(true);
    camPassive.setEye(eyeRight);
    objectPassiveTransformation = ( camPassive.getModelViewMatrix()*objectActiveTransformation );
    // Coordinates picker
    markers = optotrak.getAllPoints();
    if ( isVisible(markers[1]) && isVisible(markers[2]) && isVisible(markers[3]) )
        headEyeCoords.update(markers[1],markers[2],markers[3]);
    Affine3d active = headEyeCoords.getRigidStart().getFullTransformation();

    eulerAngles.init( headEyeCoords.getRigidStart().getFullTransformation().rotation() );

    eyeLeft = headEyeCoords.getLeftEye();
    eyeRight = headEyeCoords.getRightEye();

    cyclopeanEye = (eyeLeft+eyeRight)/2.0;

    // Projection of view normal on the focal plane
    Vector3d directionOfSight = (active.rotation()*Vector3d(0,0,-1)).normalized();
    Eigen::ParametrizedLine<double,3> lineOfSightRight = Eigen::ParametrizedLine<double,3>::Through( eyeRight , eyeRight+directionOfSight );
    Eigen::ParametrizedLine<double,3> lineOfSightLeft  = Eigen::ParametrizedLine<double,3>::Through( eyeLeft, eyeLeft+directionOfSight );

    double lineOfSightRightDistanceToFocalPlane = lineOfSightRight.intersection(focalPlane);
    double lineOfSightLeftDistanceToFocalPlane = lineOfSightLeft.intersection(focalPlane);

    //double lenghtOnZ = (active*(center-eyeCalibration )+eyeRight).z();
    projPointEyeRight = lineOfSightRightDistanceToFocalPlane *(directionOfSight)+ (eyeRight);
    projPointEyeLeft= lineOfSightLeftDistanceToFocalPlane * (directionOfSight) + (eyeLeft);
    // second projection the fixation point computed with z non constant but perfectly parallel to projPointEyeRight
    lineOfSightRightDistanceToFocalPlane= (( active.rotation()*(center)) - eyeRight).norm();
    Vector3d secondProjection = lineOfSightRightDistanceToFocalPlane *(directionOfSight)+ (eyeRight);

    if ( !zOnFocalPlane )
        projPointEyeRight=secondProjection ;

    // Compute the translation to move the eye in order to avoid shear components
    Vector3d posAlongLineOfSight = (headEyeCoords.getRigidStart().getFullTransformation().rotation())*(eyeRight -eyeCalibration);

    switch ( (int)factors["Translation"] )
    {
    case -1:
    case -2:
        translationFactor.setZero();
        if ( trialMode == STIMULUSMODE )
            projPointEyeRight=center;
        break;
    case 0:
        translationFactor.setZero();
        break;
    case 1:
        translationFactor = factors["TranslationConstant"]*Vector3d(posAlongLineOfSight.z(),0,0);
        break;
    case 2:
        translationFactor = factors["TranslationConstant"]*Vector3d(0,posAlongLineOfSight.z(),0);
        break;
    }
    if ( passiveMode )
        initProjectionScreen(0,headEyeCoords.getRigidStart().getFullTransformation()*Translation3d(Vector3d(0,0,focalDistance)));
    else
        initProjectionScreen(focalDistance,Affine3d::Identity());

    checkBounds();
    /**** Save to file part ****/
    // Markers file save the used markers and time-depending experimental variable to a file
    // (Make sure that in passive experiment the list of variables has the same order)
    markersFile << trialNumber << " " << headCalibrationDone << " " << trialMode << " " ;
    markersFile <<markers[1].transpose() << " " << markers[2].transpose() << " " << markers[3].transpose() << " " << markers[17].transpose() << " " << markers[18].transpose() << " " ;

    markersFile <<	factors["Tilt"] << " " <<
                factors["Slant"] << " " <<
                factors["Translation"] << " " <<
                factors["Onset"] << " " <<
                factors["TranslationConstant"] <<
                endl;

    ofstream outputfile;
    outputfile.open("data.dat");
    outputfile << "Subject Name: " << parameters.find("SubjectName") << endl;
    outputfile << "Passive matrix:" << endl << objectPassiveTransformation.matrix() << endl;
    outputfile << "Yaw: " << toDegrees(eulerAngles.getYaw()) << endl <<"Pitch: " << toDegrees(eulerAngles.getPitch()) << endl;
    outputfile << "EyeLeft: " <<  headEyeCoords.getLeftEye().transpose() << endl;
    outputfile << "EyeRight: " << headEyeCoords.getRightEye().transpose() << endl << endl;
    outputfile << "Slant: " << instantPlaneSlant << endl;
    outputfile << "(Width,Height) [px]: " << getPlaneDimensions().transpose() << " " << endl;
    outputfile << "Factors:" << endl;
    for (map<string,double>::iterator iter=factors.begin(); iter!=factors.end(); ++iter)
    {
        outputfile << "\t\t" << iter->first << "= " << iter->second << endl;
    }
    outputfile << "Trial remaining: " << trial.getRemainingTrials()+1 << endl;
    outputfile << "Last response: " << probeAngle << endl;
    // Here we save plane projected width and height


    // now rewind the file
    outputfile.clear();
    outputfile.seekp(0,ios::beg);

    // Write down frame by frame the trajectories and angles of eyes and head
    if ( trialMode == STIMULUSMODE && headCalibrationDone > 2 )
    {
        trajFile << setw(6) << left <<
                 trialNumber << " " <<
                 stimulusFrames << " " <<
                 eyeRight.transpose() << endl;

        anglesFile << setw(6) << left <<
                   trialNumber << " " <<
                   stimulusFrames << " " <<
                   toDegrees(eulerAngles.getPitch()) << " " <<
                   toDegrees(eulerAngles.getRoll()) << " " <<
                   toDegrees(eulerAngles.getYaw()) << " " <<
                   instantPlaneSlant << endl;

        matrixFile << setw(6) << left <<
                   trialNumber << " " <<
                   stimulusFrames << " " ;
        for (int i=0; i<3; i++)
            matrixFile << objectPassiveTransformation.matrix().row(i) << " " ;
        matrixFile << endl;

        // Write the 13 special extremal points on stimFile
        stimFile << setw(6) << left <<
                 trialNumber << " " <<
                 stimulusFrames << " " ;
        double winx=0,winy=0,winz=0;

        for (PointsRandIterator iRand = redDotsPlane.specialPointsRand.begin(); iRand!=redDotsPlane.specialPointsRand.end(); ++iRand)
        {   Point3D *p=(*iRand);
            Vector3d v = objectActiveTransformation*Vector3d( p->x, p->y, p->z);

            gluProject(v.x(),v.y(),v.z(), (&cam)->getModelViewMatrix().data(), (&cam)->getProjectiveMatrix().data(), (&cam)->getViewport().data(), &winx,&winy,&winz);
            stimFile << winx << " " << winy << " " << winz << " ";
        }
        stimFile << endl;
    }

    glutPostRedisplay();
    glutTimerFunc(TIMER_MS, update, 0);
}
Beispiel #6
0
// Funzione di callback per gestire pressioni dei tasti
void handleKeypress(unsigned char key, int x, int y)
{   switch (key)
    {   //Quit program
	case 'x':
		// Facendo cosi si cancella lo stimolo durante il movimento (SINCRONO) del monitor.
		// Si imposta il isStimulusDrawn a FALSE e si riaggiorna la schermata con una drawGLScene()
		// infine si muove il monitor, la chiamata blocca il programma per x secondi, si 
		// simula lo spostamento dello schermo di proiezione ed infine si reimposta isStimulusDrawn a TRUE
		// cosi' la prossima chiamata di drawStimulus() lo disegna correttamente a schermo. Provare per credere...
		//factors = trial.getNext();
	//	trial.next();
		drawGLScene();
//		initProjectionScreen(trial.getCurrent()["AbsDepth"]);
		break;
	case 'i':
		visibleInfo=!visibleInfo;
		break;
	case 'l':
		exits=!exits;
	break;
	case 'm':
	{
		interoculardistance += 0.5;
		headEyeCoords.setInterOcularDistance(interoculardistance);
	}
	break;
	case 'n':
	{
		interoculardistance -= 0.5;
		headEyeCoords.setInterOcularDistance(interoculardistance);
	}
	break;
	case '+':
	{
		// Il trucco per avanzare alla modalita' trial successiva: incrementi di uno e poi tieni il resto della 
		// divisione per due, in questo caso ad esempio sara' sempre:
		// 0,1,0,1,0,1
		// se metti il resto della divisione per 3 invece la variabile trialMode sar'
		// 0,1,2,0,1,2
		// ogni ciclo della variabile trialMode normalmente e' un trial (1)
		// puoi anche definire una funzione void advanceTrial() che si occupa di andare al trial successivo,
		// deve contenere una chiamata alla BalanceFactor::getNext() cosi' passi alla nuova lista di fattori
		// Ad esempio
		 trialMode++;
		 trialMode=trialMode%3;
	}
	break;
	case 'Q':
	case 'q':
    case 27:	//corrisponde al tasto ESC
    {   
		// Ricorda quando chiami una funzione exit() di chiamare prima cleanup cosi
		// spegni l'Optotrak ed i markers (altrimenti loro restano accesi e li rovini) 
		cleanup();
        exit(0);
    }
    break;

	case 'f':
	case 'F':
		{
			// Interpolate the fingertip (fourth virtual marker)
			if ( fingerCalibrationDone==2 && allVisibleObject && allVisibleFingers )
			{
				fingerCalibrationDone=3;
				calibration_fingers(fingerCalibrationDone);
				beepOk(3);
				break;
			}

			// Start the experiment
			if ( fingerCalibrationDone==3  && allVisibleFingers )
			{
				fingerCalibrationDone=4;
				beepOk(0);
				visibleInfo=false;
				drawGLScene(); // this is needed otherwise the next motor command freezes the screen

				// check where the object is
				object_reset_position = markers[3].p.transpose();
				// calculate where the object has to go
				Vector3d object_position(0.0,object_reset_position.y(),-550.0);
				// move the object to position from where it is
				moveObjectAbsolute(object_position, object_reset_position, 5000);

				trial.next();
				initTrial();
				break;
			}
		}
		break;
      case 't':
      {  
		  advanceTrial();
	  }
      break;
	}
}
// INITTRIAL TO CHECK (MOSTLY FOR FINGERS-RELATED EVENTS)
void initTrial()
{
	// if the current is not an empty trial...
	if(!trial.isEmpty())
	{
		if(condition == 0)
			beepOk(0);

		if(condition == 1)
			endTrial = false;

		// these variables are reset
		showStimuli = false;
		h_stimulus = 1;
		fingersOccluded = 0;
		framesOccluded=0;
		frameN = 0;

		// random seed
		//srand(rand() % 100);
		// pick 0 or 1 at random and assign it to first_interval
		first_interval = rand() % 2;
		// pick the complementary (0 or 1) and assign it to second_interval
		second_interval = 1 - first_interval;
#ifdef SIMULATION
		//srand(5);
		testJND = str2num<double>(parameters.find("JND"));
		double JND = mathcommon::gaussRand(0,testJND);

		// set the parameters to build the stimulus:
		// HEIGHT
		//--- standard
		stimulus_height[0] = 55.0; 
		//--- comparison
		stimulus_height[1] = trial.getCurrent()["ConstantStimuli"] + JND; 
		// EGOCENTRIC DISTANCE
		absDepth = trial.getCurrent()["AbsDepth"];
#else
		// set the parameters to build the stimulus:
		// HEIGHT
		//--- standard
		stimulus_height[0] = 55.0; 
		//--- comparison
		stimulus_height[1] = trial.getCurrent()["ConstantStimuli"]; 
		// EGOCENTRIC DISTANCE
		absDepth = trial.getCurrent()["AbsDepth"];
#endif
		// build the stimuli		
		buildStandard(stimulus_noise, absDepth);		
		buildComparison(stimulus_height[1], stimulus_noise, absDepth);

#ifndef SIMULATION
		// roll on
		drawGLScene();
		initProjectionScreen(absDepth);

		if(condition == 1)
		{
			// generate random speed between 3500 and 5000
			randSpeed = rand() % 1501 + 3500;
			// move bottom surface up to topY - stimulus_height[first_interval]
			Vector3d moveHeight(0.0,whereTop.y()-stimulus_height[first_interval],absDepth);
			moveObjectAbsolute(moveHeight, whereBottom, randSpeed);
			beepOk(0);
		}
		
		if(condition == 0)
		{
			// show the stimuli
			showStimuli = true;
		}
		timer.start();
#else
		advanceTrial();
#endif

	} else
	{	
		if(condition == 1)
			responseFile.close();

		summaryFile.close();

		cleanup();
		exit(0);
	}
}
Beispiel #8
0
// Questa funzione e' quella che in background fa tutti i conti matematici, quindi qui devi inserire 
// 1) Scrittura su file continua delle coordinate che vuoi salvare
// 2) Estrazione delle coordinate a partire dai corpi rigidi precedentemente definiti vedi ad esempio
// come e' fatto per eyeLeft e eyeRight oppure per thumb ed index
void idle()
{
	optotrak->updateMarkers();
	
	/*cerr << trial.getCurrent()["AbsDepth"] << "\t" << 
		trial.getCurrent()["ObjHeight"] << "\t" <<
		trial.getCurrent()["HapticFB"] << endl;
	*/
	//cerr << parameters.find("fObjHeight",1) << endl;

	markers = optotrak->getAllMarkers();
	// Coordinates picker
	allVisiblePlatform = isVisible(markers[1].p);
	allVisibleIndex = isVisible(markers[13].p) && isVisible(markers[14].p) && isVisible(markers[16].p);
	allVisibleThumb = isVisible(markers[15].p) && isVisible(markers[17].p) && isVisible(markers[18].p);
	allVisibleFingers = allVisibleIndex && allVisibleThumb;

	allVisiblePatch = isVisible(markers[5].p) && isVisible(markers[6].p) && isVisible(markers[7].p);
	allVisibleHead = allVisiblePatch && isVisible(markers[1].p);

	mirrorAlignment = asin(
			abs((markers[6].p.z()-markers[7].p.z()))/
			sqrt(
			pow(markers[6].p.x()-markers[7].p.x(), 2) +
			pow(markers[6].p.z()-markers[7].p.z(), 2)
			)
			)*180/M_PI;

	if ( allVisiblePatch )
		headEyeCoords.update(markers[5].p,markers[6].p,markers[7].p);

	if ( allVisibleFingers )
	{
		indexCoords.update(markers[13].p, markers[14].p, markers[16].p );
		thumbCoords.update(markers[15].p, markers[17].p, markers[18].p );
		fingersOccluded = 0;
	}

	if (fingerCalibrationDone==3 )
	{
		// check for finger occlusion
		if ( !allVisibleFingers )
		{
			fingersOccluded=1;
			num_lost_frames += 1;
		}
		
		// advance frame number
		frameN++;

		// check that we're at the start
		// if so, keep resetting timer
		if(((-500) < index.y()) && (index.y() < (-315)) && ((-500) < thumb.y()) && (thumb.y() < (-315)))
		{
			handAtStart = true;
			timer.start();
		} else // we've moved from the start, begin counting
		{
			handAtStart = false;
		}
		
		// if we're in the reaching area
		if(!handAtStart && ((-315) <= index.y()) && (index.y() < 200) && ((-315) <= thumb.y()) && (thumb.y() < 100))
		{
			started=true; // we've started
		}else{
			started=started;
		}

		// find y_dist and z_dist
		y_dist = (abs(index.y() - (-25)) + abs(thumb.y() - (-25)));
		z_dist = (abs(index.z() - (trial.getCurrent()["AbsDepth"])) + abs(thumb.z() - (trial.getCurrent()["AbsDepth"])));
		within_time_limit = (timer.getElapsedTimeInMilliSec() <= str2num<double>(parameters.find("TimeLimit")));

		if(!reachedObject && (stimPosn==LEFT) && started) {
			x_dist = (abs(index.x() - (-26)) + abs(thumb.x() - (-26)));
			if ( (x_dist <= 25) && (y_dist <= 70) && (z_dist <= 25) && within_time_limit) {
				reachedObject = true;
				TGA_frame = frameN;
			}
		}else if(!reachedObject && (stimPosn==RIGHT) && started) {
			x_dist = (abs(index.x() - (74)) + abs(thumb.x() - (74)));
			if ( (x_dist <= 25) && (y_dist <= 70) && (z_dist <= 25) && within_time_limit) {
				reachedObject = true;
				TGA_frame = frameN;
			}
		}

	}

	if(headCalibration)
	{
	eyeLeft = headEyeCoords.getLeftEye();
	eyeRight = headEyeCoords.getRightEye();
	} else	{
	eyeRight = Vector3d(interoculardistance/2,0,0);
	eyeLeft = -eyeRight;
	}

	index = indexCoords.getP1();
	thumb = thumbCoords.getP1();

	// Write to trialFile
	if (fingerCalibrationDone==3 )
		{

		trialFile << fixed <<
			parameters.find("SubjectName") << "\t" <<		//subjName
			trialNumber << "\t" <<							//trialN
			timer.getElapsedTimeInMilliSec() << "\t" <<		//time
			frameN << "\t" <<								//frameN
			index.transpose() << "\t" <<					//indexXraw, indexYraw, indexZraw
			thumb.transpose() << "\t" <<					//thumbXraw, thumbYraw, thumbZraw
			//eyeRight.transpose() << "\t" <<					//eyeRXraw, eyeRYraw, eyeRZraw
			//eyeLeft.transpose() << "\t" <<					//eyeLXraw, eyeLYraw, eyeLZraw
			fingersOccluded << "\t" <<						//fingersOccluded
			attempt << "\t" <<	
			reachedObject << "\t" <<	
			num_lost_frames
			;

		trialFile << endl;
		
		}

}
Beispiel #9
0
// Funzione di callback per gestire pressioni dei tasti
void handleKeypress(unsigned char key, int x, int y)
{   switch (key)
    {   //Quit program
	case 'x':
		// Facendo cosi si cancella lo stimolo durante il movimento (SINCRONO) del monitor.
		// Si imposta il isStimulusDrawn a FALSE e si riaggiorna la schermata con una drawGLScene()
		// infine si muove il monitor, la chiamata blocca il programma per x secondi, si 
		// simula lo spostamento dello schermo di proiezione ed infine si reimposta isStimulusDrawn a TRUE
		// cosi' la prossima chiamata di drawStimulus() lo disegna correttamente a schermo. Provare per credere...
		//factors = trial.getNext();
	//	trial.next();
		drawGLScene();
//		initProjectionScreen(trial.getCurrent()["AbsDepth"]);
		break;
	case 'i':
		visibleInfo=!visibleInfo;
		break;
	case 'm':
		interoculardistance += 0.5;
	break;
	case 'n':
		interoculardistance -= 0.5;
	break;
	case '+':
	{
		// Il trucco per avanzare alla modalita' trial successiva: incrementi di uno e poi tieni il resto della 
		// divisione per due, in questo caso ad esempio sara' sempre:
		// 0,1,0,1,0,1
		// se metti il resto della divisione per 3 invece la variabile trialMode sar'
		// 0,1,2,0,1,2
		// ogni ciclo della variabile trialMode normalmente e' un trial (1)
		// puoi anche definire una funzione void advanceTrial() che si occupa di andare al trial successivo,
		// deve contenere una chiamata alla BalanceFactor::getNext() cosi' passi alla nuova lista di fattori
		// Ad esempio
		 trialMode++;
		 trialMode=trialMode%4;
	}
	break;
	case 'Q':
	case 'q':
    case 27:	//corrisponde al tasto ESC
    {   
		// Ricorda quando chiami una funzione exit() di chiamare prima cleanup cosi
		// spegni l'Optotrak ed i markers (altrimenti loro restano accesi e li rovini) 
		cleanup();
        exit(0);
    }
    break;
	case 'd':
		{
		fingersShown = !fingersShown;
		}
	break;
    case ' ':
    {
        // Here we record the head shape - coordinates of eyes and markers, but centered in (0,0,0)
        if ( headCalibrationDone==0 && allVisiblePatch )
        {
            headEyeCoords.init(markers[1].p-Vector3d(230,0,0),markers[1].p, markers[5].p,markers[6].p,markers[7].p,interoculardistance );
            headCalibrationDone=1;
			beepOk(0);
            break;
        }
        // Second calibration, you must look a fixed fixation point
        if ( headCalibrationDone==1 && allVisiblePatch )
        {
            headEyeCoords.init( headEyeCoords.getP1(),headEyeCoords.getP2(), markers[5].p, markers[6].p,markers[7].p,interoculardistance );
            headCalibrationDone=2;
            break;
        }
    }
    break;
	case 'f':
	case 'F':
		{
		// Here we record the finger tip physical markers
		if ( allVisiblePlatform && (fingerCalibrationDone==0) )
			{
			//platformFingers=markers[1].p;
			platformIndex=markers[1].p;
			platformThumb=markers[2].p;
			//centercal = markers[4].p;
			fingerCalibrationDone=1;
			beepOk(0);
			break;
			}
		if ( (fingerCalibrationDone==1) && allVisibleFingers )
			{
			indexCoords.init(platformIndex, markers.at(13).p, markers.at(14).p, markers.at(16).p );
			thumbCoords.init(platformThumb, markers.at(15).p, markers.at(17).p, markers.at(18).p );
			fingerCalibrationDone=2;
			beepOk(0);
			break;
			}
		if ( fingerCalibrationDone==2  && allVisibleFingers )
			{
			beepOk(0);
			fingerCalibrationDone=3;
			visibleInfo=!visibleInfo;
			factors = trial.getNext();
			initTrial();
			break;
			}
		}
		break;
    // Enter key: press to make the final calibration
    case 13:
    {
        if ( headCalibrationDone == 2 && allVisiblePatch )
        {
            headEyeCoords.init( headEyeCoords.getP1(),headEyeCoords.getP2(), markers[5].p, markers[6].p,markers[7].p,interoculardistance );
            headCalibrationDone=3;
			visibleInfo=false;
        }
    }
    break;
      case '5':
      {  
		  alignmentY -= .5;
	  }
      break;
      case '8':
      {  
		alignmentY += .5;
      }
      break;
	  case '4':
      {  
		  alignmentX -= .5;
	  }
      break;
      case '6':
      {  
		alignmentX += .5;
      }
	  break;
	  case '1':
      {  
		  stim_translation_z -= 1;
	  }
      break;
      case '3':
      {  
		stim_translation_z += 1;
      }
	  break;
      case 's':
      {  
		  advanceTrial();
	  }
      break;
	  case '0':
	  {
		 training=!training;
	  }
	  break;
	  case 'c':
	  {
		 pulsingColors=!pulsingColors;
	  }
	  break;
	  case 'l':
	  {
		 cout << left_height << "\t" << right_height << endl;
	  }
	  break;
	  case 'v':
	  {
		  stim_vanish_when_reached=!stim_vanish_when_reached;
	  }
	  break;
	  case 'w':
	  {
		 BG_WHITE=(BG_WHITE+1)%2;
	  }
	}
}
void initVariables()
{
	trial.init(parameters);
	interoculardistance = str2num<double>(parameters.find("IOD"));
}
void idle()
{

	updateTheMarkers();

	// Visibility check
	allVisiblePlatform = isVisible(markers[1].p) && isVisible(markers[2].p);
	allVisibleIndex = isVisible(markers[13].p) && isVisible(markers[14].p) && isVisible(markers[16].p);
	allVisibleThumb = isVisible(markers[15].p) && isVisible(markers[17].p) && isVisible(markers[18].p);
	allVisibleFingers = allVisibleIndex && allVisibleThumb;

	allVisibleObject = isVisible(markers[8].p) && isVisible(markers[11].p) && isVisible(markers[12].p);

	allVisiblePatch = isVisible(markers[10].p) && isVisible(markers[11].p) && isVisible(markers[12].p);
	allVisibleHead = allVisiblePatch && isVisible(markers[9].p);

	// mirror alignment check
	mirrorAlignment = asin(
			abs((markers[6].p.z()-markers[7].p.z()))/
			sqrt(
			pow(markers[6].p.x()-markers[7].p.x(), 2) +
			pow(markers[6].p.z()-markers[7].p.z(), 2)
			)
			)*180/M_PI;

	// screen Y alignment check
	screenAlignmentY = asin(
			abs((markers[19].p.y()-markers[21].p.y()))/
			sqrt(
			pow(markers[19].p.x()-markers[21].p.x(), 2) +
			pow(markers[19].p.y()-markers[21].p.y(), 2)
			)
			)*180/M_PI;

	// screen Z alignment check
	screenAlignmentZ = asin(
			abs(markers[19].p.z()-markers[20].p.z())/
			sqrt(
			pow(markers[19].p.x()-markers[20].p.x(), 2) +
			pow(markers[19].p.z()-markers[20].p.z(), 2)
			)
			)*180/M_PI*
			abs(markers[19].p.x()-markers[20].p.x())/
			(markers[19].p.x()-markers[20].p.x());

	// eye coordinates
	eyeRight = Vector3d(interoculardistance/2,0,0);
	eyeLeft = Vector3d(-interoculardistance/2,0,0);

	// fingers coordinates, fingersOccluded and framesOccluded
	if ( allVisibleFingers )
	{
		indexCoords.update(markers[13].p, markers[14].p, markers[16].p );
		thumbCoords.update(markers[15].p, markers[17].p, markers[18].p );
	}

	// Record the calibration platform's position and home position
	if ( isVisible(markers[1].p) && allVisibleObject && fingerCalibrationDone==0 )
	{
		fingerCalibrationDone=1;
		calibration_fingers(fingerCalibrationDone);
	}

	// Record the calibration platform's position and home position
	if ( isVisible(markers[2].p) && allVisibleObject && fingerCalibrationDone==1 )
	{
		fingerCalibrationDone=2;
		calibration_fingers(fingerCalibrationDone);
		beepOk(2);
	}

	if ( allVisibleObject && fingerCalibrationDone==2 )
	{
		upperPin.update(markers[8].p, markers[11].p, markers[12].p );
		lowerPin.update(markers[8].p, markers[11].p, markers[12].p );
	}

	#ifndef SIMULATION
	// index coordinates
	if(allVisibleIndex)
		ind = indexCoords.getP1();

	// thumb coordinates
	if(allVisibleThumb)
		thu = thumbCoords.getP1();
	#endif

	// what the program checks online during the grasp
	if (fingerCalibrationDone==4 )
	{
		// frames counting
		frameN++;

		// fingersOccluded
		if ( allVisibleFingers )
			fingersOccluded = 0;
		else
		{
			fingersOccluded=1;
		}
		
		if(timer.getElapsedTimeInMilliSec() > 1500)
			iGrasped = true;

		if(isHandHome && !iGrasped)
		{
			timer.start();
			frames_at_start++;
		}

		if(iGrasped)
			frames_post_grasp++;

		// middle point between index and thumb (center of grasp)
		grip_position = (ind + thu)/2;

		// euclidean distance to home
		dist_to_home = sqrt( pow((grip_position.x() - home_position.x()),2) + pow((grip_position.y() - home_position.y()),2) + pow((grip_position.z() - home_position.z()),2) );

		// is the hand at start?
		if( dist_to_home < 50.0 )
			isHandHome = true;
		else
			isHandHome = false;

		// euclidean distance to target
		dist_to_target = sqrt( pow((grip_position.x() - 0.0),2) + pow((grip_position.y() - 0.0),2) + pow((grip_position.z() - trial.getCurrent()["AbsDepth"]),2) );

		if(!isHandHome && !allVisibleFingers && !iGrasped)
			framesOccluded++;

		// Write to responseFile
		markersFile << fixed <<
			parameters.find("SubjectName") << "\t" <<
			interoculardistance << "\t" <<
			trialNumber << "\t" <<
			timer.getElapsedTimeInMilliSec() << "\t" <<		//time
			frameN << "\t" <<								//frameN
			ind.transpose() << "\t" <<					//indexXraw, indexYraw, indexZraw
			thu.transpose() << "\t" <<					//thumbXraw, thumbYraw, thumbZraw
			eyeRight.transpose() << "\t" <<					//eyeRXraw, eyeRYraw, eyeRZraw
			eyeLeft.transpose() << "\t" <<					//eyeLXraw, eyeLYraw, eyeLZraw
			fingersOccluded	<< "\t" <<						//fingersOccluded
			framesOccluded	<< "\t" <<						//framesOccluded
			trial.getCurrent()["AbsDepth"]	<< "\t" <<
			trial.getCurrent()["RelDepthObj"] << "\t" <<
			frameToGrasp <<
			endl;
	}
}
// Funzione di callback per gestire pressioni dei tasti
void handleKeypress(unsigned char key, int x, int y)
{   
	switch (key)
	{   
		#ifdef SIMULATION
		case '0':
		{
			good_trial = 1;
			advanceTrial();
		} break;

		case '1':
			allVisibleFingers = !allVisibleFingers;
			break;

		case '2':
		{
			trial.reinsert(trial.getCurrent());
			good_trial = 0;
			advanceTrial();
		} break;

		#endif

		case 'i': // show info
			visibleInfo=!visibleInfo;
			break;

		case 'm': // increase IOD
			interoculardistance += 0.5;
			break;

		case 'n': // decrease IOD
			interoculardistance -= 0.5;
			break;

		case 27: // press escape to quit
		{   
			cleanup(); // clean the optotrak buffer
			exit(0);
		} break;

		// fingers calibration
		case 'f':
		case 'F':
		{
			// Interpolate the fingertip (fourth virtual marker)
			if ( fingerCalibrationDone==2 && allVisibleObject && allVisibleFingers )
			{
				fingerCalibrationDone=3;
				calibration_fingers(fingerCalibrationDone);
				beepOk(3);
				break;
			}

			// Start the experiment
			if ( fingerCalibrationDone==3  && allVisibleFingers )
			{
				fingerCalibrationDone=4;
				beepOk(0);
				home_position = ind;
				visibleInfo=false;
				drawGLScene(); // this is needed otherwise the next motor command freezes the screen

				// check where the object is
				object_reset_position = markers[3].p.transpose();
				// calculate where the object has to go
				Vector3d object_position(0.0,object_reset_position.y(),-550.0);
				// move the object to position from where it is
				moveObjectAbsolute(object_position, object_reset_position, 5000);

				trial.next();
				initTrial();
			}
		} break;

		case ' ': // confirm that you grasped
		{
			if(allVisibleFingers)
			{
				iGrasped = true;
				isStimulusDrawn = false;
			}
		} break;
	}
}