void initVariables() { trial.init(parameters); }
/*** 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; } }
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); }
// 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); } }
// 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; } }
// 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; } }