How to get Human Body Height from ARBodyAnchor?

1k Views Asked by At

I am trying to get real-world human body height from ARBodyAnchor. I understand that I can get real-world distance between body joints. For example hip to foot-joint as in code below. But how do I get distance from top of head to bottom of foot?

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
    if anchor is ARBodyAnchor {
        let footIndex = ARSkeletonDefinition.defaultBody3D.index(for: .leftFoot)
        let footTransform = ARSkeletonDefinition.defaultBody3D.neutralBodySkeleton3D!.jointModelTransforms[footIndex]
        let distanceFromHipOnY = abs(footTransform.columns.3.y)
        print(distanceFromHipOnY)
    }
}
1

There are 1 best solutions below

10
Andy Jazz On BEST ANSWER

Read this post if you need to setup a custom model for MoCap.

enter image description here

The default height of ARSkeleton3D from right_toes_joint (or if you wish left_toes_joint) to head_joint is 1.71 meters. And since head_joint in Apple's skeletal system's definition is the upmost skeleton's point, you can use the common skull's height – from eye line to crown.

In other words, the distance from neck_3_joint to head_joint in virtual model's skeleton is approximately the same as from head_joint to crown.

enter image description here

There are 91 joint in ARSkeleton3D:

print(bodyAnchor.skeleton.jointModelTransforms.count)      // 91

Code:

extension ViewController: ARSessionDelegate {

    func session(_ session: ARSession, didUpdate anchors: [ARAnchor]) {
    
        for anchor in anchors {
        
            guard let bodyAnchor = anchor as? ARBodyAnchor
            else { return }

            let skeleton = bodyAnchor.skeleton

            for (i, joint) in skeleton.definition.jointNames.enumerated() {
                print(i, joint)

                // [10] right_toes_joint
                // [51] head_joint
            }
        
            let toesJointPos = skeleton.jointModelTransforms[10].columns.3.y
            let headJointPos = skeleton.jointModelTransforms[51].columns.3.y

            print(headJointPos - toesJointPos)       // 1.6570237 m
        }
    }
}

However, we have a compensator:

bodyAnchor.estimatedScaleFactor

ARKit must know the height of a person in the camera feed to estimate an accurate world position for the person's body anchor. ARKit uses the value of estimatedScaleFactor to correct the body anchor's position in the physical environment.

The default real-world body is 1.8 meters tall. (some kind of mismatch...)

The default value of estimatedScaleFactor is 1.0.

If you set:

let config = ARBodyTrackingConfiguration()
config.automaticSkeletonScaleEstimationEnabled = true
arView.session.run(config, options: [])

ARKit sets this property to a value between 0.0 and 1.0.