2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【visionOS/ARKit】ハンドトラッキングの最小構成サンプルコード【AsyncSequence編】

Last updated at Posted at 2024-05-17

visionOSにおけるARKitのハンドトラッキングAPIの基本は、手の各ジョイントの座標や回転などのデータを取得する事です。

Joints Example SessionVideo

Joints List SessionVideo

今回は、たった41行で動作する最小構成のハンドトラッキングAPIのサンプルコードを紹介します。

基礎知識

まず、このセッションビデオを見てください。visionOSのARKitやハンドトラッキングについて概ね分かります。

日本語字幕があります。15:05からハンドトラッキングについて説明しています。

2つのAPI

ジョイントデータを取得するAPIは2つあります。どちらもHandTrackingProviderインスタンスから取得します。

  • AsyncSequenceで最新の値を受け取るanchorUpdates
  • 最新の値が格納されているlatestAnchors

Observing hand anchor data

今回はAsyncSequenceのanchorUpdatesで実装しました。

latestAnchorsで実装する場合はこちらの記事を参照してください。

サンプルコードの概要

  • アプリの起動と同時にハンドトラッキングを開始する。
  • 両手の全てのジョイントにシンプルな球体オブジェクトを配置する。
  • 常に最新のジョイントの位置になるように各オブジェクトを更新する。
  • オブジェクトが手で隠れないようにする。

Example 1

Example 2

ソースコード全体

import SwiftUI
import RealityKit
import ARKit

@main
struct MyApp: App {
    private let session = ARKitSession()
    private let provider = HandTrackingProvider()
    private let rootEntity = Entity()
    
    var body: some SwiftUI.Scene {
        ImmersiveSpace {
            RealityView { content in
                content.add(rootEntity)
                for chirality in [HandAnchor.Chirality.left, .right] {
                    for jointName in HandSkeleton.JointName.allCases {
                        let jointEntity = ModelEntity(mesh: .generateSphere(radius: 0.006),
                                                      materials: [SimpleMaterial()])
                        jointEntity.name = "\(jointName)\(chirality)"
                        rootEntity.addChild(jointEntity)
                    }
                }
            }
            .task { try! await session.run([provider]) }
            .task {
                for await update in provider.anchorUpdates {
                    let handAnchor = update.anchor
                    for jointName in HandSkeleton.JointName.allCases {
                        guard let joint = handAnchor.handSkeleton?.joint(jointName),
                              let jointEntity = rootEntity.findEntity(named: "\(jointName)\(handAnchor.chirality)") else {
                            continue
                        }
                        jointEntity.setTransformMatrix(handAnchor.originFromAnchorTransform * joint.anchorFromJointTransform,
                                                       relativeTo: nil)
                    }
                }
            }
        }
        .upperLimbVisibility(.hidden)
    }
}

ソースコードはこれだけです。コピペしてください。

コードコピペ以外に必要な作業

  • Info.plistで「NSHandsTrackingUsageDescription」に任意のテキストを設定
  • Info.plistで「Preferred Default Scene Session Role」に「Immersive Space」を設定

Info.plist Screenshot

解説

前述のセッションビデオ内で説明されている内容は省略します。また、SwiftUIやRealityKitの基本的な知識についての説明も省略します。

AsyncSequenceで最新の値を受け取る

for await update in provider.anchorUpdates {
    let handAnchor = update.anchor
    ...
}

AsyncSequence(for await構文)で最新のデータを随時受け取るようにします。そして、受け取ったupdateからHandAnchorの値を取り出します。

各エンティティの管理

jointEntity.name = "\(jointName)\(chirality)"
let jointEntity = rootEntity.findEntity(named: "\(jointName)\(handAnchor.chirality)")

今回はエンティティのnameで各エンティティを管理しました。

各ジョイントの名称を表すHandSkeleton.JointNameと、左手か右手かを表すHandAnchor.Chiralityを用いてエンティティのnameを指定しました。

手のオクルージョンを切り替える

両手のオクルージョン

visionOSでは両手のオクルージョンがデフォルトで有効になっています。これをオフにするにはSwiftUIのupperLimbVisibilityでhiddenと設定してください。

.upperLimbVisibility(.hidden)

アクセス権限リクエストの設定

アクセス権限リクエストのためにInfo.plistで「NSHandsTrackingUsageDescription」に任意のテキストを設定する必要があります。

多くの場合、Info.plistで何らかの値を設定するにはプルダウンメニューからkeyを指定します。しかし今回の場合はプルダウンメニューに表示されないので、「NSHandsTrackingUsageDescription」と直接入力してください。

Xcode Info.plist pull-down-menu

フルスペースでアプリを起動

@main
struct MyApp: App {
	...
    var body: some SwiftUI.Scene {
        ImmersiveSpace {
        	...
        }
        ...
	}
}

XcodeでvisionOSアプリプロジェクトを新規作成すると、ウインドウで起動するコードが生成されます。今回はシンプルな実装にするために、フルスペースで起動するようにしました。

Info.plistの「Preferred Default Scene Session Role」に「Immersive Space」を設定する必要があります。この設定をしないとアプリ起動直後にクラッシュします。

【注意】Apple Vision Pro実機が必要

ARKitのハンドトラッキングAPIを試すにはApple Vision Pro実機が必要です。シミュレーターでは全く動きません。

次のステップ

  • 現在のアクセス権限の状態を確認: session.queryAuthorization(for:)
  • アクセス権限許可を明示的にリクエスト: session.requestAuthorization(for:)
  • アンカーの状態を確認: AnchorUpdate.Event
  • 各アンカーや各ジョイントがトラッキング中かどうかを確認: TrackableAnchor.isTracked
  • DataProviderの状態変化を監視: ARKitSession.Events
  • 現在の実行環境がサポートしているかを確認: HandTrackingProvider.isSupported

リンク


2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?