Dela via


Utökad ögonspårning i Unity

Så här kommer du åt GitHub-lagringsplatsen för det utökade ögonspårningsexemplet:

Utökad ögonspårning är en ny funktion i HoloLens 2. Det är en supermängd av standard ögonspårning, som bara ger kombinerade ögonögadata. Utökad ögonspårning ger också individuella ögonblicksdata och gör att program kan ange olika bildfrekvenser för blickdata, till exempel 30, 60 och 90fps. Andra funktioner, till exempel ögonöppning och ögonkantighet, stöds inte av HoloLens 2 just nu.

Extended Eye Tracking SDK gör det möjligt för program att komma åt data och funktioner i utökad ögonspårning. Det kan användas tillsammans med OpenXR-API:er eller äldre WinRT-API:er.

Den här artikeln beskriver hur du kan använda SDK:et för utökad ögonspårning i Unity tillsammans med Mixed Reality OpenXR-plugin-programmet.

Projektkonfiguration

  1. Konfigurera Unity-projektet för HoloLens-utveckling.
    • Välj funktionen Gaze Input (Blickindata)
  2. Importera Mixed Reality OpenXR-plugin-programmet från funktionsverktyget MRTK.
  3. Importera NuGet-paketet Eye Tracking SDK till ditt Unity-projekt.
    1. Ladda ned och installera NuGetForUnity-paketet .
    2. I Unity-redigeraren går du till NuGet->Manage NuGet Packages och söker sedan efter Microsoft.MixedReality.EyeTracking
    3. Klicka på knappen Installera för att importera den senaste versionen av NuGet-paketet.
      Skärmbild av Nuget-paketet för eye tracking-SDK.
  4. Lägg till Unity-hjälpskripten.
    1. Lägg till skriptet ExtendedEyeGazeDataProvider.cshärifrån till ditt Unity-projekt.
    2. Skapa en scen och bifoga sedan skriptet ExtendedEyeGazeDataProvider.cs till valfri GameObject.
  5. Använd funktionerna ExtendedEyeGazeDataProvider.cs i och implementera din logik.
  6. Skapa och distribuera till HoloLens.

Använda funktioner i ExtendedEyeGazeDataProvider

Anteckning

Skriptet ExtendedEyeGazeDataProvider är beroende av vissa API:er från Mixed Reality OpenXR-plugin-programmet för att konvertera koordinaterna för blickdata. Det kan inte fungera om ditt Unity-projekt använder det inaktuella Windows XR-plugin-programmet eller det äldre inbyggda XR i äldre Unity-version. För att få den utökade ögonspårningen att fungera även i dessa scenarier:

  • Om du bara behöver komma åt inställningarna för bildfrekvens är Mixed Reality OpenXR-plugin-programmet inte nödvändigt, och du kan ändra ExtendedEyeGazeDataProvider för att endast behålla den bildfrekvensrelaterade logiken.
  • Om du fortfarande behöver komma åt enskilda ögonögadata måste du använda WinRT-API:er i Unity. Mer information om hur du använder utökad SDK för ögonspårning med WinRT-API:er finns i avsnittet "Se även".

Klassen ExtendedEyeGazeDataProvider omsluter SDK-API:erna för utökad ögonspårning. Den innehåller funktioner för att få blickläsning i unity-världsrymden eller i förhållande till huvudkameran.

Här är kodexempel som du kan använda ExtendedEyeGazeDataProvider för att hämta blickdata.

ExtendedEyeGazeDataProvider extendedEyeGazeDataProvider;
void Update() {
    timestamp = DateTime.Now;

    var leftGazeReadingInWorldSpace = extendedEyeGazeDataProvider.GetWorldSpaceGazeReading(extendedEyeGazeDataProvider.GazeType.Left, timestamp);
    var rightGazeReadingInWorldSpace = extendedEyeGazeDataProvider.GetWorldSpaceGazeReading(extendedEyeGazeDataProvider.GazeType.Right, timestamp);
    var combinedGazeReadingInWorldSpace = extendedEyeGazeDataProvider.GetWorldSpaceGazeReading(extendedEyeGazeDataProvider.GazeType.Combined, timestamp);

    var combinedGazeReadingInCameraSpace = extendedEyeGazeDataProvider.GetCameraSpaceGazeReading(extendedEyeGazeDataProvider.GazeType.Combined, timestamp);
}

När skriptet ExtendedEyeGazeDataProvider körs ställer det in bildfrekvensen för blickdata till det högsta alternativet, vilket för närvarande är 90fps.

API-referens för utökad SDK för ögonspårning

Förutom att använda skriptet ExtendedEyeGazeDataProvider kan du också skapa ett eget skript för att använda SDK-API:erna direkt.

namespace Microsoft.MixedReality.EyeTracking
{
    /// <summary>
    /// Allow discovery of Eye Gaze Trackers connected to the system
    /// This is the only class from the 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 providing individual 
        /// eye gaze vector and frame rate 
        /// </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 the Perception API, use SpatialGraphInteropPreview.CreateLocatorForNode
        /// for the 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 of 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);
    }
}

Se även