Compartir a través de


Seguimiento ocular extendido en el motor nativo

El seguimiento ocular extendido es una nueva funcionalidad en HoloLens 2. Es un superconjunto del seguimiento ocular estándar, que solo proporciona datos combinados de mirada ocular. El seguimiento extendido de los ojos también proporciona datos de mirada ocular individuales y permite a las aplicaciones establecer diferentes velocidades de fotogramas para los datos de mirada, como 30, 60 y 90 fps. Otras características como la apertura de los ojos y la vergüencia ocular no son compatibles con HoloLens 2 en este momento.

El SDK de seguimiento ocular extendido permite a las aplicaciones acceder a los datos y características del seguimiento ocular extendido. Se podría usar junto con las API de WinRT o las API de OpenXR.

En este artículo se describen las formas de usar el SDK de seguimiento ocular extendido en el motor nativo (C# o C++/WinRT), junto con las API de WinRT.

Configuración del proyecto

  1. Cree un Holographic DirectX 11 App (Universal Windows) proyecto o Holographic DirectX 11 App (Universal Windows) (C++/WinRT) con Visual Studio 2019 o posterior, o abra el proyecto de Visual Studio holográfico existente.
  2. Importe el SDK de seguimiento ocular extendido en el proyecto.
    1. En el Explorador de soluciones de Visual Studio, haga clic con el botón derecho en el proyecto:> Administrar paquetes NuGet...
    2. Asegúrese de que el origen del paquete de la esquina superior derecha apunta a nuget.org: https://api.nuget.org/v3/index.json
    3. Haga clic en la pestaña Explorador y, a continuación, busque Microsoft.MixedReality.EyeTracking.
    4. Haga clic en el botón Instalar para instalar la versión más reciente del SDK.
      Captura de pantalla del paquete NuGet del SDK de Seguimiento ocular.
  3. Establecer la funcionalidad de entrada de mirada
    1. Haga doble clic en el archivo Package.appxmanifest en Explorador de soluciones.
    2. Haga clic en la pestaña Capacidades y, a continuación, active la entrada de mirada.
  4. Incluya el archivo principal y use el espacio de nombres.
    • Para un proyecto de C#:
    using Microsoft.MixedReality.EyeTracking;
    
    • Para un proyecto de C++/WinRT:
    #include <winrt/Microsoft.MixedReality.EyeTracking.h>
    using namespace winrt::Microsoft::MixedReality::EyeTracking;
    
  5. Consuma las API extendidas del SDK de seguimiento ocular e implemente la lógica.
  6. Compile e implemente en HoloLens.

Introducción a los pasos para obtener los datos de mirada

La obtención de los datos de mirada con los ojos a través de las API del SDK de seguimiento ocular extendido requiere los pasos siguientes:

  1. Obtenga acceso a las características de Seguimiento ocular del usuario.
  2. Observe las conexiones y desconexiones del rastreador de mirada ocular.
  3. Abra el rastreador de mirada ocular y, a continuación, consulte sus funcionalidades.
  4. Lee repetidamente los datos de mirada del rastreador de miradas oculares.
  5. Transfiera datos de mirada a otros SpatialCoordinateSystems.

Obtener acceso a las características de seguimiento ocular

Para poder usar cualquier información relacionada con los ojos, la aplicación debe solicitar primero el consentimiento del usuario.

var status = await Windows.Perception.People.EyesPose.RequestAccessAsync();
bool useGaze = (status == Windows.UI.Input.GazeInputAccessStatus.Allowed);
auto accessStatus = co_await winrt::Windows::Perception::People::EyesPose::RequestAccessAsync();
bool useGaze = (accessStatus.get() == winrt::Windows::UI::Input::GazeInputAccessStatus::Allowed);

Detección de seguimiento de mirada ocular

La detección del rastreador de mirada ocular se realiza mediante el uso de la EyeGazeTrackerWatcher clase . EyeGazeTrackerAdded y EyeGazeTrackerRemoved los eventos se generan respectivamente cuando se detecta o desconecta un rastreador de mirada ocular.

El monitor debe iniciarse explícitamente con el StartAsync() método , que se completa de forma asincrónica cuando los rastreadores que ya están conectados se han señalado a través del EyeGazeTrackerAdded evento .

Cuando se detecta un rastreador de mirada ocular, se pasa una EyeGazeTracker instancia a la aplicación en los parámetros de EyeGazeTrackerAdded evento; de forma recíproca, cuando se desconecta un rastreador, la instancia correspondiente EyeGazeTracker se pasa al evento EyeGazeTrackerRemoved.

EyeGazeTrackerWatcher watcher = new EyeGazeTrackerWatcher();
watcher.EyeGazeTrackerAdded += _watcher_EyeGazeTrackerAdded;
watcher.EyeGazeTrackerRemoved += _watcher_EyeGazeTrackerRemoved;
await watcher.StartAsync();
...

private async void _watcher_EyeGazeTrackerAdded(object sender, EyeGazeTracker e)
{
    // Implementation is in next section
}

private void _watcher_EyeGazeTrackerRemoved(object sender, EyeGazeTracker e)
{
    ...
}
EyeGazeTrackerWatcher watcher;
watcher.EyeGazeTrackerAdded(std::bind(&SampleEyeTrackingNugetClientAppMain::OnEyeGazeTrackerAdded, this, _1, _2));
watcher.EyeGazeTrackerRemoved(std::bind(&SampleEyeTrackingNugetClientAppMain::OnEyeGazeTrackerRemoved, this, _1, _2));
co_await watcher.StartAsync();
...

winrt::Windows::Foundation::IAsyncAction SampleAppMain::OnEyeGazeTrackerAdded(const EyeGazeTrackerWatcher& sender, const EyeGazeTracker& tracker)
{
    // Implementation is in next section
}
void SampleAppMain::OnEyeGazeTrackerRemoved(const EyeGazeTrackerWatcher& sender, const EyeGazeTracker& tracker)
{
    ...
}

Seguimiento de mirada abierta con los ojos

Al recibir una EyeGazeTracker instancia, la aplicación primero debe abrirla llamando al OpenAsync() método . Después, puede consultar las funcionalidades de seguimiento si es necesario. El OpenAsync() método toma un parámetro booleano; esto indica si la aplicación necesita tener acceso a características que no pertenecen al seguimiento ocular estándar, como vectores de mirada ocular individuales o cambiar la velocidad de fotogramas del rastreador.

La mirada combinada es una característica obligatoria compatible con todos los rastreadores de mirada ocular. Otras características, como el acceso a la mirada individual, son opcionales y pueden admitirse o no según el rastreador y su controlador. Para estas características opcionales, la EyeGazeTracker clase expone una propiedad que indica si se admite la característica; por ejemplo, la AreLeftAndRightGazesSupported propiedad , que indica si el dispositivo admite información de mirada ocular individual.

Toda la información espacial expuesta por el rastreador de mirada ocular se publica relacionada con el propio rastreador, que se identifica mediante un identificador de nodo dinámico. El uso de nodeId para obtener un SpatialCoordinateSystem elemento con las API de WinRT podría transformar las coordenadas de los datos de mirada en otro sistema de coordenadas.

private async void _watcher_EyeGazeTrackerAdded(object sender, EyeGazeTracker e)
{
    try
    {
        // Try to open the tracker with access to restricted features
        await e.OpenAsync(true);

        // If it has succeeded, store it for future use
        _tracker = e;

        // Check support for individual eye gaze
        bool supportsIndividualEyeGaze = _tracker.AreLeftAndRightGazesSupported;

        // Get a spatial locator for the tracker, this will be used to transfer the gaze data to other coordinate systems later
        var trackerNodeId = e.TrackerSpaceLocatorNodeId;
        _trackerLocator = Windows.Perception.Spatial.Preview.SpatialGraphInteropPreview.CreateLocatorForNode(trackerNodeId);
    }
    catch (Exception ex)
    {
        // Unable to open the tracker
    }
}
winrt::Windows::Foundation::IAsyncAction SampleEyeTrackingNugetClientAppMain::OnEyeGazeTrackerAdded(const EyeGazeTrackerWatcher&, const EyeGazeTracker& tracker)
{
   auto newTracker = tracker;

   try
   {
        // Try to open the tracker with access to restricted features
        co_await newTracker.OpenAsync(true);

        // If it has succeeded, store it for future use
        m_gazeTracker = newTracker;

        // Check support for individual eye gaze
        const bool supportsIndividualEyeGaze = m_gazeTracker.AreLeftAndRightGazesSupported();

        // Get a spatial locator for the tracker. This will be used to transfer the gaze data to other coordinate systems later
        const auto trackerNodeId = m_gazeTracker.TrackerSpaceLocatorNodeId();
        m_trackerLocator = winrt::Windows::Perception::Spatial::Preview::SpatialGraphInteropPreview::CreateLocatorForNode(trackerNodeId);
   }
   catch (const winrt::hresult_error& e)
   {
       // Unable to open the tracker
   }
}

Establecer la velocidad de fotogramas del rastreador de mirada ocular

La EyeGazeTracker.SupportedTargetFrameRates propiedad devuelve la lista de la velocidad de fotogramas de destino admitida por el rastreador. HoloLens 2 admite 30, 60 y 90fps.

Use el EyeGazeTracker.SetTargetFrameRate() método para establecer la velocidad de fotogramas de destino.

// This returns a list of supported frame rate: 30, 60, 90 fps in order
var supportedFrameRates = _tracker.SupportedTargetFrameRates;

// Sets the tracker at the highest supported frame rate (90 fps)
var newFrameRate = supportedFrameRates[supportedFrameRates.Count - 1];
_tracker.SetTargetFrameRate(newFrameRate);
uint newFramesPerSecond = newFrameRate.FramesPerSecond;
// This returns a list of supported frame rate: 30, 60, 90 fps in order
const auto supportedFrameRates = m_gazeTracker.SupportedTargetFrameRates();

// Sets the tracker at the highest supported frame rate (90 fps)
const auto newFrameRate = supportedFrameRates.GetAt(supportedFrameRates.Size() - 1);
m_gazeTracker.SetTargetFrameRate(newFrameRate);
const uint32_t newFramesPerSecond = newFrameRate.FramesPerSecond();

Lee los datos de mirada del rastreador de miradas oculares.

Un rastreador de mirada ocular publica sus estados periódicamente en un búfer circular. Esto permite a la aplicación leer el estado del rastreador a la vez que pertenece a un intervalo de tiempo pequeño. Permite, por ejemplo, la recuperación del estado más reciente del rastreador o su estado en el momento de algún evento, como un gesto de mano del usuario.

Métodos que recuperan el estado de seguimiento como una EyeGazeTrackerReading instancia de :

  • Los TryGetReadingAtTimestamp() métodos y TryGetReadingAtSystemRelativeTime() devuelven el EyeGazeTrackerReading más cercano al tiempo transcurrido por la aplicación. El rastreador controla la programación de publicación, por lo que la lectura devuelta puede ser ligeramente más antigua o más reciente que el tiempo de solicitud. Las EyeGazeTrackerReading.Timestamp propiedades y EyeGazeTrackerReading.SystemRelativeTime permiten a la aplicación conocer la hora exacta del estado publicado.

  • Los TryGetReadingAfterTimestamp() métodos y TryGetReadingAfterSystemRelativeTime() devuelven el primero EyeGazeTrackerReading con una marca de tiempo estrictamente superior al tiempo pasado como parámetro. Esto permite a una aplicación leer secuencialmente todos los estados publicados por el rastreador. Tenga en cuenta que todos estos métodos consultan el búfer existente y que devuelven inmediatamente. Si no hay ningún estado disponible, devolverá null (es decir, no hará que la aplicación espere a que se publique un estado).

Además de su marca de tiempo, una instancia tiene una EyeGazeTrackerReadingIsCalibrationValid propiedad , que indica si la calibración del rastreador ocular es válida o no.

Por último, los datos de mirada se pueden recuperar mediante un conjunto de métodos como TryGetCombinedEyeGazeInTrackerSpace() o TryGetLeftEyeGazeInTrackerSpace(). Todos estos métodos devuelven un valor booleano que indica que se ha realizado correctamente. Si no se obtienen algunos datos, puede significar que no se admiten los datos (EyeGazeTracker tiene propiedades para detectar este caso) o que el rastreador no pudo obtener los datos (por ejemplo, calibración no válida o ocultación ocular).

Si, por ejemplo, la aplicación quiere mostrar un cursor correspondiente a la mirada combinada, puede consultar el rastreador mediante una marca de tiempo de la predicción del fotograma que se está preparando de la siguiente manera.

var holographicFrame = holographicSpace.CreateNextFrame();
var prediction = holographicFrame.CurrentPrediction;
var predictionTimestamp = prediction.Timestamp;
var reading = _tracker.TryGetReadingAtTimestamp(predictionTimestamp.TargetTime.DateTime);
if (reading != null)
{
    // Vector3 needs the System.Numerics namespace
    if (reading.TryGetCombinedEyeGazeInTrackerSpace(out Vector3 gazeOrigin, out Vector3 gazeDirection))
    {
        // Use gazeOrigin and gazeDirection to display the cursor
    }
}
auto holographicFrame = m_holographicSpace.CreateNextFrame();
auto prediction = holographicFrame.CurrentPrediction();
auto predictionTimestamp = prediction.Timestamp();
const auto reading = m_gazeTracker.TryGetReadingAtTimestamp(predictionTimestamp.TargetTime());
if (reading)
{
    float3 gazeOrigin;
    float3 gazeDirection;
    if (reading.TryGetCombinedEyeGazeInTrackerSpace(gazeOrigin, gazeDirection))
    {
        // Use gazeOrigin and gazeDirection to display the cursor
    }
}

Transformación de datos de mirada en otro spatialCoordinateSystem

Las API de WinRT que devuelven datos espaciales, como una posición, siempre requieren y PerceptionTimestamp .SpatialCoordinateSystem Por ejemplo, para recuperar la mirada combinada de HoloLens 2 mediante la API de WinRT, la API SpatialPointerPose.TryGetAtTimestamp() requiere dos parámetros: y SpatialCoordinateSystem .PerceptionTimestamp Cuando se obtiene acceso a la mirada combinada a través SpatialPointerPose.Eyes.Gazede , su origen y dirección se expresan en el SpatialCoordinateSystem pasado.

Las API extendidas del SDK de seguimiento no necesitan tomar y SpatialCoordinateSystem los datos de mirada siempre se expresan en el sistema de coordenadas del rastreador. Pero puede transformar esos datos de mirada en otro sistema de coordenadas con la posición del rastreador relacionada con el otro sistema de coordenadas.

  • Como se mencionó en la sección anterior denominada "Monitor de mirada abierta", para obtener un SpatialLocator para el rastreador de miradas oculares, llame Windows.Perception.Spatial.Preview.SpatialGraphInteropPreview.CreateLocatorForNode() a con la EyeGazeTracker.TrackerSpaceLocatorNodeId propiedad .

  • Los orígenes de mirada y las direcciones recuperadas a través EyeGazeTrackerReading están relacionados con el rastreador de mirada ocular.

  • SpatialLocator.TryLocateAtTimestamp() devuelve la ubicación 6DoF completa del rastreador de mirada ocular en un determinado PerceptionTimeStamp y relacionado con un determinado SpatialCoordinateSystem, que se podría usar para construir una matriz de transformación Matrix4x4.

  • Use la matriz de transformación Matrix4x4 construida para transferir los orígenes de mirada y las direcciones a otros SpatialCoordinateSystem.

Los siguientes ejemplos de código muestran cómo calcular la posición de un cubo ubicado en la dirección de la mirada combinada, dos metros delante del origen de la mirada;

var predictionTimestamp = prediction.Timestamp;
var stationaryCS = stationaryReferenceFrame.CoordinateSystem;
var trackerLocation = _trackerLocator.TryLocateAtTimestamp(predictionTimestamp, stationaryCS);
if (trackerLocation != null)
{
    var trackerToStationaryMatrix = Matrix4x4.CreateFromQuaternion(trackerLocation.Orientation) * Matrix4x4.CreateTranslation(trackerLocation.Position);
    var reading = _tracker.TryGetReadingAtTimestamp(predictionTimestamp.TargetTime.DateTime);
    if (reading != null)
    {
        if (reading.TryGetCombinedEyeGazeInTrackerSpace(out Vector3 gazeOriginInTrackerSpace, out Vector3 gazeDirectionInTrackerSpace))
        {
            var cubePositionInTrackerSpace = gazeOriginInTrackerSpace + 2.0f * gazeDirectionInTrackerSpace;
            var cubePositionInStationaryCS = Vector3.Transform(cubePositionInTrackerSpace, trackerToStationaryMatrix);
        }
    }
}
auto predictionTimestamp = prediction.Timestamp();
auto stationaryCS = m_stationaryReferenceFrame.CoordinateSystem();
auto trackerLocation = m_trackerLocator.TryLocateAtTimestamp(predictionTimestamp, stationaryCS);
if (trackerLocation) 
{
    auto trackerOrientation = trackerLocation.Orientation();
    auto trackerPosition = trackerLocation.Position();
    auto trackerToStationaryMatrix = DirectX::XMMatrixRotationQuaternion(DirectX::XMLoadFloat4(reinterpret_cast<const DirectX::XMFLOAT4*>(&trackerOrientation))) * DirectX::XMMatrixTranslationFromVector(DirectX::XMLoadFloat3(&trackerPosition));

    const auto reading = m_gazeTracker.TryGetReadingAtTimestamp(predictionTimestamp.TargetTime());
    if (reading)
    {
        float3 gazeOriginInTrackerSpace;
        float3 gazeDirectionInTrackerSpace;
        if (reading.TryGetCombinedEyeGazeInTrackerSpace(gazeOriginInTrackerSpace, gazeDirectionInTrackerSpace))
        {
            auto cubePositionInTrackerSpace = gazeOriginInTrackerSpace + 2.0f * gazeDirectionInTrackerSpace;
            float3 cubePositionInStationaryCS;
            DirectX::XMStoreFloat3(&cubePositionInStationaryCS, DirectX::XMVector3TransformCoord(DirectX::XMLoadFloat3(&cubePositionInTrackerSpace), trackerToStationaryMatrix));
        }
    }
}

Referencia de API del SDK de seguimiento ocular extendido

namespace Microsoft.MixedReality.EyeTracking
{
    /// <summary>
    /// Allow discovery of Eye Gaze Trackers connected to the system
    /// This is the only class from Extended Eye Tracking SDK that the application will instantiate, 
    /// other classes' instances will be returned by method calls or properties.
    /// </summary>
    public class EyeGazeTrackerWatcher
    {
        /// <summary>
        /// Constructs an instance of the watcher
        /// </summary>
        public EyeGazeTrackerWatcher();

        /// <summary>
        /// Starts trackers enumeration.
        /// </summary>
        /// <returns>Task representing async action; completes when the initial enumeration is completed</returns>
        public System.Threading.Tasks.Task StartAsync();

        /// <summary>
        /// Stop listening to trackers additions and removal
        /// </summary>
        public void Stop();

        /// <summary>
        /// Raised when an Eye Gaze tracker is connected
        /// </summary>
        public event System.EventHandler<EyeGazeTracker> EyeGazeTrackerAdded;

        /// <summary>
        /// Raised when an Eye Gaze tracker is disconnected
        /// </summary>
        public event System.EventHandler<EyeGazeTracker> EyeGazeTrackerRemoved;        
    }

    /// <summary>
    /// Represents an Eye Tracker device
    /// </summary>
    public class EyeGazeTracker
    {
        /// <summary>
        /// True if Restricted mode is supported, which means the driver supports to provide individual 
        /// eye gaze vector and framerate 
        /// </summary>
        public bool IsRestrictedModeSupported;

        /// <summary>
        /// True if Vergence Distance is supported by tracker
        /// </summary>
        public bool IsVergenceDistanceSupported;

        /// <summary>
        /// True if Eye Openness is supported by the driver
        /// </summary>
        public bool IsEyeOpennessSupported;

        /// <summary>
        /// True if individual gazes are supported
        /// </summary>
        public bool AreLeftAndRightGazesSupported;

        /// <summary>
        /// Get the supported target frame rates of the tracker
        /// </summary>
        public System.Collections.Generic.IReadOnlyList<EyeGazeTrackerFrameRate> SupportedTargetFrameRates;

        /// <summary>
        /// NodeId of the tracker, used to retrieve a SpatialLocator or SpatialGraphNode to locate the tracker in the scene
        /// for Perception API, use SpatialGraphInteropPreview.CreateLocatorForNode
        /// for Mixed Reality OpenXR API, use SpatialGraphNode.FromDynamicNodeId
        /// </summary>
        public Guid TrackerSpaceLocatorNodeId;

        /// <summary>
        /// Opens the tracker
        /// </summary>
        /// <param name="restrictedMode">True if restricted mode active</param>
        /// <returns>Task representing async action; completes when the initial enumeration is completed</returns>
        public System.Threading.Tasks.Task OpenAsync(bool restrictedMode);

        /// <summary>
        /// Closes the tracker
        /// </summary>
        public void Close();

        /// <summary>
        /// Changes the target frame rate of the tracker
        /// </summary>
        /// <param name="newFrameRate">Target frame rate</param>
        public void SetTargetFrameRate(EyeGazeTrackerFrameRate newFrameRate);

        /// <summary>
        /// Try to get tracker state at a given timestamp
        /// </summary>
        /// <param name="timestamp">timestamp</param>
        /// <returns>State if available, null otherwise</returns>
        public EyeGazeTrackerReading TryGetReadingAtTimestamp(DateTime timestamp);

        /// <summary>
        /// Try to get tracker state at a system relative time
        /// </summary>
        /// <param name="time">time</param>
        /// <returns>State if available, null otherwise</returns>
        public EyeGazeTrackerReading TryGetReadingAtSystemRelativeTime(TimeSpan time);

        /// <summary>
        /// Try to get first first tracker state after a given timestamp
        /// </summary>
        /// <param name="timestamp">timestamp</param>
        /// <returns>State if available, null otherwise</returns>
        public EyeGazeTrackerReading TryGetReadingAfterTimestamp(DateTime timestamp);

        /// <summary>
        /// Try to get the first tracker state after a system relative time
        /// </summary>
        /// <param name="time">time</param>
        /// <returns>State if available, null otherwise</returns>
        public EyeGazeTrackerReading TryGetReadingAfterSystemRelativeTime(TimeSpan time);
    }

    /// <summary>
    /// Represents a Frame Rate supported by an Eye Tracker
    /// </summary>
    public class EyeGazeTrackerFrameRate
    {
        /// <summary>
        /// Frames per second of the frame rate
        /// </summary>
        public UInt32 FramesPerSecond;
    }

    /// <summary>
    /// Snapshot of Gaze Tracker state
    /// </summary>
    public class EyeGazeTrackerReading
    {
        /// <summary>
        /// Timestamp of state
        /// </summary>
        public DateTime Timestamp;

        /// <summary>
        /// Timestamp of state as system relative time
        /// Its SystemRelativeTime.Ticks could provide the QPC time to locate tracker pose 
        /// </summary>
        public TimeSpan SystemRelativeTime;

        /// <summary>
        /// Indicates user calibration is valid
        /// </summary>
        public bool IsCalibrationValid;

        /// <summary>
        /// Tries to get a vector representing the combined gaze related to the tracker's node
        /// </summary>
        /// <param name="origin">Origin of the gaze vector</param>
        /// <param name="direction">Direction of the gaze vector</param>
        /// <returns></returns>
        public bool TryGetCombinedEyeGazeInTrackerSpace(out System.Numerics.Vector3 origin, out System.Numerics.Vector3 direction);

        /// <summary>
        /// Tries to get a vector representing the left eye gaze related to the tracker's node
        /// </summary>
        /// <param name="origin">Origin of the gaze vector</param>
        /// <param name="direction">Direction of the gaze vector</param>
        /// <returns></returns>
        public bool TryGetLeftEyeGazeInTrackerSpace(out System.Numerics.Vector3 origin, out System.Numerics.Vector3 direction);

        /// <summary>
        /// Tries to get a vector representing the right eye gaze related to the tracker's node position
        /// </summary>
        /// <param name="origin">Origin of the gaze vector</param>
        /// <param name="direction">Direction of the gaze vector</param>
        /// <returns></returns>
        public bool TryGetRightEyeGazeInTrackerSpace(out System.Numerics.Vector3 origin, out System.Numerics.Vector3 direction);

        /// <summary>
        /// Tries to read vergence distance
        /// </summary>
        /// <param name="value">Vergence distance if available</param>
        /// <returns>bool if value is valid</returns>
        public bool TryGetVergenceDistance(out float value);

        /// <summary>
        /// Tries to get left Eye openness information
        /// </summary>
        /// <param name="value">Eye Openness if valid</param>
        /// <returns>bool if value is valid</returns>
        public bool TryGetLeftEyeOpenness(out float value);

        /// <summary>
        /// Tries to get right Eye openness information
        /// </summary>
        /// <param name="value">Eye Openness if valid</param>
        /// <returns>bool if value is valid</returns>
        public bool TryGetRightEyeOpenness(out float value);
    }
}

Consulte también