void update(int value) { frameTimer.start(); // Read the experiment from file, if the file is finished exit suddenly if ( inputStream.eof() ) { exit(0); } if ( isReading ) { // This reads a line (frame) in inputStream readline(inputStream, trialNumber, headCalibration, trialMode, pointMatrix ); headEyeCoords.update(pointMatrix.col(0),pointMatrix.col(1),pointMatrix.col(2)); Affine3d active = headEyeCoords.getRigidStart().getFullTransformation(); eulerAngles.init( headEyeCoords.getRigidStart().getFullTransformation().rotation() ); eyeLeft = headEyeCoords.getLeftEye(); eyeRight= headEyeCoords.getRightEye(); //cerr << eyeRight.transpose() << endl; cyclopeanEye = (eyeLeft+eyeRight)/2.0; if ( trialMode == STIMULUSMODE ) stimulusFrames++; if ( trialMode == FIXATIONMODE ) stimulusFrames=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 ); double lineOfSightRightDistanceToFocalPlane = lineOfSightRight.intersection(focalPlane); //double lenghtOnZ = (active*(center-eyeCalibration )+eyeRight).z(); projPointEyeRight = lineOfSightRightDistanceToFocalPlane *(directionOfSight)+ (eyeRight); // 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); projPointEyeRight=secondProjection ; // Compute the translation to move the eye in order to avoid share components Vector3d posAlongLineOfSight = (headEyeCoords.getRigidStart().getFullTransformation().rotation())*(eyeRight -eyeCalibration); // GENERATION OF PASSIVE MODE. // HERE WE MOVE THE SCREEN TO FACE THE OBSERVER's EYE if ( passiveMode ) { initProjectionScreen(0, headEyeCoords.getRigidStart().getFullTransformation()*Translation3d(center)); } else initProjectionScreen(focalDistance, Affine3d::Identity()); if ( trialMode == STIMULUSMODE ) { // IMPORTANT Reset the previous status of transformations objectActiveTransformation[0].setIdentity(); objectActiveTransformation[1].setIdentity(); // PLANE 0 Transformation QUELLO CHE STA SOTTO alpha = atan( eyeRight.x()/abs(projPointEyeRight.z()) ); if ( overallTilt ) { instantPlaneSlant = alphaMultiplier*alpha+toRadians(-factors.at("DeltaSlant")-factors.at("StillPlaneSlant")); AngleAxis<double> aa0( instantPlaneSlant,Vector3d::UnitY()); objectActiveTransformation[0]*=aa0; double planesYOffset = factors.at("PlanesCentersYDistance")*(whichPlaneDrawUp ? 1 : -1); objectActiveTransformation[0].translation() = Vector3d(0,planesYOffset,focalDistance); // PLANE 1 Transformation QUELLO CHE STA SOPRA AngleAxis<double> aa1(-toRadians(factors.at("StillPlaneSlant")),Vector3d::UnitY()); objectActiveTransformation[1]*=aa1; objectActiveTransformation[1].translation() = Vector3d(0,-planesYOffset,focalDistance); } else { instantPlaneSlant = alphaMultiplier*alpha+toRadians(factors.at("DeltaSlant")+factors.at("StillPlaneSlant")); AngleAxis<double> aa0( instantPlaneSlant,Vector3d::UnitY()); objectActiveTransformation[0]*=aa0; double planesYOffset = factors.at("PlanesCentersYDistance")*(whichPlaneDrawUp ? 1 : -1); objectActiveTransformation[0].translation() = Vector3d(0,planesYOffset,focalDistance); // PLANE 1 Transformation QUELLO CHE STA SOPRA AngleAxis<double> aa1(toRadians(factors.at("StillPlaneSlant")),Vector3d::UnitY()); objectActiveTransformation[1]*=aa1; objectActiveTransformation[1].translation() = Vector3d(0,-planesYOffset,focalDistance); } objectPassiveTransformation[0] = ( cam.getModelViewMatrix()*objectActiveTransformation[0] ); objectPassiveTransformation[1] = ( cam.getModelViewMatrix()*objectActiveTransformation[1] ); //cout << toDegrees(instantPlaneSlant) << endl; // **************** COMPUTE THE OPTIC FLOWS ************************** // 1) Project the points to screen by computing their coordinates on focalPlane in passive (quite complicate, see the specific method) // *********** FOR THE MOVING PLANE ************* vector<Vector3d> projPointsMovingPlane = stimDrawer[0].projectStimulusPoints(objectActiveTransformation[0],headEyeCoords.getRigidStart().getFullTransformation(),cam,focalDistance, screen, eyeCalibration,passiveMode,false); // 2) Get the angles formed by stimulus and observer // updating with the latest values Vector3d oldAlphaMoving = flowsAnglesAlphaMoving,oldBetaMoving=flowsAnglesBetaMoving; // alpha is the "pitch" angle, beta is the "yaw" angle // Here me must use the points 4,5,8 of the stimulus flowsAnglesAlphaMoving(0) = ( atan2(projPointsMovingPlane[4].x(), abs(focalDistance) ) ); flowsAnglesAlphaMoving(1) = ( atan2(projPointsMovingPlane[5].x(), abs(focalDistance) ) ); flowsAnglesAlphaMoving(2) = ( atan2(projPointsMovingPlane[8].x(), abs(focalDistance) ) ); flowsAnglesBetaMoving(0) = ( atan2(projPointsMovingPlane[4].y(), abs(focalDistance) ) ); flowsAnglesBetaMoving(1) = ( atan2(projPointsMovingPlane[5].y(), abs(focalDistance) ) ); flowsAnglesBetaMoving(2) = ( atan2(projPointsMovingPlane[8].y(), abs(focalDistance) ) ); // 3) Fill the matrix of derivatives MatrixXd angVelocitiesMoving(6,1); angVelocitiesMoving(0) = flowsAnglesAlphaMoving(0)-oldAlphaMoving(0); angVelocitiesMoving(1) = flowsAnglesBetaMoving(0)-oldBetaMoving(0); angVelocitiesMoving(2) = flowsAnglesAlphaMoving(1)-oldAlphaMoving(1); angVelocitiesMoving(3) = flowsAnglesBetaMoving(1)-oldBetaMoving(1); angVelocitiesMoving(4) = flowsAnglesAlphaMoving(2)-oldAlphaMoving(2); angVelocitiesMoving(5) = flowsAnglesBetaMoving(2)-oldBetaMoving(2); angVelocitiesMoving /= ((double)TIMER_MS/(double)1000); // 4) Fill the coefficient matrix, to solve the linear system MatrixXd coeffMatrixMoving(6,6); coeffMatrixMoving << 1, flowsAnglesAlphaMoving(0), flowsAnglesBetaMoving(0), 0, 0, 0, 0, 0, 0, 1,flowsAnglesAlphaMoving(0),flowsAnglesBetaMoving(0), 1, flowsAnglesAlphaMoving(1), flowsAnglesBetaMoving(1), 0, 0, 0, 0, 0, 0, 1,flowsAnglesAlphaMoving(1),flowsAnglesBetaMoving(1), 1, flowsAnglesAlphaMoving(2), flowsAnglesBetaMoving(2), 0, 0, 0, 0, 0, 0, 1,flowsAnglesAlphaMoving(2),flowsAnglesBetaMoving(2) ; // 5) Solve the linear system by robust fullPivHouseholderQR decomposition (see Eigen for details http://eigen.tuxfamily.org/dox/TutorialLinearAlgebra.html ) MatrixXd velocitiesMoving = coeffMatrixMoving.colPivHouseholderQr().solve(angVelocitiesMoving); // 6) Write the output to file flowsFileMoving flowsFileMoving << fixed << trialNumber << "\t" << //1 stimulusFrames << " " << factors.at("DeltaSlant")<< " " << factors.at("StillPlaneSlant") << " " << overallTilt << " " << projPointsMovingPlane[4].transpose() << " " << projPointsMovingPlane[5].transpose() << " " << projPointsMovingPlane[8].transpose() << " " << angVelocitiesMoving.transpose() << " " << velocitiesMoving.transpose() << endl; // ********************* FLOWS FOR THE STILL PLANE ************** // Here we must repeat the same things for the still plane vector<Vector3d> projPointsStillPlane = stimDrawer[1].projectStimulusPoints(objectActiveTransformation[1],headEyeCoords.getRigidStart().getFullTransformation(),cam,focalDistance, screen, eyeCalibration,passiveMode,false); // 2) Get the angles formed by stimulus and observer // updating with the latest values Vector3d oldAlphaStill = flowsAnglesAlphaStill,oldBetaStill=flowsAnglesBetaStill; // alpha is the "pitch" angle, beta is the "yaw" angle // Here me must use the points 4,5,8 of the stimulus flowsAnglesAlphaStill(0) = ( atan2(projPointsStillPlane[4].x(), abs(focalDistance) ) ); flowsAnglesAlphaStill(1) = ( atan2(projPointsStillPlane[5].x(), abs(focalDistance) ) ); flowsAnglesAlphaStill(2) = ( atan2(projPointsStillPlane[8].x(), abs(focalDistance) ) ); flowsAnglesBetaStill(0) = ( atan2(projPointsStillPlane[4].y(), abs(focalDistance) ) ); flowsAnglesBetaStill(1) = ( atan2(projPointsStillPlane[5].y(), abs(focalDistance) ) ); flowsAnglesBetaStill(2) = ( atan2(projPointsStillPlane[8].y(), abs(focalDistance) ) ); // 3) Fill the matrix of derivatives MatrixXd angVelocitiesStill(6,1); angVelocitiesStill(0) = flowsAnglesAlphaStill(0)-oldAlphaStill(0); angVelocitiesStill(1) = flowsAnglesBetaStill(0)-oldBetaStill(0); angVelocitiesStill(2) = flowsAnglesAlphaStill(1)-oldAlphaStill(1); angVelocitiesStill(3) = flowsAnglesBetaStill(1)-oldBetaStill(1); angVelocitiesStill(4) = flowsAnglesAlphaStill(2)-oldAlphaStill(2); angVelocitiesStill(5) = flowsAnglesBetaStill(2)-oldBetaStill(2); angVelocitiesStill /= ((double)TIMER_MS/(double)1000); // 4) Fill the coefficient matrix, to solve the linear system MatrixXd coeffMatrixStill(6,6); coeffMatrixStill << 1, flowsAnglesAlphaStill(0), flowsAnglesBetaStill(0), 0, 0, 0, 0, 0, 0, 1,flowsAnglesAlphaStill(0),flowsAnglesBetaStill(0), 1, flowsAnglesAlphaStill(1), flowsAnglesBetaStill(1), 0, 0, 0, 0, 0, 0, 1,flowsAnglesAlphaStill(1),flowsAnglesBetaStill(1), 1, flowsAnglesAlphaStill(2), flowsAnglesBetaStill(2), 0, 0, 0, 0, 0, 0, 1,flowsAnglesAlphaStill(2),flowsAnglesBetaStill(2) ; // 5) Solve the linear system by robust fullPivHouseholderQR decomposition (see Eigen for details http://eigen.tuxfamily.org/dox/TutorialLinearAlgebra.html ) MatrixXd velocitiesStill = coeffMatrixStill.colPivHouseholderQr().solve(angVelocitiesStill); // 6) Write the output to file flowsFileStill flowsFileStill << fixed << trialNumber << "\t" << // 1 stimulusFrames << " " << // 2 factors.at("DeltaSlant")<< " " << // 3 factors.at("StillPlaneSlant") << " " << // 4 overallTilt << " " << projPointsStillPlane[4].transpose() << " " << // 5,6,7 projPointsStillPlane[5].transpose() << " " << // 8,9,10 projPointsStillPlane[8].transpose() << " " << // 11,12,13 angVelocitiesStill.transpose() << " " << // 14, 15, 16, 17, 18, 19 velocitiesStill.transpose() << endl; // 20, 21, 22, 23, 24, 25 // **************** END OF OPTIC FLOWS COMPUTATION } /* 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 << "Factors:" << endl; for (map<string,double>::iterator iter=factors.begin(); iter!=factors.end(); ++iter) { outputfile << "\t\t" << iter->first << "= " << iter->second << endl; } */ } if ( trialMode == PROBEMODE ) isReading=false; glutPostRedisplay(); glutTimerFunc(TIMER_MS, update, 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); }
void idle() { // Set the time during which the stimulus is drawn, it depents on the phase (adaption or test) double drawStimTime = 0; if ( block.at("Phase") == 1 ) drawStimTime = str2num<double>(parameters.find("AdaptStimulusDuration")); else drawStimTime = str2num<double>(parameters.find("TestStimulusDuration")); double deltaT = (double)TIMER_MS; optotrak->updateMarkers(deltaT); markers = optotrak->getAllMarkers(); // Coordinates picker allVisiblePlatform = isVisible(markers.at(15).p) && isVisible(markers.at(16).p); allVisibleThumb = isVisible(markers.at(11).p) && isVisible(markers.at(12).p) && isVisible(markers.at(13).p); allVisibleIndex = isVisible(markers.at(7).p) && isVisible(markers.at(8).p) && isVisible(markers.at(9).p); allVisibleFingers = allVisibleThumb && allVisibleIndex; allVisiblePatch = isVisible(markers.at(1).p) && isVisible(markers.at(2).p) && isVisible(markers.at(3).p); allVisibleHead = allVisiblePatch && isVisible(markers.at(17).p) && isVisible(markers.at(18).p); //if ( allVisiblePatch ) headEyeCoords.update(markers.at(1).p,markers.at(2).p,markers.at(3).p,deltaT); // update thumb coordinates thumbCoords.update(markers.at(11).p,markers.at(12).p,markers.at(13).p,deltaT); // update index coordinates indexCoords.update(markers.at(7).p, markers.at(8).p, markers.at(9).p,deltaT); eyeLeft = headEyeCoords.getLeftEye().p; eyeRight = headEyeCoords.getRightEye().p; checkBounds(); indexInside[1]=indexInside[0]; // Controlla i frames occlusi, se il dito di test รจ fuori dalla sfera // ed ha superato una percentuale di tempo maggiore di // TestPercentOccludedFrames rispetto al tempo di presentazione dello // stimolo allora fa un beep if ( headCalibrationDone==3 && fingerCalibrationDone==3 && !indexInside[0] && (int) block.at("Phase")!=1 && isDrawing ) { bool visibleFinger=true; switch ( str2num<int>(parameters.find("TestFinger")) ) { case 0: visibleFinger=isVisible(thumbCoords.getP1().p); break; case 1: visibleFinger=isVisible(indexCoords.getP1().p); break; case 2: visibleFinger=isVisible(thumbCoords.getP1().p) && isVisible(indexCoords.getP1().p); break; } // XXX scommentare per far si che anche il polso venga controllato per missing frames //visibleFinger = visibleFinger && isVisible(markers.at(6).p); if ( !visibleFinger ) { occludedFrames++; if ( str2num<int>(parameters.find("AudioFeedback") ) ) boost::thread invisibleBeep( beepInvisible); } trialOk=true; // mentre disegna lo stimolo } // Qui durante la fase di delay dopo la scomparsa dello stimolo controlla che il numero // di frames occlusi non abbia superato il limite consentito if ( isDrawing==0 && headCalibrationDone==3 && (block.at("Phase")!=1) && !indexInside[0] ) { double percentOccludedFrames = ((double)occludedFrames/(double)drawingTrialFrame )*100.0; trialOk=(percentOccludedFrames < str2num<double>(parameters.find("TestPercentOccludedFrames"))); } // Calcola le coordinate delle dita offsettate durante la fase di adattamento if ( block.at("Phase") == 1 ) { double fingerOffset = adaptOffsets.at(block1TrialNumber) ; switch ( str2num<int>(parameters.find("AdaptFinger")) ) { case 0: //index visualThumb = thumbCoords.getP1().p + Vector3d(0,0,fingerOffset); break; case 1: //thumb visualIndex = indexCoords.getP1().p + Vector3d(0,0,fingerOffset); break; case 2: { visualThumb = thumbCoords.getP1().p + Vector3d(0,0,fingerOffset); visualIndex = indexCoords.getP1().p + Vector3d(0,0,fingerOffset); } break; } drawingTrialFrame=0; occludedFrames=0; } if ( headCalibrationDone==3 && fingerCalibrationDone==3 && trialMode==STIMULUSMODE ) { if ( globalTimer.getElapsedTimeInMilliSec() <= drawStimTime ) { isDrawing=1; delayedTimer.start(); } else { // non disegna nulla if ( delayedTimer.getElapsedTimeInMilliSec() < str2num<int>(parameters.find("DelayTime")) ) isDrawing=0; else { delayedTimer.start(); advanceTrial(); } } } if ( (int) block.at("Phase") != 1 && isDrawing==1 ) { drawingTrialFrame++; } #define WRITE int thisBlockTrialNumber=0; switch ( block.at("Phase") ) { case 0: thisBlockTrialNumber=block0TrialNumber; break; case 1: thisBlockTrialNumber=block1TrialNumber; break; case 2: thisBlockTrialNumber=block2TrialNumber; break; } if ( !isMovingRod ) { RowVector3d junk(9999,9999,9999); // Write to file if ( headCalibrationDone==3 && fingerCalibrationDone==3 ) { if ( totalFrame==0) { markersFile << fixed << setprecision(3) << "SubjectName\tAdaptFinger\tTestFinger\tAdaptOffset\tAdaptHapticFeedback\tFingerDist\tTotalTrial\tPhase\tTrialNumber\tTrialFrame\tdT\tTotTime\tIndexInside\tIsDrawing\tTrialOk\tVisualStimX\tVisualStimY\tVisualStimZ\tHapticRodX\tHapticRodY\tHapticRodZ\tfRelDepth\tfDistances\tDeltaXRods\tEyeLeftXraw\tEyeLeftYraw\tEyeLeftZraw\tEyeRightXraw\tEyeRightYraw\tEyeRightZraw\tWristXraw\tWristYraw\tWristZraw\tThumbXraw\tThumbYraw\tThumbZraw\tIndexXraw\tIndexYraw\tIndexZraw" << endl; totalFrame++; } markersFile << fixed << setprecision(3) << parameters.find("SubjectName") << "\t" << parameters.find("AdaptFinger") << "\t" << parameters.find("TestFinger") << "\t" << adaptOffsets.at(block1TrialNumber) << "\t" << parameters.find("AdaptHapticFeedback") << "\t" << fingerDistance << "\t" << totalTrialNumber << "\t" << block.at("Phase") << "\t" << thisBlockTrialNumber << "\t" << trialFrame << "\t" << deltaT*1000 << "\t" << totalTime.getElapsedTimeInMilliSec() << "\t" << indexInside[0] << "\t" << isDrawing << "\t" << trialOk << "\t" << visualRodCenter.transpose() << "\t" << hapticRodCenter.transpose() << "\t" << ((block.at("Phase")!=1) ? factors.at("RelDepth") : 9999) << "\t" << ((block.at("Phase")!=1) ? factors.at("Distances") : 9999) << "\t" << deltaXRods << "\t" << ( isVisible(eyeLeft) ? eyeLeft.transpose() : junk ) << "\t" << ( isVisible(eyeRight) ? eyeRight.transpose() : junk ) << "\t" << ( isVisible(markers.at(6).p) ? markers.at(6).p.transpose() : junk ) << "\t" << ( isVisible(thumbCoords.getP1().p) ? thumbCoords.getP1().p.transpose() : junk ) << "\t" << ( isVisible(indexCoords.getP1().p) ? indexCoords.getP1().p.transpose() : junk ) << endl; } trialFrame++; } #ifdef SAVEDATADAT eulerAngles.init( headEyeCoords.getRigidStart().getFullTransformation().rotation() ); // Write datafile to real-time streaming of data ofstream outputfile; outputfile.open("data.dat"); outputfile << "Subject Name: " << parameters.find("SubjectName") << endl; outputfile << "AdaptHapticFeedback: " << parameters.find("AdaptHapticFeedback") << endl; outputfile << "AdaptFinger: " << parameters.find("AdaptFinger") << endl; outputfile << "TestFinger: " << parameters.find("TestFinger") << endl; outputfile << "IndexInside: " << indexInside[0] << endl; //outputfile << "Yaw: " << toDegrees(eulerAngles.getYaw()) << endl <<"Pitch: " << toDegrees(eulerAngles.getPitch()) << endl << "Roll: " << toDegrees(eulerAngles.getRoll()) << endl; outputfile << "EyeLeft: " << headEyeCoords.getLeftEye().p.transpose() << endl; outputfile << "EyeRight: " << headEyeCoords.getRightEye().p.transpose() << endl << endl; outputfile << "Thumb: " << thumbCoords.getP1().p.transpose() << endl; outputfile << "Index: " << indexCoords.getP1().p.transpose() << endl; outputfile << "Wrist: " << markers.at(6).p.transpose() << endl; outputfile << "IsDrawing: " << isDrawing << " TrialOk: " << trialOk << " OccludedFrames: " << occludedFrames << " DrawingTrialFrames: " << drawingTrialFrame << endl; outputfile << "HapticRodCenter: " << hapticRodCenter.transpose() << endl; outputfile << "VisualRodCenter: " << visualRodCenter.transpose() << endl; outputfile << "Markers(5): " << markers.at(5).p.transpose() << endl; outputfile << "AdaptOffset: " << adaptOffsets.at(block1TrialNumber) << endl; outputfile << "Phase: " << block.at("Phase") << endl; outputfile << "TrialNumber: " << thisBlockTrialNumber << endl; outputfile << "Total trials: " << totalTrialNumber << endl; #endif frameTimer.start(); }
void update(int value) { // Read the experiment from file, if the file is finished exit suddenly if ( inputStream.eof() ) { cleanup(); exit(0); } if ( isReading ) { // This reads a line (frame) in inputStream readline(inputStream, trialNumber, headCalibration, trialMode, pointMatrix ); headEyeCoords.update(pointMatrix.col(0),pointMatrix.col(1),pointMatrix.col(2)); Affine3d active = headEyeCoords.getRigidStart().getFullTransformation(); eulerAngles.init( headEyeCoords.getRigidStart().getFullTransformation().rotation() ); eyeLeft = headEyeCoords.getLeftEye(); eyeRight= headEyeCoords.getRightEye(); cyclopeanEye = (eyeLeft+eyeRight)/2.0; if ( trialMode == STIMULUSMODE ) stimulusFrames++; if ( trialMode == FIXATIONMODE ) stimulusFrames=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 share components Vector3d posAlongLineOfSight = (headEyeCoords.getRigidStart().getFullTransformation().rotation())*(eyeRight -eyeCalibration); // GENERATION OF PASSIVE MODE. // HERE WE MOVE THE SCREEN TO FACE THE OBSERVER's EYE if ( passiveMode ) { initProjectionScreen(0, headEyeCoords.getRigidStart().getFullTransformation()*Translation3d(center)); } else initProjectionScreen(focalDistance, Affine3d::Identity()); objectPassiveTransformation = ( cam.getModelViewMatrix()*objectActiveTransformation ); 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 << "Factors:" << endl; for (map<string,double>::iterator iter=factors.begin(); iter!=factors.end(); ++iter) { outputfile << "\t\t" << iter->first << "= " << iter->second << endl; } } if ( trialMode == PROBEMODE ) isReading=false; glutPostRedisplay(); glutTimerFunc(TIMER_MS, update, 0); }