Пример #1
0
        /// <summary>
        /// Handle new eye tracking data by logging it
        /// Note: We should be in the main Unity thread when receiving the event from the data provider, however logging should also work outside the main thread
        /// </summary>
        /// <param name="gazeData"></param>
        private void NewDataHandler(GazeData gazeData)
        {
            // Start the resulting data string
            StringBuilder logStringBuilder = new StringBuilder();

            logStringBuilder.Append(gazeData.EyeDataTimestamp.ToString(ci));
            logStringBuilder.Append(",");
            // Note: Highest accuracy for the EyeDataRelativeTimestamp is 100ns so we don't loose information by outputting a fixed number of decimal places
            logStringBuilder.Append(gazeData.EyeDataRelativeTimestamp.ToString("F4", ci));
            logStringBuilder.Append(",");
            logStringBuilder.Append(gazeData.FrameTimestamp.ToString(ci));
            logStringBuilder.Append(",");
            logStringBuilder.Append(gazeData.IsCalibrationValid.ToString(ci));
            logStringBuilder.Append(",");
            logStringBuilder.Append(gazeData.GazeHasValue.ToString(ci));
            logStringBuilder.Append(",");

            // If we have valid gaze data process it
            if (gazeData.GazeHasValue)
            {
                // Append the info about the gaze to our log
                logStringBuilder.Append(gazeData.GazeOrigin.x.ToString("F5", ci));
                logStringBuilder.Append(",");
                logStringBuilder.Append(gazeData.GazeOrigin.y.ToString("F5", ci));
                logStringBuilder.Append(",");
                logStringBuilder.Append(gazeData.GazeOrigin.z.ToString("F5", ci));
                logStringBuilder.Append(",");
                logStringBuilder.Append(gazeData.GazeDirection.x.ToString("F5", ci));
                logStringBuilder.Append(",");
                logStringBuilder.Append(gazeData.GazeDirection.y.ToString("F5", ci));
                logStringBuilder.Append(",");
                logStringBuilder.Append(gazeData.GazeDirection.z.ToString("F5", ci));
                logStringBuilder.Append(",");

                // Did we hit any GameObject?
                logStringBuilder.Append(gazeData.GazePointHit);
                logStringBuilder.Append(",");

                // If we did hit something on the gaze ray, write the hit info to the log, otherwise simply write NA
                if (gazeData.GazePointHit)
                {
                    logStringBuilder.Append(gazeData.GazePoint.x.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePoint.y.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePoint.z.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointName);
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointOnHit.x.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointOnHit.y.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointOnHit.z.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointHitPosition.x.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointHitPosition.y.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointHitPosition.z.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointHitRotation.x.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointHitRotation.y.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointHitRotation.z.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointHitScale.x.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointHitScale.y.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointHitScale.z.ToString("F5", ci));
                    logStringBuilder.Append(",");

                    if (gazeData.GazePointLeftDisplay.HasValue)
                    {
                        logStringBuilder.Append(gazeData.GazePointLeftDisplay.Value.x.ToString("F5", ci));
                        logStringBuilder.Append(",");
                        logStringBuilder.Append(gazeData.GazePointLeftDisplay.Value.y.ToString("F5", ci));
                        logStringBuilder.Append(",");
                        logStringBuilder.Append(gazeData.GazePointLeftDisplay.Value.z.ToString("F5", ci));
                        logStringBuilder.Append(",");
                        logStringBuilder.Append(gazeData.GazePointRightDisplay.Value.x.ToString("F5", ci));
                        logStringBuilder.Append(",");
                        logStringBuilder.Append(gazeData.GazePointRightDisplay.Value.y.ToString("F5", ci));
                        logStringBuilder.Append(",");
                        logStringBuilder.Append(gazeData.GazePointRightDisplay.Value.z.ToString("F5", ci));
                        logStringBuilder.Append(",");
                    }
                    else
                    {
                        logStringBuilder.Append("NA,NA,NA,NA,NA,NA,");
                    }

                    logStringBuilder.Append(gazeData.GazePointMonoDisplay.x.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointMonoDisplay.y.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointMonoDisplay.z.ToString("F5", ci));
                    logStringBuilder.Append(",");

                    logStringBuilder.Append(gazeData.GazePointWebcam.x.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointWebcam.y.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointWebcam.z.ToString("F5", ci));
                    logStringBuilder.Append(",");
                }
                else
                {
                    logStringBuilder.Append("NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,");
                    logStringBuilder.Append("NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,");
                }

                // Did we hit an AOI?
                logStringBuilder.Append(gazeData.GazePointAOIHit);
                logStringBuilder.Append(",");

                // If we hit an AOI, write the hit info to the log, otherwise simply write NA
                if (gazeData.GazePointAOIHit)
                {
                    logStringBuilder.Append(gazeData.GazePointAOI.x.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointAOI.y.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointAOI.z.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointAOIName);
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointAOIOnHit.x.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointAOIOnHit.y.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointAOIOnHit.z.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointAOIHitPosition.x.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointAOIHitPosition.y.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointAOIHitPosition.z.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointAOIHitRotation.x.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointAOIHitRotation.y.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointAOIHitRotation.z.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointAOIHitScale.x.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointAOIHitScale.y.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointAOIHitScale.z.ToString("F5", ci));
                    logStringBuilder.Append(",");

                    logStringBuilder.Append(gazeData.GazePointAOIWebcam.x.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointAOIWebcam.y.ToString("F5", ci));
                    logStringBuilder.Append(",");
                    logStringBuilder.Append(gazeData.GazePointAOIWebcam.z.ToString("F5", ci));
                }
                else
                {
                    logStringBuilder.Append("NA,NA,NA,NA,NA,NA,NA,");
                    logStringBuilder.Append("NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA");
                }
            }
            else
            {
                // No gaze data
                logStringBuilder.Append("NA,NA,NA,NA,NA,NA,NA,");
                // No gaze hit
                logStringBuilder.Append("NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,");
                logStringBuilder.Append("NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,");
                // No AOI hit
                logStringBuilder.Append("NA,NA,NA,NA,NA,NA,NA,NA,");
                logStringBuilder.Append("NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA");
            }

            // If we are supposed to log the position of game objects, log them
            // Note: We log the position even when we have no gaze data!
            for (int i = 0; i < gazeData.positionInfos.Length; i++)
            {
                // Make sure the object does have a valid position
                if (!gazeData.positionInfos[i].positionValid)
                {
                    logStringBuilder.Append(",NA,NA,NA,NA,NA,NA,NA,NA,NA");
                    continue;
                }

                logStringBuilder.Append(",");
                logStringBuilder.Append(gazeData.positionInfos[i].xPosition.ToString("F5", ci));
                logStringBuilder.Append(",");
                logStringBuilder.Append(gazeData.positionInfos[i].yPosition.ToString("F5", ci));
                logStringBuilder.Append(",");
                logStringBuilder.Append(gazeData.positionInfos[i].zPosition.ToString("F5", ci));
                logStringBuilder.Append(",");
                logStringBuilder.Append(gazeData.positionInfos[i].xRotation.ToString("F5", ci));
                logStringBuilder.Append(",");
                logStringBuilder.Append(gazeData.positionInfos[i].yRotation.ToString("F5", ci));
                logStringBuilder.Append(",");
                logStringBuilder.Append(gazeData.positionInfos[i].zRotation.ToString("F5", ci));
                logStringBuilder.Append(",");
                logStringBuilder.Append(gazeData.positionInfos[i].xScale.ToString("F5", ci));
                logStringBuilder.Append(",");
                logStringBuilder.Append(gazeData.positionInfos[i].yScale.ToString("F5", ci));
                logStringBuilder.Append(",");
                logStringBuilder.Append(gazeData.positionInfos[i].zScale.ToString("F5", ci));
            }

            // Append the separator for the info to the output string
            logStringBuilder.Append(",");

            // If there is info we should log, log it
            if (infoToLog.Count > 0)
            {
                // Add the missing infos to the string
                while (infoToLog.TryDequeue(out string info))
                {
                    // Append the string
                    logStringBuilder.Append(info);

                    // If there are more strings to append, add a separator between them
                    if (infoToLog.Count > 0)
                    {
                        logStringBuilder.Append(";");
                    }
                }
            }
            // If there is nothing to log simply leave this column empty.
            // This saves space and as we are at the end of the columns it doesn't mess up the other columns

            // Write info to file
            FileHandler.WriteData(logStringBuilder.ToString());
        }
Пример #2
0
        /// <summary>
        /// Asynchronous Coroutine which starts the recording
        /// </summary>
        /// <returns></returns>
        private IEnumerator StartRecordingCoroutine()
        {
            // Start the data log and thereby initialize the file handler for this recording
            FileHandler.StartDataLog(ParticipantName, RecordingName);

            // Wait for the file to be opened
            yield return(new WaitUntil(() => FileHandler.writingData));

            // Create recording info
            // Note: At this point we transfer the game objects of which we want to log the position into the recording info.
            //       This means the list stays static during recording which is important for the data file header
            CurrentRecording = new RecordingInfo
            {
                participantName = ParticipantName,
                recordingName   = RecordingName,
                startTime       = DateTime.Now,
                positionLoggedGameObjectNames = dataProvider.PositionLoggedGameObjectNames
            };

            // Write information file
            JSON.RecordingInfo infoJson   = new JSON.RecordingInfo(CurrentRecording);
            string             infoString = JsonUtility.ToJson(infoJson);

            FileHandler.WriteInformation(infoString, true);

            // Create the header for the data file
            StringBuilder dataFileHeader = new StringBuilder();

            // Append the general information
            dataFileHeader.Append("eyeDataTimestamp,eyeDataRelativeTimestamp,frameTimestamp,isCalibrationValid,");
            dataFileHeader.Append("gazeHasValue,gazeOrigin_x,gazeOrigin_y,gazeOrigin_z,gazeDirection_x,gazeDirection_y,gazeDirection_z,");
            dataFileHeader.Append("gazePointHit,gazePoint_x,gazePoint_y,gazePoint_z,gazePoint_target_name,gazePoint_target_x,gazePoint_target_y,gazePoint_target_z,");
            dataFileHeader.Append("gazePoint_target_pos_x,gazePoint_target_pos_y,gazePoint_target_pos_z,gazePoint_target_rot_x,gazePoint_target_rot_y,gazePoint_target_rot_z,gazePoint_target_scale_x,gazePoint_target_scale_y,gazePoint_target_scale_z,");
            dataFileHeader.Append("gazePointLeftScreen_x,gazePointLeftScreen_y,gazePointLeftScreen_z,gazePointRightScreen_x,gazePointRightScreen_y,gazePointRightScreen_z,gazePointMonoScreen_x,gazePointMonoScreen_y,gazePointMonoScreen_z,");
            dataFileHeader.Append("GazePointWebcam_x,GazePointWebcam_y,GazePointWebcam_z,");
            dataFileHeader.Append("gazePointAOIHit,gazePointAOI_x,gazePointAOI_y,gazePointAOI_z,gazePointAOI_name,gazePointAOI_target_x,gazePointAOI_target_y,gazePointAOI_target_z,");
            dataFileHeader.Append("gazePointAOI_target_pos_x,gazePointAOI_target_pos_y,gazePointAOI_target_pos_z,gazePointAOI_target_rot_x,gazePointAOI_target_rot_y,gazePointAOI_target_rot_z,gazePointAOI_target_scale_x,gazePointAOI_target_scale_y,gazePointAOI_target_scale_z,");
            dataFileHeader.Append("GazePointAOIWebcam_x,GazePointAOIWebcam_y,GazePointAOIWebcam_z");

            // Append the game object information if we want to log game objects
            for (int i = 0; i < CurrentRecording.positionLoggedGameObjectNames.Length; i++)
            {
                // We start with NA as game object name and replace it with the actual name if the game object (still) exists
                string gameObjectName = "NA";
                if (CurrentRecording.positionLoggedGameObjectNames[i] != null)
                {
                    gameObjectName = FileHandler.RemoveAllNonAlphanumeric(CurrentRecording.positionLoggedGameObjectNames[i]);
                }

                dataFileHeader.Append(",GameObject_");
                dataFileHeader.Append(gameObjectName);
                dataFileHeader.Append("_xPos,GameObject_");
                dataFileHeader.Append(gameObjectName);
                dataFileHeader.Append("_yPos,GameObject_");
                dataFileHeader.Append(gameObjectName);
                dataFileHeader.Append("_zPos,GameObject_");
                dataFileHeader.Append(gameObjectName);
                dataFileHeader.Append("_xRot,GameObject_");
                dataFileHeader.Append(gameObjectName);
                dataFileHeader.Append("_yRot,GameObject_");
                dataFileHeader.Append(gameObjectName);
                dataFileHeader.Append("_zRot,GameObject_");
                dataFileHeader.Append(gameObjectName);
                dataFileHeader.Append("_xScale,GameObject_");
                dataFileHeader.Append(gameObjectName);
                dataFileHeader.Append("_yScale,GameObject_");
                dataFileHeader.Append(gameObjectName);
                dataFileHeader.Append("_zScale");
            }

            // Header for the info column
            dataFileHeader.Append(",info");

            // Write the header for the data file
            FileHandler.WriteData(dataFileHeader.ToString());

            // Subscribe to new data event
            dataProvider.NewDataEvent += NewDataHandler;

            Debug.Log("[EyeTracking DataLogger] Started recording");
        }