Seguimiento de manos: MRTK3

Información general

Los datos procedentes de las articulaciones de las manos son uno de los únicos tipos de datos de entrada que el sistema de entrada de Unity aún no controla de forma nativa, así que nuestros subsistemas son quienes se encargan de controlarlos.

Nota

Si no está familiarizado con los subsistemas MRTK3 y sus diferencias con respecto a los servicios de MRTK 2.x, consulte la documentación de arquitectura de subsistemas de MRTK3 para profundizar en nuestra filosofía y diseño.

Nuestros subsistemas ingieren datos de las articulaciones de manos procedentes de varios orígenes y los agregan a una API central, que funciona en distintos dispositivos y contextos de simulación. Los subsistemas siguientes son implementaciones de HandsSubsystem:

  • El subsistema OpenXRHandsSubsystem recibe datos procedentes de las manos directamente del complemento OpenXR.
  • El subsistema XRSDKHandsSubsystem recibe datos procedentes de manos de la capa de abstracción del SDK de XR de Unity (que, a su vez, puede obtener sus datos de OpenXR o de algún otro origen).
  • El subsistema SyntheticHandsSubsystem sintetiza articulaciones de manos falsas basadas en las acciones de entrada procedentes del sistema (como pueden ser devicePosition, deviceRotation, etc.). Este es el subsistema que proporciona las articulaciones que se ven al usar la simulación de entrada en el editor.

HandsAggregatorSubsystem es un subsistema que combina todos los orígenes de datos de mano en una API central. Extrae datos de articulaciones esqueléticas de todos los que ejecutan HandsSubsystemsactivamente . La implementación de MRTK de es HandsAggregatorSubsystemMRTKHandsAggregatorSubsystem, que admite la carga diferida y la reutilización de datos de mano por fotograma.

Importante

Siempre que se consulte directamente en búsqueda de datos de las articulaciones de manos, siempre es preferible consultar desde el agregador y no desde los subsistemas individuales. De este modo, el código funcionará para cualquier origen de datos procedentes de manos, incluidos los datos simulados.

El agregador y los subsistemas de manos evalúan las solicitudes entrantes de datos procedentes de manos de forma diferida. Es decir, los datos procedentes de manos no se consultarán hasta que un script "cliente" lo solicite. Si la aplicación solo solicita datos de una articulación determinada, los subsistemas de manos evaluarán de forma diferida y se limitarán a consultar una sola articulación en las API subyacentes. Además, si un "cliente" solicita los datos de todas las articulaciones de una mano, todas las llamadas posteriores dentro del mismo marco reutilizarán los mismos datos. Esto reducirá el costo de consultar varias articulaciones dentro del mismo marco. En cada nuevo marco, la memoria caché se llenará y se vaciará, y las llamadas posteriores comenzarán a llenarla de nuevo.

Como resultado, al generar perfiles de la aplicación, podría notar que la primera consulta de datos de articulaciones de un marco tarda más tiempo que las consultas posteriores. Esto se debe al costo amortizado asociado con la primera consulta, así como al rendimiento relativo de los siguientes "aciertos de caché".

Características del gesto de reducir

El agregador calcula varias medidas con respecto al gesto de reducir en función de los datos de las articulaciones que se consultan en cada subsistema de manos específico. Estas medidas se configuran en la configuración del subsistema de agregador.

Configuración del subsistema del agregador de manos

El umbral de inicio del gesto de reducir y el umbral de finalización del gesto de reducir controlan la distancia absoluta del mundo entre el pulgar y el dedo que se use para normalizar el progreso del gesto. Cuando la distancia sea equivalente al umbral de inicio, el valor del progreso de la reducción será de 1.0. A su vez, cuando la distancia equivalga al umbral de finalización, este será de 0.0. (Actualmente, estos umbrales se encuentran en unidades de Unity, pero pronto se normalizarán con el tamaño de la mano del usuario).

El campo de visión de la cámara de elevación de la mano controla cómo de cerca debe estar la mano, en relación con el centro de la vista del usuario, para considerarse que puede realizar el gesto de reducir. La tolerancia de la mano volteada controla la tolerancia con la que se mide la rotación de la mano del usuario, para determinar el momento en el que el usuario está orientando su mano hacia fuera.

Ejemplos de agregador de manos

// Get a reference to the aggregator.
var aggregator = XRSubsystemHelpers.GetFirstRunningSubsystem<HandsAggregatorSubsystem>();
// Wait until an aggregator is available.
IEnumerator EnableWhenSubsystemAvailable()
{
    yield return new WaitUntil(() => XRSubsystemHelpers.GetFirstRunningSubsystem<HandsAggregatorSubsystem>() != null);
    GoAhead();
}
// Get a single joint (Index tip, on left hand, for example)
bool jointIsValid = aggregator.TryGetJoint(TrackedHandJoint.IndexTip, XRNode.LeftHand, out HandJointPose jointPose);
// Get an entire hand's worth of joints from the left hand.
bool allJointsAreValid = aggregator.TryGetEntireHand(XRNode.LeftHand, out IReadOnlyList<HandJointPose> joints)
// Check whether the user's left hand is facing away (commonly used to check "aim" intent)
// This is adjustable with the HandFacingAwayTolerance option in the Aggregator configuration.
// "handIsValid" represents whether there was valid hand data in the first place!
bool handIsValid = aggregator.TryGetPalmFacingAway(XRNode.LeftHand, out bool isLeftPalmFacingAway)
// Query pinch characteristics from the left hand.
// pinchAmount is [0,1], normalized to the open/closed thresholds specified in the Aggregator configuration.
// "isReadyToPinch" is adjusted with the HandRaiseCameraFOV and HandFacingAwayTolerance settings in the configuration.
bool handIsValid = aggregator.TryGetPinchProgress(XRNode.LeftHand, out bool isReadyToPinch, out bool isPinching, out float pinchAmount)

Objetos prefabricados del controlador de mano

Los MRTK LeftHand Controller objetos prefabricados y MRTK RightHand Controller permiten usar controladores de mano en el proyecto. Estos objetos prefabricados pueden funcionar con controladores de mano articulados y no articulados. Tienen interactores para hacer poke, agarrar, ray lejos y hacer pinchar la mirada. Además, estos objetos prefabricados muestran los objetos visuales adecuados y controlan las acciones de entrada del dispositivo mediante componentes de controlador e interactor conectados a ellos. A su vez, estos componentes consumen las asignaciones de acciones de entrada de Unity, que declaran enlaces de entrada. Los objetos prefabricados, de forma predeterminada, usan las asignaciones de acciones de entrada definidas en el recurso incluido MRTK Default Input Actions .

Tenga en cuenta que los objetos prefabricados del controlador de mano ya están incluidos en el MRTK XR Rig objeto prefabricado, consulte creación de una nueva escena para obtener más detalles. Si ya se está usando la plataforma XR de MRTK3, no es necesario realizar ninguna otra acción para admitir controladores de mano.

Jerarquía del objeto prefabricado mrTK LeftHand Controller Unity.

Importante

Si las acciones de entrada en la plataforma XR de MRTK3 se modifican y usan acciones definidas fuera del recurso, asegúrese de actualizar el administrador de acciones de entrada de MRTK Default Input Actions MRT3 para que apunte al nuevo recurso de acción de entrada. No hacerlo puede dar lugar a un comportamiento indefinido.

Los objetos prefabricados de controlador de mano izquierda y derecha de MRTK3 contienen todos los componentes necesarios para admitir la entrada manual. Uno de estos componentes es el de ArticulatedHandControllerMRTK, que es una versión especializada de la entrada ActionBasedControllerXR de Unity. Este script de controlador MRTK3 usa el subsistema del agregador de manos de MRTK3 para exponer varios eventos de entrada de mano. Por ejemplo, el controlador expone el evento de selección de pellizcar.

Los objetos prefabricados de mano también tienen scripts para habilitar la visualización del controlador de mano. El HandJointVisualizer componente está diseñado para la depuración y dibuja una malla con instancias en cada articulación de mano. Aunque el ControllerVisualizer componente está pensado para escenarios de producción y, cuando se detecta un controlador, representa el modelo de controlador correspondiente. La malla del controlador de la plataforma se usa cuando está disponible; de lo contrario, se usa un modelo de controlador genérico, el especificado en el fallbackControllerModel campo .

Las plataformas que no son HoloLens pueden usar RiggedHandMeshVisualizer para visualizar la mano. Como se indica con el nombre, este visualizador usa una malla irregular para representar modelos de mano de alta calidad y no se recomienda para plataformas de AR como HoloLens, tanto por motivos de rendimiento como de diseño. Tenga en cuenta que este visualizador no está configurado en los objetos prefabricados predeterminados del controlador de mano.

Nota

En el caso de plataformas de realidad aumentada como HoloLens, se recomienda no usar ninguna visualización manual. El conflicto entre la mano real del usuario y la visualización holográfica ligeramente retrasada puede ser más distraída de lo que vale la pena. Sin embargo, para plataformas opacas, esta es una excelente solución.

Los objetos prefabricados predeterminados del controlador de mano también hospedan un conjunto de componentes de interactor. Entre estos se incluyen los eventos PokeInteractor, MRTKRayInteractor, GrabInteractor y GrabInteractor. Para obtener más información sobre estos interactores, visite Interactor Architecture — MRTK3.

Por último, los objetos prefabricados del controlador también contienen componentes de detector, IInteractionModeDetector, NearInteractionModeDetector y InteractionDetector. Estos componentes informan al administrador del modo de interacción de la aplicación de qué interactores deben habilitarse. Para obtener más información sobre los detectores de MRTK3, visite Interaction Mode Manager — MRTK3.

Posar orígenes

Todos los interactores de mano de MRTK3 requieren una posición de controlador (o posición de mano). El tipo de posición de mano puede variar de interactor a interactor. Por ejemplo, algunos usan acciones de entrada de Unity para obtener la posición y la rotación, mientras que otras usan la posición del dedo índice, amd algunos usan la posición de la palma. El origen de posición de la mano de cada interactor se define mediante una clase que implementa la interfaz de IPoseSource MRTK3. Esta interfaz declara lo siguiente:

  • TryGetPose. Este método intenta conseguir una posición de mano en el espacio mundial. Por ejemplo, la posición devuelta puede corresponder a una posición de articulación de mano obtenida del subsistema del agregador de manos de MRTK3. Este método devuelve un valor devuelto si la recuperación de la posición se realizó correctamente. Algunas implementaciones de este método, como recuperar la posición de los datos de la articulación manual, pueden producir un error si los datos no están disponibles.

El tipo de un interactor se especifica a través del IPoseSource inspector de Unity y puede ser uno de los siguientes tipos:

  • FallbackCompositePoseSource. Origen de posición compuesto a partir de una lista ordenada de orígenes de posición. Devuelve el resultado del primer origen de posición que devuelve correctamente una posición.
  • HandBasedPoseSource. Una clase abstracta que ayuda a definir un origen de posición basado en una entrega específica con acceso al subsistema de agregador de manos de MRTK3.
  • HandJointPoseSource. Una fuente de posado que extiende HandBasedPoseSource y realiza un seguimiento de una articulación de mano específica sobre una mano específica.
  • InputActionPoseSource. Origen de posición que obtiene una posición compuesta de una posición con seguimiento y rotación de las acciones de entrada de Unity especificadas. Las acciones de entrada predeterminadas se pueden encontrar en el MRTK Default Input Actions recurso de Unity.
  • PinchPoseSource. Fuente de posición que extiende HandBasedPoseSource y obtiene la posición de pellizca de una mano específica del subsistema de agregador de manos de MRTK3.
  • PolyfillHandRayPoseSource. Fuente de posición que extiende HandBasedPoseSource y representa un rayo de mano. Este rayo de mano se construye derivando de las posiciones de palma y nuckle del subsistema de agregador de manos de MRTK3.

Los tipos de origen de posición para los interactores de mano ya se especifican en los objetos prefabricados predeterminados del controlador MRTK3. No se recomienda modificar la configuración de origen de posición predeterminada del objeto prefabricado.