Jetpack XR के लिए ARCore का इस्तेमाल करके, हाथों से काम करना

एक्सआर की सुविधा वाले डिवाइस
इस गाइड की मदद से, इन तरह के एक्सआर डिवाइसों के लिए अनुभव बनाए जा सकते हैं.
एक्सआर हेडसेट
वायर्ड एक्सआर ग्लास

ARCore for Jetpack XR, उपयोगकर्ता के हाथों का पता लगा सकता है. साथ ही, हाथों और उनसे जुड़े जोड़ों की पोज़िशन की जानकारी दे सकता है. इस हाथ के डेटा का इस्तेमाल, किसी उपयोगकर्ता के हाथों से इकाइयों और मॉडल को जोड़ने के लिए किया जा सकता है. उदाहरण के लिए, टूल मेन्यू:

किसी सेशन को ऐक्सेस करना

Jetpack XR Runtime Session के ज़रिए हाथ की जानकारी ऐक्सेस करें. आपका ऐप्लिकेशन इसे बना सकता है.

सेशन कॉन्फ़िगर करना

XR सेशन में, हाथ ट्रैक करने की सुविधा डिफ़ॉल्ट रूप से चालू नहीं होती. हाथ के डेटा को पाने के लिए, सेशन को कॉन्फ़िगर करें और HandTrackingMode.BOTH मोड सेट करें:

val newConfig = session.config.copy(
    handTracking = Config.HandTrackingMode.BOTH
)
when (val result = session.configure(newConfig)) {
    is SessionConfigureSuccess -> TODO(/* Success! */)
    else ->
        TODO(/* The session could not be configured. See SessionConfigureResult for possible causes. */)
}

हाथ के डेटा को वापस पाना

हाथों का डेटा, बाएं और दाएं हाथ के लिए अलग-अलग उपलब्ध होता है. हर हाथ के state का इस्तेमाल करके, हर जॉइंट के लिए पोज़ की पोज़िशन ऐक्सेस करें:

Hand.left(session)?.state?.collect { handState -> // or Hand.right(session)
    // Hand state has been updated.
    // Use the state of hand joints to update an entity's position.
    renderPlanetAtHandPalm(handState)
}

हाथों में ये प्रॉपर्टी होती हैं:

  • trackingState: हाथ को ट्रैक किया जा रहा है या नहीं.
  • handJoints: हाथ की उंगलियों के जोड़ों को पोज़ पर मैप करने वाला मैप. हाथ की उंगलियों के जॉइंट के पोज़, OpenXR स्टैंडर्ड के हिसाब से तय किए जाते हैं.

अपने ऐप्लिकेशन में हाथ के डेटा का इस्तेमाल करना

उपयोगकर्ता के हाथ की उंगलियों की पोज़िशन का इस्तेमाल, 3D ऑब्जेक्ट को एंकर करने के लिए किया जा सकता है. उदाहरण के लिए, किसी मॉडल को बाएं हाथ की हथेली से अटैच करने के लिए:

val palmPose = leftHandState.handJoints[HandJointType.HAND_JOINT_TYPE_PALM] ?: return

// the down direction points in the same direction as the palm
val angle = Vector3.angleBetween(palmPose.rotation * Vector3.Down, Vector3.Up)
palmEntity.setEnabled(angle > Math.toRadians(40.0))

val transformedPose =
    session.scene.perceptionSpace.transformPoseTo(
        palmPose,
        session.scene.activitySpace,
    )
val newPosition = transformedPose.translation + transformedPose.down * 0.05f
palmEntity.setPose(Pose(newPosition, transformedPose.rotation))

इसके अलावा, अगर आपको मॉडल को अपने दाएँ हाथ के अंगूठे के पास वाली उंगली के सिरे से जोड़ना है, तो:

val tipPose = rightHandState.handJoints[HandJointType.HAND_JOINT_TYPE_INDEX_TIP] ?: return

// the forward direction points towards the finger tip.
val angle = Vector3.angleBetween(tipPose.rotation * Vector3.Forward, Vector3.Up)
indexFingerEntity.setEnabled(angle > Math.toRadians(40.0))

val transformedPose =
    session.scene.perceptionSpace.transformPoseTo(
        tipPose,
        session.scene.activitySpace,
    )
val position = transformedPose.translation + transformedPose.forward * 0.03f
val rotation = Quaternion.fromLookTowards(transformedPose.up, Vector3.Up)
indexFingerEntity.setPose(Pose(position, rotation))

हाथ के बुनियादी जेस्चर का पता लगाना

हाथ के बेसिक जेस्चर का पता लगाने के लिए, हाथ की उंगलियों के जोड़ों की पोज़ का इस्तेमाल करें. हाथ की उंगलियों के जोड़ों के लिए तय किए गए नियमों को देखें. इससे यह तय करने में मदद मिलेगी कि किसी पोज़ को रजिस्टर करने के लिए, जोड़ों को किस रेंज में होना चाहिए.

उदाहरण के लिए, अंगूठे और तर्जनी उंगली से पिंच करने का पता लगाने के लिए, दोनों उंगलियों के सिरे के बीच की दूरी का इस्तेमाल करें:

val thumbTip = handState.handJoints[HandJointType.HAND_JOINT_TYPE_THUMB_TIP] ?: return false
val thumbTipPose = session.scene.perceptionSpace.transformPoseTo(thumbTip, session.scene.activitySpace)
val indexTip = handState.handJoints[HandJointType.HAND_JOINT_TYPE_INDEX_TIP] ?: return false
val indexTipPose = session.scene.perceptionSpace.transformPoseTo(indexTip, session.scene.activitySpace)
return Vector3.distance(thumbTipPose.translation, indexTipPose.translation) < 0.05

ज़्यादा मुश्किल जेस्चर का एक उदाहरण "बंद करो" जेस्चर है. इस जेस्चर में, हर उंगली को फैलाया जाना चाहिए. इसका मतलब है कि हर उंगली का हर जोड़, एक ही दिशा में होना चाहिए:

val threshold = toRadians(angleInDegrees = 30f)
fun pointingInSameDirection(joint1: HandJointType, joint2: HandJointType): Boolean {
    val forward1 = handState.handJoints[joint1]?.forward ?: return false
    val forward2 = handState.handJoints[joint2]?.forward ?: return false
    return Vector3.angleBetween(forward1, forward2) < threshold
}
return pointingInSameDirection(HandJointType.HAND_JOINT_TYPE_INDEX_PROXIMAL, HandJointType.HAND_JOINT_TYPE_INDEX_TIP) &&
    pointingInSameDirection(HandJointType.HAND_JOINT_TYPE_MIDDLE_PROXIMAL, HandJointType.HAND_JOINT_TYPE_MIDDLE_TIP) &&
    pointingInSameDirection(HandJointType.HAND_JOINT_TYPE_RING_PROXIMAL, HandJointType.HAND_JOINT_TYPE_RING_TIP)

हाथ के जेस्चर का पता लगाने के लिए कस्टम डिटेक्शन की सुविधा डेवलप करते समय, इन बातों का ध्यान रखें:

  • ऐसा हो सकता है कि उपयोगकर्ता, किसी भी जेस्चर को अलग-अलग तरीके से समझें. उदाहरण के लिए, कुछ लोगों के लिए "रुकें" का मतलब उंगलियों को फैलाना हो सकता है, जबकि कुछ लोगों के लिए उंगलियों को एक साथ रखना ज़्यादा आसान हो सकता है.
  • कुछ जेस्चर को बनाए रखना मुश्किल हो सकता है. ऐसे आसान जेस्चर का इस्तेमाल करें जिनसे उपयोगकर्ता के हाथों पर ज़ोर न पड़े.

उपयोगकर्ता के दूसरे हाथ का पता लगाना

Android सिस्टम, सिस्टम नेविगेशन को उपयोगकर्ता के मुख्य हाथ पर रखता है. यह उपयोगकर्ता की सिस्टम सेटिंग में तय किया जाता है. सिस्टम नेविगेशन के जेस्चर के साथ टकराव से बचने के लिए, अपने कस्टम जेस्चर के लिए दूसरे हाथ का इस्तेमाल करें:

val handedness = Hand.getPrimaryHandSide(activity.contentResolver)
val secondaryHand = if (handedness == Hand.HandSide.LEFT) Hand.right(session) else Hand.left(session)
val handState = secondaryHand?.state ?: return
detectGesture(handState)


OpenXR™ और OpenXR लोगो, The Khronos Group Inc. के ट्रेडमार्क हैं. इन्हें चीन, यूरोपियन यूनियन, जापान, और यूनाइटेड किंगडम में ट्रेडमार्क के तौर पर रजिस्टर किया गया है.