Saving data in a text file

Hi,
I’m using Unity with HTC Vive Pro Eye headset. I’ve used the script below to save data coming from the eye tracker in a txt file.

using System.Collections;
using System.Runtime.InteropServices;
using UnityEngine;
using System;
using System.IO;
using ViveSR.anipal.Eye;
using ViveSR.anipal;
using ViveSR;

public class ProvaTxt : MonoBehaviour
{
    public static string UserID = "EyeRecording";   
    public static string Path = Directory.GetCurrentDirectory();
    string File_Path = Directory.GetCurrentDirectory() + "\\StandardSaccade_" + UserID + ".txt";
 
    public static int cnt_callback = 0;
    private static long MeasureTime, CurrentTime, MeasureEndTime = 0;
 
    private static float time_stamp;
    private static int frame;

    //  Parameters for eye data.
    private static EyeData_v2 eyeData = new EyeData_v2();
    public EyeParameter eye_parameter = new EyeParameter();
    public GazeRayParameter gaze = new GazeRayParameter();
    private static bool eye_callback_registered = false;

    private const int maxframe_count = 120 * 30;                  // Maximum number of samples for eye tracking (120 Hz * time in seconds).
    private static UInt64 eye_valid_L, eye_valid_R;                 // The bits explaining the validity of eye data.
    private static float openness_L, openness_R;                    // The level of eye openness.
    private static float pupil_diameter_L, pupil_diameter_R;        // Diameter of pupil dilation.
    private static Vector2 pos_sensor_L, pos_sensor_R;              // Positions of pupils.
    private static Vector3 gaze_origin_L, gaze_origin_R;            // Position of gaze origin.
    private static Vector3 gaze_direct_L, gaze_direct_R;            // Direction of gaze ray.
    private static float frown_L, frown_R;                          // The level of user's frown.
    private static float squeeze_L, squeeze_R;                      // The level to show how the eye is closed tightly.
    private static float wide_L, wide_R;                            // The level to show how the eye is open widely.
    private static double gaze_sensitive;                           // The sensitive factor of gaze ray.
    private static float distance_C;                                // Distance from the central point of right and left eyes.
    private static bool distance_valid_C;                           // Validity of combined data of right and left eyes.

    private static int track_imp_cnt = 0;
    private static TrackingImprovement[] track_imp_item;

    // Start is called before the first frame update
    void Start()
    {
        Invoke("SystemCheck", 0.5f);                // System check.
        Invoke("Measurement", 0.5f);                // Start the measurement of ocular movements in a separate callback function.
    }

 
    //  Create a text file and header names of each column to store the measured data of eye movements.
 
    void Data_txt()
    {
        string variable =
        "time(100ns)" + "   " +
        "time_stamp(ms)" + "    " +
        "frame" + " " +
        "eye_valid_L" + "   " +
        "eye_valid_R" + "   " +
        "openness_L" + "    " +
        "openness_R" + "    " +
        "pupil_diameter_L(mm)" + "  " +
        "pupil_diameter_R(mm)" + "  " +
        "pos_sensor_L.x" + "    " +
        "pos_sensor_L.y" + "    " +
        "pos_sensor_R.x" + "    " +
        "pos_sensor_R.y" + "    " +
        "gaze_origin_L.x(mm)" + "   " +
        "gaze_origin_L.y(mm)" + "   " +
        "gaze_origin_L.z(mm)" + "   " +
        "gaze_origin_R.x(mm)" + "   " +
        "gaze_origin_R.y(mm)" + "   " +
        "gaze_origin_R.z(mm)" + "   " +
        "gaze_direct_L.x" + "   " +
        "gaze_direct_L.y" + "   " +
        "gaze_direct_L.z" + "   " +
        "gaze_direct_R.x" + "   " +
        "gaze_direct_R.y" + "   " +
        "gaze_direct_R.z" + "   " +
        "gaze_sensitive" + "    " +
        "frown_L" + "   " +
        "frown_R" + "   " +
        "squeeze_L" + " " +
        "squeeze_R" + " " +
        "wide_L" + "    " +
        "wide_R" + "    " +
        "distance_valid_C" + "  " +
        "distance_C(mm)" + "    " +
        "track_imp_cnt" +
        Environment.NewLine;

        File.AppendAllText("StandardSaccade_" + UserID + ".txt", variable);

    }

    //  Measure eye movements in a callback function that HTC SRanipal provides.
 
    void Measurement()
    {
        EyeParameter eye_parameter = new EyeParameter();
        SRanipal_Eye_API.GetEyeParameter(ref eye_parameter);
        Data_txt();

        if (SRanipal_Eye_Framework.Instance.EnableEyeDataCallback == true && eye_callback_registered == false)
        {
            SRanipal_Eye_v2.WrapperRegisterEyeDataCallback(Marshal.GetFunctionPointerForDelegate((SRanipal_Eye_v2.CallbackBasic)EyeCallback));
            eye_callback_registered = true;
        }

        else if (SRanipal_Eye_Framework.Instance.EnableEyeDataCallback == false && eye_callback_registered == true)
        {
            SRanipal_Eye_v2.WrapperUnRegisterEyeDataCallback(Marshal.GetFunctionPointerForDelegate((SRanipal_Eye_v2.CallbackBasic)EyeCallback));
            eye_callback_registered = false;
        }
    }

    //  Callback function to record the eye movement data.
    //  Note that SRanipal_Eye_v2 does not work in the function below. It only works under UnityEngine.
    //
    // ********************************************************************************************************************
    private static void EyeCallback(ref EyeData_v2 eye_data)
    {
        EyeParameter eye_parameter = new EyeParameter();
        SRanipal_Eye_API.GetEyeParameter(ref eye_parameter);
        eyeData = eye_data;

   
        //  Measure eye movements at the frequency of 120Hz until framecount reaches the maxframe count set.
        // ----------------------------------------------------------------------------------------------------------------
        while (cnt_callback < maxframe_count)
        {
            ViveSR.Error error = SRanipal_Eye_API.GetEyeData_v2(ref eyeData);

            if (error == ViveSR.Error.WORK)
            {
                // --------------------------------------------------------------------------------------------------------
                //  Measure each parameter of eye data that are specified in the guideline of SRanipal SDK.
                // --------------------------------------------------------------------------------------------------------
                MeasureTime = DateTime.Now.Ticks;
                time_stamp = eyeData.timestamp;
                frame = eyeData.frame_sequence;
                eye_valid_L = eyeData.verbose_data.left.eye_data_validata_bit_mask;
                eye_valid_R = eyeData.verbose_data.right.eye_data_validata_bit_mask;
                openness_L = eyeData.verbose_data.left.eye_openness;
                openness_R = eyeData.verbose_data.right.eye_openness;
                pupil_diameter_L = eyeData.verbose_data.left.pupil_diameter_mm;
                pupil_diameter_R = eyeData.verbose_data.right.pupil_diameter_mm;
                pos_sensor_L = eyeData.verbose_data.left.pupil_position_in_sensor_area;
                pos_sensor_R = eyeData.verbose_data.right.pupil_position_in_sensor_area;
                gaze_origin_L = eyeData.verbose_data.left.gaze_origin_mm;
                gaze_origin_R = eyeData.verbose_data.right.gaze_origin_mm;
                gaze_direct_L = eyeData.verbose_data.left.gaze_direction_normalized;
                gaze_direct_R = eyeData.verbose_data.right.gaze_direction_normalized;
                gaze_sensitive = eye_parameter.gaze_ray_parameter.sensitive_factor;
                frown_L = eyeData.expression_data.left.eye_frown;
                frown_R = eyeData.expression_data.right.eye_frown;
                squeeze_L = eyeData.expression_data.left.eye_squeeze;
                squeeze_R = eyeData.expression_data.right.eye_squeeze;
                wide_L = eyeData.expression_data.left.eye_wide;
                wide_R = eyeData.expression_data.right.eye_wide;
                distance_valid_C = eyeData.verbose_data.combined.convergence_distance_validity;
                distance_C = eyeData.verbose_data.combined.convergence_distance_mm;
                track_imp_cnt = eyeData.verbose_data.tracking_improvements.count;
                ////track_imp_item = eyeData.verbose_data.tracking_improvements.items;

                //  Convert the measured data to string data to write in a text file.
                string value =
                    MeasureTime.ToString() + "  " +
                    time_stamp.ToString() + "   " +
                    frame.ToString() + "    " +
                    eye_valid_L.ToString() + "  " +
                    eye_valid_R.ToString() + "  " +
                    openness_L.ToString() + "   " +
                    openness_R.ToString() + "   " +
                    pupil_diameter_L.ToString() + " " +
                    pupil_diameter_R.ToString() + " " +
                    pos_sensor_L.x.ToString() + "   " +
                    pos_sensor_L.y.ToString() + "   " +
                    pos_sensor_R.x.ToString() + "   " +
                    pos_sensor_R.y.ToString() + "   " +
                    gaze_origin_L.x.ToString() + "  " +
                    gaze_origin_L.y.ToString() + "  " +
                    gaze_origin_L.z.ToString() + "  " +
                    gaze_origin_R.x.ToString() + "  " +
                    gaze_origin_R.y.ToString() + "  " +
                    gaze_origin_R.z.ToString() + "  " +
                    gaze_direct_L.x.ToString() + "  " +
                    gaze_direct_L.y.ToString() + "  " +
                    gaze_direct_L.z.ToString() + "  " +
                    gaze_direct_R.x.ToString() + "  " +
                    gaze_direct_R.y.ToString() + "  " +
                    gaze_direct_R.z.ToString() + "  " +
                    gaze_sensitive.ToString() + "   " +
                    frown_L.ToString() + "  " +
                    frown_R.ToString() + "  " +
                    squeeze_L.ToString() + "    " +
                    squeeze_R.ToString() + "    " +
                    wide_L.ToString() + "   " +
                    wide_R.ToString() + "   " +
                    distance_valid_C.ToString() + " " +
                    distance_C.ToString() + "   " +
                    track_imp_cnt.ToString() +
                    //track_imp_item.ToString() +
                    Environment.NewLine;

                File.AppendAllText("StandardSaccade_" + UserID + ".txt", value);

                cnt_callback++;
            }
        }
    }
}

I would like to create the text file and saving data in it after having pressed a button from the keyboard. However I don’t know what and where in the code add to the script to make this.

I’m new to coding in C#, can someone help me solve?

Thank you

Do it in Update(), and use Input.GetKeyDown() to determine when to do so. That being said, if you are new to C# it can be a tall order to learn how Unity functions and serialize data coming from a third party library all on the first day.

3 Likes

Thank you!