// ******************************************************************************************************************** // // Check if the system works properly. // // ******************************************************************************************************************** void SystemCheck() { if (SRanipal_Eye_API.GetEyeData_v2(ref eyeData) == ViveSR.Error.WORK) { Debug.Log("Device is working properly."); } if (SRanipal_Eye_API.GetEyeParameter(ref eye_parameter) == ViveSR.Error.WORK) { Debug.Log("Eye parameters are measured."); } // Check again if the initialisation of eye tracking functions successfully. If not, we stop playing Unity. Error result_eye_init = SRanipal_API.Initial(SRanipal_Eye_v2.ANIPAL_TYPE_EYE_V2, IntPtr.Zero); if (result_eye_init == Error.WORK) { Debug.Log("[SRanipal] Initial Eye v2: " + result_eye_init); } else { Debug.LogError("[SRanipal] Initial Eye v2: " + result_eye_init); if (UnityEditor.EditorApplication.isPlaying) { UnityEditor.EditorApplication.isPlaying = false; // Stops Unity editor. } } }
private static void UpdateEye() { SRanipal_Eye_API.GetEyeData_v2(ref LatestEyeData); if (LatestEyeData.verbose_data.right.GetValidity(SingleEyeDataValidity .SINGLE_EYE_DATA_PUPIL_DIAMETER_VALIDITY)) { CurrentDiameter = LatestEyeData.verbose_data.right.pupil_diameter_mm; UpdateMinMaxDilation(LatestEyeData.verbose_data.right.pupil_diameter_mm); } else if (LatestEyeData.verbose_data.left.GetValidity(SingleEyeDataValidity .SINGLE_EYE_DATA_PUPIL_DIAMETER_VALIDITY)) { CurrentDiameter = LatestEyeData.verbose_data.left.pupil_diameter_mm; UpdateMinMaxDilation(LatestEyeData.verbose_data.left.pupil_diameter_mm); } }
private static bool UpdateData() { if (Time.frameCount == LastUpdateFrame) { return(LastUpdateResult == Error.WORK); } else { LastUpdateFrame = Time.frameCount; } LastUpdateResult = SRanipal_Eye_API.GetEyeData_v2(ref EyeData_); //Debug.Log("[EYE V2] LeftWide = " + EyeData_.verbose_data.left.eye_wide); //Debug.Log("[EYE V2] RightWide = " + EyeData_.verbose_data.right.eye_wide); return(LastUpdateResult == Error.WORK); }
private static void Update() { for (;;) { try { if (SRanipal_Eye_Framework.Status != SRanipal_Eye_Framework.FrameworkStatus.WORKING && SRanipal_Eye_Framework.Status != SRanipal_Eye_Framework.FrameworkStatus.NOT_SUPPORT) { Thread.Sleep(50); continue; } SRanipal_Eye_API.GetEyeData_v2(ref _latestEyeData); var CombinedEyeReverse = Vector3.Scale( _latestEyeData.verbose_data.combined.eye_data.gaze_direction_normalized, new Vector3(-1, 1, 1)); var LeftEyeReverse = Vector3.Scale(_latestEyeData.verbose_data.left.gaze_direction_normalized, new Vector3(-1, 1, 1)); var RightEyeReverse = Vector3.Scale(_latestEyeData.verbose_data.right.gaze_direction_normalized, new Vector3(-1, 1, 1)); if (CombinedEyeReverse != new Vector3(1.0f, -1.0f, -1.0f)) { SRanipalData["EyesX"] = CombinedEyeReverse.x; SRanipalData["EyesY"] = CombinedEyeReverse.y; SRanipalData["LeftEyeX"] = LeftEyeReverse.x; SRanipalData["LeftEyeY"] = LeftEyeReverse.y; SRanipalData["RightEyeX"] = RightEyeReverse.x; SRanipalData["RightEyeY"] = RightEyeReverse.y; } SRanipalData["LeftEyeLid"] = _latestEyeData.verbose_data.left.eye_openness; SRanipalData["RightEyeLid"] = _latestEyeData.verbose_data.right.eye_openness; if (_latestEyeData.verbose_data.right.GetValidity(SingleEyeDataValidity .SINGLE_EYE_DATA_PUPIL_DIAMETER_VALIDITY)) { CurrentDiameter = _latestEyeData.verbose_data.right.pupil_diameter_mm; if (_latestEyeData.verbose_data.right.eye_openness >= 1f) { UpdateMinMaxDilation(_latestEyeData.verbose_data.right.pupil_diameter_mm); } } else if (_latestEyeData.verbose_data.left.GetValidity(SingleEyeDataValidity .SINGLE_EYE_DATA_PUPIL_DIAMETER_VALIDITY)) { CurrentDiameter = _latestEyeData.verbose_data.left.pupil_diameter_mm; if (_latestEyeData.verbose_data.left.eye_openness >= 1f) { UpdateMinMaxDilation(_latestEyeData.verbose_data.left.pupil_diameter_mm); } } var normalizedFloat = CurrentDiameter / MinOpen / (MaxOpen - MinOpen); SRanipalData["EyesDilation"] = Mathf.Clamp(normalizedFloat, 0, 1); SRanipalData["EyesWiden"] = _latestEyeData.expression_data.left.eye_wide > _latestEyeData.expression_data.right.eye_wide ? _latestEyeData.expression_data.left.eye_wide : _latestEyeData.expression_data.right.eye_wide; SRanipalData["LeftEyeWiden"] = _latestEyeData.expression_data.left.eye_wide; SRanipalData["RightEyeWiden"] = _latestEyeData.expression_data.right.eye_wide; SRanipalData["LeftEyeSqueeze"] = _latestEyeData.expression_data.left.eye_squeeze; SRanipalData["RightEyeSqueeze"] = _latestEyeData.expression_data.right.eye_squeeze; SRanipalData["EyesSqueeze"] = _latestEyeData.expression_data.left.eye_squeeze > _latestEyeData.expression_data.right.eye_squeeze ? _latestEyeData.expression_data.left.eye_squeeze : _latestEyeData.expression_data.right.eye_squeeze; } catch (Exception e) { if (!(e.InnerException is ThreadAbortException)) { MelonLogger.LogError("Threading error occured in SRanipalTrack.Update: " + e.Message); } } Thread.Sleep(5); } }
private void Update() { if (SRanipal_Eye_Framework.Status != SRanipal_Eye_Framework.FrameworkStatus.WORKING && SRanipal_Eye_Framework.Status != SRanipal_Eye_Framework.FrameworkStatus.NOT_SUPPORT) { return; } if (NeededToGetData) { 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; } else if (SRanipal_Eye_Framework.Instance.EnableEyeDataCallback == false) { SRanipal_Eye_API.GetEyeData_v2(ref eyeData); } bool isLeftEyeActive = false; bool isRightEyeAcitve = false; if (SRanipal_Eye_Framework.Status == SRanipal_Eye_Framework.FrameworkStatus.WORKING) { isLeftEyeActive = eyeData.no_user; isRightEyeAcitve = eyeData.no_user; } else if (SRanipal_Eye_Framework.Status == SRanipal_Eye_Framework.FrameworkStatus.NOT_SUPPORT) { isLeftEyeActive = true; isRightEyeAcitve = true; } if (isLeftEyeActive || isRightEyeAcitve) { if (eye_callback_registered == true) { SRanipal_Eye_v2.GetEyeWeightings(out EyeWeightings, eyeData); } else { SRanipal_Eye_v2.GetEyeWeightings(out EyeWeightings); } UpdateEyeShapes(EyeWeightings); } else { for (int i = 0; i < (int)EyeShape_v2.Max; ++i) { bool isBlink = ((EyeShape_v2)i == EyeShape_v2.Eye_Left_Blink || (EyeShape_v2)i == EyeShape_v2.Eye_Right_Blink); EyeWeightings[(EyeShape_v2)i] = isBlink ? 1 : 0; } UpdateEyeShapes(EyeWeightings); return; } Vector3 GazeOriginCombinedLocal, GazeDirectionCombinedLocal = Vector3.zero; if (eye_callback_registered == true) { if (SRanipal_Eye_v2.GetGazeRay(GazeIndex.COMBINE, out GazeOriginCombinedLocal, out GazeDirectionCombinedLocal, eyeData)) { } else if (SRanipal_Eye_v2.GetGazeRay(GazeIndex.LEFT, out GazeOriginCombinedLocal, out GazeDirectionCombinedLocal, eyeData)) { } else if (SRanipal_Eye_v2.GetGazeRay(GazeIndex.RIGHT, out GazeOriginCombinedLocal, out GazeDirectionCombinedLocal, eyeData)) { } } else { if (SRanipal_Eye_v2.GetGazeRay(GazeIndex.COMBINE, out GazeOriginCombinedLocal, out GazeDirectionCombinedLocal)) { } else if (SRanipal_Eye_v2.GetGazeRay(GazeIndex.LEFT, out GazeOriginCombinedLocal, out GazeDirectionCombinedLocal)) { } else if (SRanipal_Eye_v2.GetGazeRay(GazeIndex.RIGHT, out GazeOriginCombinedLocal, out GazeDirectionCombinedLocal)) { } } UpdateGazeRay(GazeDirectionCombinedLocal); } }
private void Update() { if (SRanipal_Eye_Framework.Status != SRanipal_Eye_Framework.FrameworkStatus.WORKING && SRanipal_Eye_Framework.Status != SRanipal_Eye_Framework.FrameworkStatus.NOT_SUPPORT) { return; } if (NeededToGetData) { 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; } else if (SRanipal_Eye_Framework.Instance.EnableEyeDataCallback == false) { SRanipal_Eye_API.GetEyeData_v2(ref eyeData); } //Debug.Log("[Eye v2] Openness = " + eyeData.verbose_data.left.eye_openness + ", " + eyeData.verbose_data.right.eye_openness); bool isLeftEyeActive = false; bool isRightEyeAcitve = false; if (SRanipal_Eye_Framework.Status == SRanipal_Eye_Framework.FrameworkStatus.WORKING) { isLeftEyeActive = eyeData.verbose_data.left.GetValidity(SingleEyeDataValidity.SINGLE_EYE_DATA_GAZE_ORIGIN_VALIDITY); isRightEyeAcitve = eyeData.verbose_data.right.GetValidity(SingleEyeDataValidity.SINGLE_EYE_DATA_GAZE_ORIGIN_VALIDITY); } else if (SRanipal_Eye_Framework.Status == SRanipal_Eye_Framework.FrameworkStatus.NOT_SUPPORT) { isLeftEyeActive = true; isRightEyeAcitve = true; } if (isLeftEyeActive || isRightEyeAcitve) { if (eye_callback_registered == true) { SRanipal_Eye_v2.GetEyeWeightings(out EyeWeightings, eyeData); } else { SRanipal_Eye_v2.GetEyeWeightings(out EyeWeightings); } UpdateEyeShapes(EyeWeightings); } else { for (int i = 0; i < (int)EyeShape.Max; ++i) { bool isBlink = ((EyeShape)i == EyeShape.Eye_Left_Blink || (EyeShape)i == EyeShape.Eye_Right_Blink); EyeWeightings[(EyeShape)i] = isBlink ? 1 : 0; } UpdateEyeShapes(EyeWeightings); return; } Vector3 GazeOriginCombinedLocal, GazeDirectionCombinedLocal = Vector3.zero; if (eye_callback_registered == true) { if (SRanipal_Eye_v2.GetGazeRay(GazeIndex.COMBINE, out GazeOriginCombinedLocal, out GazeDirectionCombinedLocal, eyeData)) { } else if (SRanipal_Eye_v2.GetGazeRay(GazeIndex.LEFT, out GazeOriginCombinedLocal, out GazeDirectionCombinedLocal, eyeData)) { } else if (SRanipal_Eye_v2.GetGazeRay(GazeIndex.RIGHT, out GazeOriginCombinedLocal, out GazeDirectionCombinedLocal, eyeData)) { } } else { if (SRanipal_Eye_v2.GetGazeRay(GazeIndex.COMBINE, out GazeOriginCombinedLocal, out GazeDirectionCombinedLocal)) { } else if (SRanipal_Eye_v2.GetGazeRay(GazeIndex.LEFT, out GazeOriginCombinedLocal, out GazeDirectionCombinedLocal)) { } else if (SRanipal_Eye_v2.GetGazeRay(GazeIndex.RIGHT, out GazeOriginCombinedLocal, out GazeDirectionCombinedLocal)) { } } UpdateGazeRay(GazeDirectionCombinedLocal); } }
// ******************************************************************************************************************** // // 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++; } // Break while loop 3 seconds after the saccade tasks are completed. We know the timing at this point by time information. CurrentTime = DateTime.Now.Ticks; MeasureEndTime = GetSaccadeEndTime(); if ((CurrentTime - MeasureEndTime > 3 * 10000000) && MeasureEndTime != 0) { break; } } }