Eingaben in den Kopf-und Augenblick in DirectXHead-gaze and eye-gaze input in DirectX

Hinweis

Dieser Artikel bezieht sich auf die älteren WinRT-APIs.This article relates to the legacy WinRT native APIs. Bei neuen nativen App-Projekten wird die Verwendung der openxr-API empfohlen.For new native app projects, we recommend using the OpenXR API.

In Windows Mixed Reality werden die Eingaben für Eye und Head-Blick verwendet, um zu bestimmen, was der Benutzer sieht.In Windows Mixed Reality, eye and head gaze input is used to determine what the user is looking at. Sie können die Daten verwenden, um primäre Eingabe Modelle wie Kopf-und Commitzu steuern und Kontext für verschiedene Interaktions Typen bereitzustellen.You can use the data to drive primary input models like head-gaze and commit, and provide context for different interaction types. Es gibt zwei Arten von Blick Vektoren, die über die API bereitgestellt werden: Kopf-und Augenblick.There are two types of gaze vectors available through the API: head-gaze and eye-gaze. Beide werden als dreidimensionale Ray mit einem Ursprung und einer Richtung bereitgestellt.Both are provided as a three-dimensional ray with an origin and direction. Anwendungen können dann in Ihre Szenen oder in der realen Welt integriert werden und bestimmen, was der Benutzer als Ziel verwendet.Applications can then raycast into their scenes, or the real world, and determine what the user is targeting.

Der Kopf zeilig stellt die Richtung dar, in der die Kopfzeile des Benutzers gezeigt wird.Head-gaze represents the direction that the user's head is pointed in. Stellen Sie sich den Haupt Blick als Position und Vorwärtsrichtung des Geräts selbst vor, wobei die Position als Mittelpunkt zwischen den beiden anzeigen angezeigt wird.Think of head-gaze as the position and forward direction of the device itself, with the position as the center point between the two displays. Der Haupt Blick ist auf allen Geräten mit gemischter Realität verfügbar.Head-gaze is available on all Mixed Reality devices.

Der Augen Blick stellt die Richtung dar, in der die Augen des Benutzers suchen.Eye-gaze represents the direction that the user's eyes are looking towards. Der Ursprung befindet sich zwischen den Augen des Benutzers.The origin is located between the user's eyes. Es ist auf Geräten mit gemischter Realität verfügbar, die ein Augen Verfolgungssystem enthalten.It's available on Mixed Reality devices that include an eye tracking system.

Mit der spatialpointerpose -API ist sowohl der Kopf-als auch der Augenblick-Strahlen zugänglich.Both head and eye-gaze rays are accessible through the SpatialPointerPose API. Nennen Sie spatialpointerpose:: trygetattimestamp , um ein neues spatialpointerpose-Objekt am angegebenen Zeitstempel und Koordinatensystemzu empfangen.Call SpatialPointerPose::TryGetAtTimestamp to receive a new SpatialPointerPose object at the specified timestamp and coordinate system. Diese spatialpointerpose enthält den Ursprung und die Richtung des Haupt Blicks.This SpatialPointerPose contains a head-gaze origin and direction. Sie enthält außerdem einen Blick auf den Ursprung und die Richtung des Augenblicks, wenn die Augen Verfolgung verfügbar ist.It also contains an eye-gaze origin and direction if eye tracking is available.

GeräteunterstützungDevice support

FeatureFeature HoloLens (1. Generation)HoloLens (1st gen) HoloLens 2HoloLens 2 Immersive HeadsetsImmersive headsets
Anvisieren mit dem KopfHead-gaze ✔️✔️ ✔️✔️ ✔️✔️
AugenblickEye-gaze ✔️✔️

Verwenden des Haupt BlicksUsing head-gaze

Um auf den Kopf Blick zuzugreifen, rufen Sie zunächst spatialpointerpose:: trygetattimestamp auf, um ein neues spatialpointerpose-Objekt zu erhalten.To access the head-gaze, start by calling SpatialPointerPose::TryGetAtTimestamp to receive a new SpatialPointerPose object. Übergeben Sie die folgenden Parameter.Pass the following parameters.

  • Ein spatialcoordinatesystem , das das Koordinatensystem darstellt, das für den Head-Blick bestimmt werden soll.A SpatialCoordinateSystem that represents the coordinate system you want for the head-gaze. Dies wird von der CoordinateSystem -Variablen im folgenden Code dargestellt.This is represented by the coordinateSystem variable in the following code. Weitere Informationen finden Sie im Entwicklerhandbuch zu Koordinatensystemen .For more information, visit our coordinate systems developer guide.
  • Ein Zeitstempel , der die genaue Uhrzeit der angeforderten Kopfzeile darstellt.A Timestamp that represents the exact time of the head pose requested. In der Regel verwenden Sie einen Zeitstempel, der der Uhrzeit entspricht, zu der der aktuelle Frame angezeigt wird.Typically, you'll use a timestamp that corresponds to the time when the current frame will be displayed. Sie können diesen vorhergesagten Anzeigezeit Stempel von einem holographicframevorhersage -Objekt erhalten, das über den aktuellen holographicframezugänglich ist.You can get this predicted display timestamp from a HolographicFramePrediction object, which is accessible through the current HolographicFrame. Dieses holographicframevorhersage-Objekt wird durch die Vorhersage Variable im folgenden Code dargestellt.This HolographicFramePrediction object is represented by the prediction variable in the following code.

Sobald Sie über eine gültige spatialpointerpose verfügen, sind die Kopf-und Vorwärtsrichtung als Eigenschaften zugänglich.Once you have a valid SpatialPointerPose, the head position and forward direction are accessible as properties. Der folgende Code zeigt, wie Sie darauf zugreifen können.The following code shows how to access them.

using namespace winrt::Windows::UI::Input::Spatial;
using namespace winrt::Windows::Foundation::Numerics;

SpatialPointerPose pointerPose = SpatialPointerPose::TryGetAtTimestamp(coordinateSystem, prediction.Timestamp());
if (pointerPose)
{
   float3 headPosition = pointerPose.Head().Position();
   float3 headForwardDirection = pointerPose.Head().ForwardDirection();

   // Do something with the head-gaze
}

Verwenden des AugenblicksUsing eye-gaze

Damit Ihre Benutzer die Augenblick Eingaben verwenden können, muss jeder Benutzer bei der erstmaligen Verwendung des Geräts eine Augen nach Verfolgungs Benutzer-Kalibrierung durchlaufen.For your users to use eye-gaze input, each user has to go through an eye tracking user calibration the first time they use the device. Die Eye-Eye-API ähnelt der Kopfzeile.The eye-gaze API is similar to head-gaze. Dabei wird dieselbe spatialpointerpose -API verwendet, die einen Strahl Ursprung und eine Richtung bereitstellt, die Sie für Ihre Szene bereitstellen können.It uses the same SpatialPointerPose API, which provides a ray origin and direction that you can raycast against your scene. Der einzige Unterschied besteht darin, dass Sie die Eye-Überwachung vor der Verwendung explizit aktivieren müssen:The only difference is that you need to explicitly enable eye tracking before using it:

  1. Fordern Sie die Benutzer Berechtigung zum Verwenden der Augen Verfolgung in Ihrer APP an.Request user permission to use eye tracking in your app.
  2. Aktivieren Sie die Funktion "Blick auf Eingaben" in Ihrem Paket Manifest.Enable the "Gaze Input" capability in your package manifest.

Anfordern des Zugriffs auf die Eingabe des AugenblicksRequesting access to eye-gaze input

Wenn Ihre APP gestartet wird, können Sie eyespose:: requestaccessasync aufrufen, um den Zugriff auf die Eye-Nachverfolgung anzufordern.When your app is starting up, call EyesPose::RequestAccessAsync to request access to eye tracking. Das System fordert den Benutzer bei Bedarf auf und gibt " gazeinputaccessstatus:: Allowed " zurück, nachdem der Zugriff gewährt wurde.The system will prompt the user if needed, and return GazeInputAccessStatus::Allowed once access has been granted. Dabei handelt es sich um einen asynchronen-Befehl, der eine gewisse zusätzliche Verwaltung erfordert.This is an asynchronous call, so it requires a bit of extra management. Im folgenden Beispiel wird ein getrennter Std:: Thread aufgerufen, um auf das Ergebnis zu warten, das in einer Element Variablen mit dem Namen m_isEyeTrackingEnabled gespeichert wird.The following example spins up a detached std::thread to wait for the result, which it stores to a member variable called m_isEyeTrackingEnabled.

using namespace winrt::Windows::Perception::People;
using namespace winrt::Windows::UI::Input;

std::thread requestAccessThread([this]()
{
    auto status = EyesPose::RequestAccessAsync().get();

    if (status == GazeInputAccessStatus::Allowed)
        m_isEyeTrackingEnabled = true;
    else
        m_isEyeTrackingEnabled = false;
});

requestAccessThread.detach();

Das Starten eines getrennten Threads ist nur eine Option für die Behandlung von asynchronen Aufrufen.Starting a detached thread is just one option for handling async calls. Sie können auch die neuen co_await Funktionen verwenden, die von C++ unterstützt werden/WinRT.You could also use the new co_await functionality supported by C++/WinRT. Im folgenden finden Sie ein weiteres Beispiel für das Anfordern von Benutzerberechtigungen:Here's another example for asking for user permission:

  • Mit eyespose:: IsSupported () kann die Anwendung das Berechtigungs Dialogfeld nur aufrufen, wenn ein Eye Tracker vorhanden ist.EyesPose::IsSupported() allows the application to trigger the permission dialog only if there's an eye tracker.
  • Gazinput Access Status-m_gazeInputAccessStatus; Dadurch wird verhindert, dass die Berechtigungs Aufforderung immer wieder nach oben und wiederholt wird.GazeInputAccessStatus m_gazeInputAccessStatus; // This is to prevent popping up the permission prompt over and over again.
GazeInputAccessStatus m_gazeInputAccessStatus; // This is to prevent popping up the permission prompt over and over again.

// This will trigger to show the permission prompt to the user.
// Ask for access if there is a corresponding device and registry flag did not disable it.
if (Windows::Perception::People::EyesPose::IsSupported() &&
   (m_gazeInputAccessStatus == GazeInputAccessStatus::Unspecified))
{ 
    Concurrency::create_task(Windows::Perception::People::EyesPose::RequestAccessAsync()).then(
    [this](GazeInputAccessStatus status)
    {
        // GazeInputAccessStatus::{Allowed, DeniedBySystem, DeniedByUser, Unspecified}
            m_gazeInputAccessStatus = status;
        
        // Let's be sure to not ask again.
        if(status == GazeInputAccessStatus::Unspecified)
        {
                m_gazeInputAccessStatus = GazeInputAccessStatus::DeniedBySystem;    
        }
    });
}

Deklarieren der Blick Eingabe FunktionDeclaring the Gaze Input capability

Doppelklicken Sie in Projektmappen-Explorer auf die Datei appxmanifest.Double-click the appxmanifest file in Solution Explorer. Navigieren Sie dann zum Abschnitt " Funktionen ", und überprüfen Sie die Funktion " Blick Eingaben "Then navigate to the Capabilities section and check the Gaze Input capability.

Blick Eingabe Funktion

Dadurch werden dem Paket Abschnitt in der appxmanifest-Datei die folgenden Zeilen hinzugefügt:This adds the following lines to the Package section in the appxmanifest file:

  <Capabilities>
    <DeviceCapability Name="gazeInput" />
  </Capabilities>

Der Augenblick StrahlGetting the eye-gaze ray

Nachdem Sie den Zugriff auf das et erhalten haben, können Sie den Augenblick Strahl jeden Frame abrufen.Once you have received access to ET, you're free to grab the eye-gaze ray every frame. Rufen Sie wie bei der Kopf Zeitangabe die spatialpointerpose durch Aufrufen von spatialpointerpose:: trygetattimestamp mit einem gewünschten Zeitstempel und Koordinatensystem ab.As with head-gaze, get the SpatialPointerPose by calling SpatialPointerPose::TryGetAtTimestamp with a desired timestamp and coordinate system. Spatialpointerpose enthält ein eyespose -Objekt über die Augen Eigenschaft.The SpatialPointerPose contains an EyesPose object through the Eyes property. Dieser Wert ist nur ungleich NULL, wenn die Eye-Nachverfolgung aktiviert ist.This is non-null only if eye tracking is enabled. Von dort aus können Sie überprüfen, ob der Benutzer auf dem Gerät über eine Eye Tracking-Kalibrierung verfügt, indem Sie eyespose:: iscalibrationvalidaufrufen.From there, you can check if the user in the device has an eye tracking calibration by calling EyesPose::IsCalibrationValid. Verwenden Sie als nächstes die Eigenschaft " Blick ", um das spatialray mit der Position und Richtung des Augenblicks zu erhalten.Next, use the Gaze property to get the SpatialRay containing the eye-gaze position and direction. Die Eigenschaft "Blick" kann in manchen Fällen NULL sein. Achten Sie daher darauf, dies zu überprüfen.The Gaze property can sometimes be null, so be sure to check for this. Dies kann vorkommen, wenn ein Benutzer mit einem kalibrierten Benutzer die Augen vorübergehend schließt.This can happen is if a calibrated user temporarily closes their eyes.

Der folgende Code zeigt, wie Sie auf den Augenblick-Strahl zugreifen können.The following code shows how to access the eye-gaze ray.

using namespace winrt::Windows::UI::Input::Spatial;
using namespace winrt::Windows::Foundation::Numerics;

SpatialPointerPose pointerPose = SpatialPointerPose::TryGetAtTimestamp(coordinateSystem, prediction.Timestamp());
if (pointerPose)
{
    if (pointerPose.Eyes() && pointerPose.Eyes().IsCalibrationValid())
    {
        if (pointerPose.Eyes().Gaze())
        {
            auto spatialRay = pointerPose.Eyes().Gaze().Value();
            float3 eyeGazeOrigin = spatialRay.Origin;
            float3 eyeGazeDirection = spatialRay.Direction;
            
            // Do something with the eye-gaze
        }
    }
}

Fallback, wenn die Augen Verfolgung nicht verfügbar istFallback when eye tracking isn't available

Wie in unserer Design Dokumentation für die Augen Verfolgungerwähnt, sollten Designer und Entwickler über Instanzen verfügen, bei denen die Augen Verfolgungs Daten möglicherweise nicht verfügbar sind.As mentioned in our eye tracking design docs, both designers and developers should be aware of instances where eye tracking data may not be available.

Es gibt verschiedene Gründe dafür, dass Daten nicht verfügbar sind:There are various reasons for data being unavailable:

  • Ein Benutzer wird nicht kalibriert.A user not being calibrated
  • Ein Benutzer hat der APP den Zugriff auf seine Überwachungsdaten verweigert.A user has denied the app access to his/her eye tracking data
  • Temporäre Interferenzen, wie z. b. smudges auf dem Halt der hololens oder die Haare, die die Augen des Benutzers bilden.Temporary interferences, such as smudges on the HoloLens visor or hair occluding the user's eyes.

Einige der APIs wurden bereits in diesem Dokument erwähnt. im folgenden finden Sie eine Übersicht darüber, wie Sie erkennen können, dass die Augen Verfolgung als Kurzübersicht verfügbar ist:While some of the APIs have already been mentioned in this document, in the following, we provide a summary of how to detect that eye tracking is available as a quick reference:

Sie können auch überprüfen, ob Ihre Eye-Überwachungsdaten nicht veraltet sind, indem Sie ein Timeout zwischen empfangenen Datenaktualisierungen für die Augen Verfolgung hinzufügen und andernfalls auf den Haupt Blick zurückgreifen, wie unten erläutert.You may also want to check that your eye tracking data isn't stale by adding a timeout between received eye tracking data updates and otherwise fallback to head-gaze as discussed below.
Weitere Informationen finden Sie in unseren Fall Back Entwurfs Überlegungen .Visit our fallback design considerations for more information.


Korrelieren von Blick mit anderen EingabenCorrelating gaze with other inputs

Manchmal stellen Sie möglicherweise fest, dass Sie eine spatialpointerpose benötigen, die einem Ereignis in der Vergangenheit entspricht.Sometimes you may find that you need a SpatialPointerPose that corresponds with an event in the past. Wenn der Benutzer z. b. eine lufttap-Aktion durchführt, möchte Ihre APP möglicherweise wissen, was Sie sich angeschaut haben.For example, if the user does an Air Tap, your app might want to know what they were looking at. Zu diesem Zweck wäre die einfache Verwendung von spatialpointerpose:: trygetattimestamp mit der vorhergesagten Frame Zeit aufgrund der Latenz zwischen der System Eingabe Verarbeitung und der Anzeigezeit ungenau.For this purpose, simply using SpatialPointerPose::TryGetAtTimestamp with the predicted frame time would be inaccurate because of the latency between system input processing and display time. Wenn Sie den Augenblick für das Ziel verwenden, werden die Augen auch vor dem Beenden einer Commit-Aktion weiter bewegt.Also, if using eye-gaze for targeting, our eyes tend to move on even before finishing a commit action. Dabei handelt es sich weniger um ein Problem bei einer einfachen Luft tippen, aber es wird wichtiger, wenn Sie lange Sprachbefehle mit fast-Eye-Bewegungen kombinieren.This is less of an issue for a simple Air Tap, but becomes more critical when combining long voice commands with fast eye movements. Eine Möglichkeit zur Behandlung dieses Szenarios besteht darin, einen zusätzlichen aufzurufenden spatialpointerpose:: trygetattimestampmithilfe eines historischen Zeitstempels zu erstellen, der dem Eingabe Ereignis entspricht.One way to handle this scenario is to make an additional call to SpatialPointerPose::TryGetAtTimestamp, using a historical timestamp that corresponds to the input event.

Bei Eingaben, die den spatialinteraktionmanager weiterleiten, gibt es jedoch eine einfachere Methode.However, for input that routes through the SpatialInteractionManager, there's an easier method. Der spatialinteraktionsourcestate verfügt über eine eigene trygetattimestamp -Funktion.The SpatialInteractionSourceState has its own TryGetAtTimestamp function. Der Aufruf von, der eine perfekt korrelierte spatialpointerpose ohne den "Guess work" bereitstellt.Calling that will provide a perfectly correlated SpatialPointerPose without the guesswork. Weitere Informationen zum Arbeiten mit spatialinteraktionsourcestates finden Sie in den Hand-und Bewegungs Controllern in der DirectX- Dokumentation.For more information on working with SpatialInteractionSourceStates, take a look at the Hands and Motion Controllers in DirectX documentation.


KalibrierungCalibration

Damit die Eye-Nachverfolgung ordnungsgemäß funktioniert, muss jeder Benutzer über eine Eye Tracking-benutzerkalibrierungverfügen.For eye tracking to work accurately, each user is required to go through an eye tracking user calibration. Dies ermöglicht es dem Gerät, das System für eine komfortablere und qualitativ hochwertige Anzeige für den Benutzer anzupassen und gleichzeitig eine genaue Eye-Nachverfolgung sicherzustellen.This allows the device to adjust the system for a more comfortable and higher quality viewing experience for the user and to ensure accurate eye tracking at the same time. Entwickler müssen nichts auf Ihrem Ende durchführen, um die benutzerkalibrierung zu verwalten.Developers don’t need to do anything on their end to manage user calibration. Das System stellt sicher, dass der Benutzer in den folgenden Situationen aufgefordert wird, das Gerät zu kalibrieren:The system will ensure that the user gets prompted to calibrate the device under the following circumstances:

  • Der Benutzer verwendet das Gerät zum ersten Mal.The user is using the device for the first time
  • Der Benutzer hat sich zuvor für den Kalibrierungsprozess entschieden.The user previously opted out of the calibration process
  • Der Kalibrierungsprozess war nicht erfolgreich, als der Benutzer das Gerät zum letzten Mal verwendet hat.The calibration process didn't succeed the last time the user used the device

Entwickler sollten sicherstellen, dass Sie angemessene Unterstützung für Benutzer bereitstellen, in denen die Augen Verfolgungs Daten möglicherweise nicht verfügbar sind.Developers should make sure to provide adequate support for users where eye tracking data may not be available. Erfahren Sie mehr über Überlegungen zu Fall Back-Lösungen bei der Überwachung von hololens 2.Learn more about considerations for fallback solutions at Eye tracking on HoloLens 2.


Siehe auchSee also