# UAR51Character

<Badge tone="type">UCLASS · UPoseableMeshComponent</Badge> <Badge>BlueprintSpawnableComponent</Badge>

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

**Inherits:** [`UPoseableMeshComponent`](https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Engine/Components/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`](/docs/sdk-api/unreal-api/classes/uar51skeletonmapping)), then on each frame `Solve(...)` writes the bone transforms through the IK / auto-scale / smoothing pipeline. Normally spawned and owned by [`USkeletonConsumer`](/docs/sdk-api/unreal-api/classes/skeletonconsumer) inside an [`AAR51CharacterActor`](/docs/sdk-api/unreal-api/classes/aar51characteractor) — you rarely construct one by hand.

:::caution[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`](#solve) are indexed by [`Keypoints`](/docs/sdk-api/unreal-api/skeletons-and-characters#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.
:::

:::note[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`](/docs/sdk-api/unreal-api/skeletons-and-characters#fsolverparams) on `USkeletonConsumer::SolverParameters`.
:::

:::tip[How-to]
This page is **reference** (facts only). For the step-by-step *connect → drive a character* walkthrough, see the [How-to guide](/docs/sdk-api/unreal-api/skeletons-and-characters#walkthrough).
:::

## Properties

All `EditAnywhere, BlueprintReadWrite`.

<div className="apiPropTable">

| Property | Type | Default | Description |
|---|---|---|---|
| **General** | | | |
| `AR51Mapping` | [`UAR51SkeletonMapping*`](/docs/sdk-api/unreal-api/classes/uar51skeletonmapping) | — | **preferred** per-skeleton bone-mapping asset |
| `SkeletonMapping` | `UNodeMappingContainer*` | — | legacy fallback mapping, used only if `AR51Mapping` is unset |
| **IK Solver** | | | |
| `bOverrideCalfCorrectionScale` | `bool` | `false` | enable the per-character calf/ankle correction override |
| `CalfCorrectionScaleOverride` | `float` | `0.95` | per-character calf/ankle correction, overrides the global solver value (clamp 0–2; 1.0 = no correction) |
| `bOverrideHandCorrectionScale` | `bool` | `false` | enable the per-character hand-scale correction override |
| `HandCorrectionScaleOverride` | `float` | `0.95` | per-character hand-scale correction (clamp 0–2; 1.0 = no correction) |
| **IK Solver \| Twist** | | | |
| `LeftForearmTwistBones` | [`TArray<FBoneWeight>`](/docs/sdk-api/unreal-api/skeletons-and-characters#fboneweight) | — | left forearm twist-distribution chain |
| `RightForearmTwistBones` | [`TArray<FBoneWeight>`](/docs/sdk-api/unreal-api/skeletons-and-characters#fboneweight) | — | right forearm twist-distribution chain |

</div>

## Method summary

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

| Method | Returns | |
|---|---|---|
| [`Solve`](#solve) | `void` | <Badge>C++ only</Badge> |
| [`SolveHands`](#solvehands) | `void` | <Badge>C++ only</Badge> |
| [`ApplyOnSkeletalMeshes`](#applyonskeletalmeshes) | `void` | <Badge>C++ only</Badge> |

**Setup**

| Method | Returns | |
|---|---|---|
| [`Initialize`](#initialize) | `void` | <Badge tone="accent">BlueprintCallable</Badge> |
| [`GetSkeletonId`](#getskeletonid) | `FString` | <Badge tone="accent">BlueprintCallable</Badge> |
| [`SetSkeletonId` / `GetDeviceId` / `SetDeviceId`](#id--device-wiring) | `void` / `FString` | <Badge>C++ only</Badge> |
| [`GetBoneName`](#getbonename) | `FName` | <Badge>C++ only</Badge> |
| [`ValidateMapping`](#validatemapping) | `bool` | <Badge>C++ only</Badge> |

**Pose read/write**

| Method | Returns | |
|---|---|---|
| [`SetBoneLocalTransformByName`](#setbonelocaltransformbyname) | `void` | <Badge tone="accent">BlueprintCallable</Badge> |
| [`GetBoneLocalTransformByName`](#getbonelocaltransformbyname) | `FTransform` | <Badge tone="accent">BlueprintCallable</Badge> |
| [`GetHeadPosition`](#getheadposition) | `FVector` | <Badge>C++ only</Badge> |
| [`GetHeadRotation` / `SetHeadRotation`](#head-rotation) | `FQuat` / `void` | <Badge>C++ only</Badge> |
| [`GetLeftWristPosition` / `GetRightWristPosition`](#wrist-positions) | `FVector` | <Badge>C++ only</Badge> |
| [`GetLeftHandJoints` / `GetRightHandJoints`](#hand-joints) | `TArray<TSharedPtr<BoneTransform>>` | <Badge>C++ only</Badge> |

→ Full descriptions in [Method details](#method-details) below.

## Method details

### Solve

<ApiBody kind="method" tags="C++ only">

```cpp
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.

<Params>
<Param name="positions" type="TArray<FVector>">one joint position per entry, **indexed by [`Keypoints`](/docs/sdk-api/unreal-api/skeletons-and-characters#keypoints)**, in **UE world-space cm ⚠️**</Param>
<Param name="confidence" type="TArray<float>">per-joint confidence, parallel to `positions`</Param>
<Param name="SolveHands" type="bool">also solve the finger joints this frame (default `true`)</Param>
</Params>

:::caution[⚠️ 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.
:::

<Example inferred>

```cpp
// 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
```

</Example>

</ApiBody>

### SolveHands

<ApiBody kind="method" tags="C++ only">

```cpp
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.

<Params>
<Param name="lHandPos" type="TArray<FVector>">left-hand keypoint positions (UE cm)</Param>
<Param name="rHandPos" type="TArray<FVector>">right-hand keypoint positions (UE cm)</Param>
</Params>

</ApiBody>

### ApplyOnSkeletalMeshes

<ApiBody kind="method" tags="C++ only">

```cpp
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.

</ApiBody>

### Initialize

<ApiBody kind="method" tags="BlueprintCallable">

```cpp
void Initialize();
```

Build the bone mapping and internal solver state from [`AR51Mapping`](/docs/sdk-api/unreal-api/classes/uar51skeletonmapping). Call **once** before driving the character. The consumer calls it for spawned characters; call it yourself only on the manual path.

</ApiBody>

### GetSkeletonId

<ApiBody kind="method" tags="BlueprintCallable">

```cpp
FString GetSkeletonId() const;
```

<Returns type="FString">the AR 51 skeleton id this character represents</Returns>

</ApiBody>

### Id & device wiring

<ApiBody kind="method" tags="C++ only">

```cpp
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.

</ApiBody>

### GetBoneName

<ApiBody kind="method" tags="C++ only">

```cpp
FName GetBoneName(FName& name);
```

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

<Params>
<Param name="name" type="FName">the canonical AR 51 bone name</Param>
</Params>

<Returns type="FName">the mapped bone name on the target skeleton</Returns>

</ApiBody>

### ValidateMapping

<ApiBody kind="method" tags="C++ only">

```cpp
bool ValidateMapping(const TArray<FName>& requiredBoneNames);
```

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

<Params>
<Param name="requiredBoneNames" type="TArray<FName>">the canonical bones that must be mapped</Param>
</Params>

<Returns type="bool">`true` if all required canonical bones resolve to a target bone</Returns>

<Example inferred>

```cpp
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"));
```

</Example>

</ApiBody>

### SetBoneLocalTransformByName

<ApiBody kind="method" tags="BlueprintCallable">

```cpp
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`.

<Params>
<Param name="BoneName" type="FName">target-skeleton bone name (resolve a canonical name first with [`GetBoneName`](#getbonename))</Param>
<Param name="InTransform" type="FTransform">the new local transform (UE cm; rotation as a quaternion)</Param>
</Params>

</ApiBody>

### GetBoneLocalTransformByName

<ApiBody kind="method" tags="BlueprintCallable">

```cpp
FTransform GetBoneLocalTransformByName(FName BoneName);
```

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

<Params>
<Param name="BoneName" type="FName">target-skeleton bone name</Param>
</Params>

<Returns type="FTransform" typeHref="https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Core/Math/FTransform">the bone's local transform (UE cm)</Returns>

</ApiBody>

### GetHeadPosition

<ApiBody kind="method" tags="C++ only">

```cpp
FVector GetHeadPosition();
```

<Returns type="FVector" typeHref="https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Core/Math/FVector">the solved head-bone **world** position (UE cm)</Returns>

<Example inferred>

```cpp
// 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
}
```

</Example>

</ApiBody>

### Head rotation

<ApiBody kind="method" tags="C++ only">

```cpp
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.

<Params>
<Param name="Rotation" type="FQuat">the head world rotation to apply</Param>
</Params>

<Returns type="FQuat" typeHref="https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Core/Math/FQuat">the current head world rotation</Returns>

</ApiBody>

### Wrist positions

<ApiBody kind="method" tags="C++ only">

```cpp
FVector GetLeftWristPosition();
FVector GetRightWristPosition();
```

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

<Returns type="FVector" typeHref="https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Core/Math/FVector">the wrist world position (UE cm)</Returns>

<Example inferred>

```cpp
const FVector L = Char->GetLeftWristPosition();    // UE world-space cm
const FVector R = Char->GetRightWristPosition();
AttachedSword->SetActorLocation(R);
```

</Example>

</ApiBody>

### Hand joints

<ApiBody kind="method" tags="C++ only">

```cpp
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.

<Returns type="TArray<TSharedPtr<BoneTransform>>" typeHref="/docs/sdk-api/unreal-api/classes/bonetransform">the finger-bone handles (see [`BoneTransform`](/docs/sdk-api/unreal-api/classes/bonetransform))</Returns>

</ApiBody>

## See also

- [`USkeletonConsumer`](/docs/sdk-api/unreal-api/classes/skeletonconsumer) — spawns, owns, and drives this character every frame
- [`AAR51CharacterActor`](/docs/sdk-api/unreal-api/classes/aar51characteractor) — the actor that wraps this component
- [`UAR51SkeletonMapping`](/docs/sdk-api/unreal-api/classes/uar51skeletonmapping) — the bone-mapping asset `AR51Mapping` points at
- [`IPersonBase`](/docs/sdk-api/unreal-api/classes/ipersonbase) — `GetCharacter()` returns the `UAR51Character` for a tracked person
- [`BoneTransform`](/docs/sdk-api/unreal-api/classes/bonetransform) — the finger-joint handle type
- [`Keypoints`](/docs/sdk-api/unreal-api/skeletons-and-characters#keypoints) — the joint index order expected by `Solve`
- [`FSolverParams`](/docs/sdk-api/unreal-api/skeletons-and-characters#fsolverparams) — global IK / auto-scale settings on the consumer
- [Class index](/docs/sdk-api/unreal-api/classes) — all Unreal SDK types
