Skip to main content

Skeletons & characters

The heart of the SDK: USkeletonConsumer connects to the skeleton stream, spawns/destroys a character per tracked person, drives each UAR51Character every frame, and fires person-lifecycle events.

Units

UE works in centimeters / degrees; AR 51 mocap data is natively meters. Conversion happens inside the SDK before bone driving — by the time positions reach UAR51Character::Solve(...) they appear to be UE world-space cm. ⚠️ The exact layer that scales meters→cm, and whether SkeletonData.Positions handed to callers is meters or cm, is unconfirmed.

USkeletonConsumer

Moved to USkeletonConsumer.

UAR51Character

Moved to UAR51Character.

AAR51CharacterActor

Moved to AAR51CharacterActor.

UAR51SkeletonMapping

Moved to UAR51SkeletonMapping.

FBoneWeight

USTRUCT BlueprintType

A single bone + blend weight, used for twist chains: FName Bone; float Weight = 1.0f (clamp 0–1). Both EditAnywhere, BlueprintReadWrite.

UAR51FootBoundsComponent

Moved to UAR51FootBoundsComponent.

SkeletonData

Moved to SkeletonData.

Keypoints

Moved to Keypoints.

IPersonBase

Moved to IPersonBase.

BoneTransform

Moved to BoneTransform.

Prediction

Smoothing / extrapolation knobs, set via USkeletonConsumer::SkeletonPredictionSettings. The predictor classes themselves are C++-only strategy types — you configure them entirely through these structs.

EPredictionModel

UENUM BlueprintType

None ("No Prediction"), Linear, Kalman ("Kalman Filter").

FPredictionSettings

USTRUCT BlueprintType
FieldDefaultMeaning
ModelNonewhich model filters/predicts incoming skeleton data
PredictionDeltaTime0.016flook-ahead Δt in seconds (~60 FPS)
MaxPredictionDisplacement5.0fclamp look-ahead displacement (cm)
OutlierThreshold50.fignore per-frame spikes above this (cm)
LinearFLinearPredictionTuning (shown when Model==Linear)
KalmanFKalmanPredictionTuning (shown when Model==Kalman)

FLinearPredictionTuningVelocitySmoothingAlpha{0.92} (0–1; higher = smoother), MaxVelocity{800.f} (cm/s), ConfidenceMinForVelocity{0.2} (0–1).

FKalmanPredictionTuningAccelStd{200.f} (cm/s²; higher = more responsive), MeasurementNoisePos{2.0} (cm²; higher = smoother), bConfidenceWeighting{true} (scale trust by 1 - confidence).

IK solver & auto-scale settings

FSolverParams

USTRUCT BlueprintType

Set via USkeletonConsumer::SolverParameters. All EditAnywhere, BlueprintReadWrite:

  • Enabled{true}.
  • CalfCorrectionScale{0.95} — ankle-position correction (1.0 = none); per-character override via UAR51Character.
  • HandCorrectionScale{1.0} — hand auto-scale correction (1.0 = none).
  • MinimumHandsConfidence{0.1} — min headset-hand confidence still solved.
  • EnableLimbPositioning{true}, EnableClavicleRotation{true}.
  • AutoScaleType{Default}, AutoHandScaleType{NoScaling}, FilterType{SimpleSmoothing}.
  • SmoothingFactor{0.995}, MinValidScale{0.2}, MaxValidScale{1.8}.
  • EnableBodySmoothing{true}, TemporalRotationalSmooth{0.75}, TemporalRotationalNeckSmooth{0.75}, EnableFingerSmoothing{true}, TemporalFingersRotationalSmooth{0.75}.
  • Helpers: bool IsValidScale(float), bool IsEnableLimbPositioning().
UENUM BlueprintType
  • EAutoCharacterAssignmentModeACAM_Default (first valid character), ACAM_Cycle, ACAM_Random.
  • EAutoScaleFilterTypeFT_Default, FT_Kalman, FT_MovingAverage, FT_MovingMedian, FT_SimpleSmoothing.
  • EActivePersonCameraSpaceAPCS_ComponentSpace (default, world location), APCS_RelativeSpace (relative within parent).
  • EAutoScaleTypeFT_NoScaling, FT_Default.

Walkthrough

Connect → receive skeleton → drive a character (Blueprint-first; the SDK does the heavy lifting):

  1. Place the consumer. Add a USkeletonConsumer component to an actor (e.g. a "GameManager" actor). Only one is needed — it's a singleton.
  2. Author a mapping asset. Create a UAR51SkeletonMapping, set TargetSkeleton, run AutoMap() (or map in the AR 51 humanoid mapping editor). Check GetValidationSummary shows 0 missing/invalid. ⚠️ exact editor menu/action name unconfirmed.
  3. Make a character actor. Create a Blueprint child of AAR51CharacterActor for your mesh; set its Character's AR51Mapping to the asset from step 2. (Fit Left/RightFootBounds via the character's "Create Foot Bounds" action.) ⚠️ whether AR51Mapping is set on the BP default or wired at spawn is unconfirmed.
  4. Register the character. Add your character BP to USkeletonConsumer::CharacterBlueprints. Optionally map specific people via PersonIdToCharacterBPMap / SetCharacterByPersonId(...), or rely on AutoCharacterAssignmentMode.
  5. Tune (optional). Set SolverParameters and SkeletonPredictionSettings (e.g. Model=Linear). Set the main camera via SetMainCameraComponent if head fusion / active-person selection needs a specific one.
  6. Connect. On BeginPlay, call Connect("IP:Port") (the AR 51 skeleton service endpoint). ⚠️ default/expected endpoint string unconfirmed.
  7. React to people. Bind OnPersonDetected / OnPersonUpdated / OnPersonDestroyed / OnActivePersonChanged. The consumer automatically spawns an AAR51CharacterActor per detected person and drives it every frame (calls Solve(...) internally) — you do not call Solve yourself. Use GetPersonByPersonId(...) / GetActivePerson()GetCharacter() to read state (head/wrist positions, etc.).
  8. Cleanup. Disconnect() on EndPlay; ResetCharacters() to clear all spawned models.
Manual/advanced path

If you drive a UAR51Character yourself: call Initialize() once, then per frame call Solve(positions, confidence) with positions indexed by Keypoints in UE world-space cm, followed by ApplyOnSkeletalMeshes(). ⚠️ whether positions are world- or component-space, and the meters→cm scaling responsibility at that boundary, is unconfirmed.


Next: Object detection.

Was this page helpful?