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)
}
}
Read this post if you need to setup a custom model for MoCap.
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
.
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.