見出し画像

Magic Leap2 の ハンドジェスチャー

はじめに

この記事は、Magic Leap2 Advent Calendar 2022 の19日目です。
Magic Leap2 ハンドジェスチャー について説明します。


OnePlanet XR について

https://1planet.co.jp/xrconsulting.html

このブログ記事は OnePlanet XR によるものです。
OnePlanet XR は、AR/MR/VPS技術に専門特化したコンサルティングサービスです。豊富な実績を元に、AR/MR技術を活用した新たな事業の立ち上げ支援や、社内業務のデジタル化/DX推進など、貴社の必要とするイノベーションを実現いたします。

ご相談から受け付けております。ご興味ございましたらお問い合わせください。


Magic Leap2 の ハンドジェスチャー情報の取得について

Magic Leap2 でハンドジェスチャーの情報を取得する方法を紹介します。
位置、回転、指の状態、指の長さ、指の角度の取得も可能だが、ここではポーズの状態のみ行います。


開発環境 / 動作環境

Unity Editor 2022.2.0b8.3023
Magic Leap SDK 1.1.0-dev1
Magic Leap XR Plugin 7.0.0.pre.1
Magic Leap2 OS 1.1.0-dev1 (B3E.221020.13-R.039_40)


サポートしているハンドジェスチャー

Magic Leap ではKeyPoseとPostureの2種類のジェスチャー判定を行うkとができます。

Key Poses

OK , C , Pinch , Finger , L , Thumb , Fist , Open

Magic Leap2 Gesture Key Poses

Postures

Pinch , Point , Grasp , Open

Magic Leap2 Postures

ヒエラルキー

シーンを新規作成します。Main Cameraは削除し、XR Rigのプレファブをヒエラルキーに配置します。
Game Objectを作成し、名前を Gesture Example にします。


GestureExample

Gesture Example の Game Object にアタッチするGestureExampleというスクリプトを作成します。

スクリプトは以下になります。

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR;
using UnityEngine.InputSystem;
using UnityEngine.XR.MagicLeap;
using InputDevice = UnityEngine.InputSystem.InputDevice;
using HandGestures = UnityEngine.XR.MagicLeap.InputSubsystem.Extensions.DeviceFeatureUsages.HandGesture;
using GestureClassification = UnityEngine.XR.MagicLeap.InputSubsystem.Extensions.MLGestureClassification;
using TMPro;


public class GestureExample : MonoBehaviour
{
    [SerializeField]
    private TextMeshProUGUI gestureInfo;
    private UnityEngine.XR.InputDevice leftHandDevice;
    private UnityEngine.XR.InputDevice rightHandDevice;


    // Start is called before the first frame update
    void Start()
    {
        if (!MLPermissions.CheckPermission(MLPermission.HandTracking).IsOk)
        {
            gestureInfo.text = $"You must include the {MLPermission.HandTracking} permission in the AndroidManifest.xml to run this example.";
            enabled = false;
            return;
        }
        GestureClassification.StartTracking();
    }

    // Update is called once per frame
    void Update()
    {
        if (!GesturesInitialized())
        {
            gestureInfo.text = "Gestures Not Initialized.";
            return;
        }
        leftHandDevice.TryGetFeatureValue(
            InputSubsystem.Extensions.DeviceFeatureUsages.HandGesture.GesturePosture, out uint leftPostureInt);
        rightHandDevice.TryGetFeatureValue(
            InputSubsystem.Extensions.DeviceFeatureUsages.HandGesture.GesturePosture, out uint rightPostureInt);

        InputSubsystem.Extensions.MLGestureClassification.PostureType leftHandPostureType =
            (InputSubsystem.Extensions.MLGestureClassification.PostureType)leftPostureInt;

        InputSubsystem.Extensions.MLGestureClassification.PostureType rightHandPostureType =
            (InputSubsystem.Extensions.MLGestureClassification.PostureType)rightPostureInt;

        leftHandDevice.TryGetFeatureValue(
            InputSubsystem.Extensions.DeviceFeatureUsages.HandGesture.GestureKeyPose, out uint leftKeyPoseInt);
        rightHandDevice.TryGetFeatureValue(
            InputSubsystem.Extensions.DeviceFeatureUsages.HandGesture.GestureKeyPose, out uint rightKeyPoseInt);

        InputSubsystem.Extensions.MLGestureClassification.KeyPoseType leftHandKeyPoseType =
            (InputSubsystem.Extensions.MLGestureClassification.KeyPoseType)leftKeyPoseInt;

        InputSubsystem.Extensions.MLGestureClassification.KeyPoseType rightHandKeyPoseType =
            (InputSubsystem.Extensions.MLGestureClassification.KeyPoseType)rightKeyPoseInt;


        gestureInfo.text =
              "Left Hand Posture: " + leftHandPostureType + " Right Hand Posture: " + rightHandPostureType + "\n"
            + "Left Hand KeyPose: " + leftHandKeyPoseType + " Right Hand KeyPose: " + rightHandKeyPoseType;



    }

    bool GesturesInitialized()
    {
        if (!leftHandDevice.isValid || !rightHandDevice.isValid)
        {
            List<UnityEngine.XR.InputDevice> foundDevices = new List<UnityEngine.XR.InputDevice>();
            InputDevices.GetDevices(foundDevices);

            foreach (UnityEngine.XR.InputDevice device in foundDevices)
            {
                if (device.name == GestureClassification.LeftGestureInputDeviceName)
                {
                    leftHandDevice = device;
                    continue;
                }
                if (device.name == GestureClassification.RightGestureInputDeviceName)
                {
                    rightHandDevice = device;
                    continue;
                }
                if (leftHandDevice.isValid && rightHandDevice.isValid)
                {
                    break;
                }
            }
            return false;
        }

        leftHandDevice.TryGetFeatureValue(HandGestures.GesturesEnabled, out bool leftGesture);
        
        if (!leftGesture)
        {
            return false;
        }

        return true;
    }
}



ジェスチャー情報のテキスト表示

ジェスチャーのテキスト表示用のUIを作成します。以下の記事に従って構築してください。

上記の記事で作成したText(TMP)を GestureExampleの gestureInfoフィールドに設定してください。


実行

左右のジェスチャーの状態をテキストに表示されます。


OnePlanet XR

https://1planet.co.jp/xrconsulting.html

AR/MR/VPS技術に専門特化したコンサルティングサービス

Magic Leap2 を使ったソリューションのご検討の方からのお問い合わせ、お待ちしております。


お問い合わせ先

https://1planet.co.jp/xrconsulting.html#op_form


OnePlanet Tech Magazine

Magic Leap1、Magic Leap2 、スマホAR(Niantic Lightship ARDK、WebAR、VPSなど)といったAR技術全般をブログマガジンを連載しています。