Skip to main content

UAR51Character

UCLASS · UPoseableMeshComponent BlueprintSpawnableComponent
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class AR51SDK_API UAR51Character : public UPoseableMeshComponent

Inherits: UPoseableMeshComponent (Unreal Engine)

The mocap-driven mesh: the skeletal mesh that gets posed from AR 51 skeleton data. It maps each canonical AR 51 bone name onto the target skeleton (via AR51Mapping), then on each frame Solve(...) writes the bone transforms through the IK / auto-scale / smoothing pipeline. Normally spawned and owned by USkeletonConsumer inside an AAR51CharacterActor — you rarely construct one by hand.

Units

This is an Unreal class, so all positions and lengths are UE centimetres and rotations are quaternions/degrees. The joint positions passed to Solve are indexed by Keypoints and are in UE world-space cm ⚠️ — AR 51 mocap data is natively in metres, so the metres→cm scaling happens at the consumer/Solve boundary. See the ⚠️ on Solve below.

Internal — not documented

IK solving, calf/hand correction math, auto-scale, body and finger smoothing, and forearm-twist computation are black boxes. The only public knobs are the properties below plus FSolverParams on USkeletonConsumer::SolverParameters.

How-to

This page is reference (facts only). For the step-by-step connect → drive a character walkthrough, see the How-to guide.

Properties

All EditAnywhere, BlueprintReadWrite.

PropertyTypeDefaultDescription
General
AR51MappingUAR51SkeletonMapping*preferred per-skeleton bone-mapping asset
SkeletonMappingUNodeMappingContainer*legacy fallback mapping, used only if AR51Mapping is unset
IK Solver
bOverrideCalfCorrectionScaleboolfalseenable the per-character calf/ankle correction override
CalfCorrectionScaleOverridefloat0.95per-character calf/ankle correction, overrides the global solver value (clamp 0–2; 1.0 = no correction)
bOverrideHandCorrectionScaleboolfalseenable the per-character hand-scale correction override
HandCorrectionScaleOverridefloat0.95per-character hand-scale correction (clamp 0–2; 1.0 = no correction)
IK Solver | Twist
LeftForearmTwistBonesTArray<FBoneWeight>left forearm twist-distribution chain
RightForearmTwistBonesTArray<FBoneWeight>right forearm twist-distribution chain

Method summary

Drive (per-frame pipeline) — normally called for you by USkeletonConsumer.

MethodReturns
SolvevoidC++ only
SolveHandsvoidC++ only
ApplyOnSkeletalMeshesvoidC++ only

Setup

MethodReturns
InitializevoidBlueprintCallable
GetSkeletonIdFStringBlueprintCallable
SetSkeletonId / GetDeviceId / SetDeviceIdvoid / FStringC++ only
GetBoneNameFNameC++ only
ValidateMappingboolC++ only

Pose read/write

MethodReturns
SetBoneLocalTransformByNamevoidBlueprintCallable
GetBoneLocalTransformByNameFTransformBlueprintCallable
GetHeadPositionFVectorC++ only
GetHeadRotation / SetHeadRotationFQuat / voidC++ only
GetLeftWristPosition / GetRightWristPositionFVectorC++ only
GetLeftHandJoints / GetRightHandJointsTArray<TSharedPtr<BoneTransform>>C++ only

→ Full descriptions in Method details below.

Method details

Solve

methodC++ only
void Solve(const TArray<FVector>& positions, const TArray<float>& confidence, bool SolveHands = true);

The core drive call. Poses the whole skeleton from one frame of joint positions plus per-joint confidence, running the IK / auto-scale / smoothing pipeline (a black box). USkeletonConsumer calls this every frame; you only call it on the manual/advanced path.

Parameters
positionsTArray<FVector>one joint position per entry, indexed by Keypoints, in UE world-space cm ⚠️
confidenceTArray<float>per-joint confidence, parallel to positions
SolveHandsboolalso solve the finger joints this frame (default true)
⚠️ needs confirmation

Whether positions are world-space or component-space, and which side owns the metres→cm scaling at this boundary, is unconfirmed. AR 51 mocap data is metres; UE is cm. Verify before driving manually.

Exampleinferred
// Manual/advanced path only — the consumer normally does this for you.
Character->Initialize(); // once, after AR51Mapping is set
// per frame:
Character->Solve(Positions, Confidence); // Positions indexed by Keypoints, UE world-space cm
Character->ApplyOnSkeletalMeshes(); // push the solved pose to the rendered mesh

SolveHands

methodC++ only
void SolveHands(const TArray<FVector>& lHandPos, const TArray<FVector>& rHandPos);

Pose just the finger joints from hand keypoint positions (UE cm). Useful when body and hands arrive on separate cadences; Solve(..., SolveHands=true) already covers the combined case.

Parameters
lHandPosTArray<FVector>left-hand keypoint positions (UE cm)
rHandPosTArray<FVector>right-hand keypoint positions (UE cm)

ApplyOnSkeletalMeshes

methodC++ only
void ApplyOnSkeletalMeshes();

Push the solved pose onto the rendered mesh(es). Call after Solve / SolveHands on the manual path; in the normal flow the consumer does this for you.

Initialize

methodBlueprintCallable
void Initialize();

Build the bone mapping and internal solver state from AR51Mapping. Call once before driving the character. The consumer calls it for spawned characters; call it yourself only on the manual path.

GetSkeletonId

methodBlueprintCallable
FString GetSkeletonId() const;
ReturnsFStringthe AR 51 skeleton id this character represents

Id & device wiring

methodC++ only
void SetSkeletonId(const FString& Id);
FString GetDeviceId() const;
void SetDeviceId(const FString& Id);

Low-level id/device plumbing, set up by the consumer when it spawns the character. Read GetDeviceId() to find which capture device a character is bound to.

GetBoneName

methodC++ only
FName GetBoneName(FName& name);

Resolve a canonical AR 51 bone name to the corresponding target-skeleton bone name via the active mapping.

Parameters
nameFNamethe canonical AR 51 bone name
ReturnsFNamethe mapped bone name on the target skeleton

ValidateMapping

methodC++ only
bool ValidateMapping(const TArray<FName>& requiredBoneNames);

Check that the mapping covers every required canonical bone — a useful guard before Solve.

Parameters
requiredBoneNamesTArray<FName>the canonical bones that must be mapped
Returnsbooltrue if all required canonical bones resolve to a target bone
Exampleinferred
static const TArray<FName> Required = { TEXT("Hips"), TEXT("Head"), TEXT("LeftHand"), TEXT("RightHand") };
if (!Character->ValidateMapping(Required))
UE_LOG(LogTemp, Warning, TEXT("AR51Mapping is missing required bones — Solve may misbehave"));

SetBoneLocalTransformByName

methodBlueprintCallable
void SetBoneLocalTransformByName(FName BoneName, const FTransform& InTransform);

Set a bone's local (parent-space) transform on the poseable mesh. Lets you override or post-process the solved pose (e.g. additive props) before ApplyOnSkeletalMeshes.

Parameters
BoneNameFNametarget-skeleton bone name (resolve a canonical name first with GetBoneName)
InTransformFTransformthe new local transform (UE cm; rotation as a quaternion)

GetBoneLocalTransformByName

methodBlueprintCallable
FTransform GetBoneLocalTransformByName(FName BoneName);

Read a bone's local (parent-space) transform.

Parameters
BoneNameFNametarget-skeleton bone name
ReturnsFTransformthe bone's local transform (UE cm)

GetHeadPosition

methodC++ only
FVector GetHeadPosition();
ReturnsFVectorthe solved head-bone world position (UE cm)
Exampleinferred
// From a tracked person, read the driven character's head position (UE cm).
if (UObject* P = Consumer->GetActivePerson().GetObject())
{
UAR51Character* Char = IPersonBase::Execute_GetCharacter(P);
const FVector Head = Char->GetHeadPosition(); // UE world-space cm
}

Head rotation

methodC++ only
FQuat GetHeadRotation();
void SetHeadRotation(const FQuat& Rotation);

Read or write the head-bone world rotation. SetHeadRotation is how headset orientation is fused onto the solved skeleton — when USkeletonConsumer::IsApplyHeadRotationWristPositionAndFingerRotations is on, the consumer writes the device's head rotation here.

Parameters
RotationFQuatthe head world rotation to apply
ReturnsFQuatthe current head world rotation

Wrist positions

methodC++ only
FVector GetLeftWristPosition();
FVector GetRightWristPosition();

The solved wrist world positions (UE cm) — handy for attaching props or driving hand UI.

ReturnsFVectorthe wrist world position (UE cm)
Exampleinferred
const FVector L = Char->GetLeftWristPosition(); // UE world-space cm
const FVector R = Char->GetRightWristPosition();
AttachedSword->SetActorLocation(R);

Hand joints

methodC++ only
const TArray<TSharedPtr<BoneTransform>>& GetLeftHandJoints() const;
const TArray<TSharedPtr<BoneTransform>>& GetRightHandJoints() const;

The live finger-bone handles for each hand — direct access to the per-joint transforms maintained by the solver.

ReturnsTArray<TSharedPtr<BoneTransform>>the finger-bone handles (see BoneTransform)

See also

Was this page helpful?