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

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

सेशन पाना

Android XR Session की मदद से, हाथ की जानकारी ऐक्सेस करें. Session पाने के लिए, सेशन के लाइफ़साइकल को समझना लेख पढ़ें.

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

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

val newConfig = session.config.copy(
    handTracking = Config.HandTrackingMode.BOTH
)
when (val result = session.configure(newConfig)) {
    is SessionConfigureConfigurationNotSupported ->
        TODO(/* Some combinations of configurations are not valid. Handle this failure case. */)
    is SessionConfigureSuccess -> TODO(/* Success! */)
    else ->
        TODO(/* A different unhandled exception was thrown. */)
}

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

हाथों का डेटा, बाएं और दाएं हाथ के लिए अलग-अलग उपलब्ध होता है. हर जोड़ के लिए पोज़ की पोज़िशन ऐक्सेस करने के लिए, हर हाथ के 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.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.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.THUMB_TIP] ?: return false
val thumbTipPose = session.scene.perceptionSpace.transformPoseTo(thumbTip, session.scene.activitySpace)
val indexTip = handState.handJoints[HandJointType.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.INDEX_PROXIMAL, HandJointType.INDEX_TIP) &&
    pointingInSameDirection(HandJointType.MIDDLE_PROXIMAL, HandJointType.MIDDLE_TIP) &&
    pointingInSameDirection(HandJointType.RING_PROXIMAL, HandJointType.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. के ट्रेडमार्क हैं. इन्हें चीन, यूरोपियन यूनियन, जापान, और यूनाइटेड किंगडम में ट्रेडमार्क के तौर पर रजिस्टर किया गया है.