# HandJointInfo

<Badge tone="type">struct (plain C++)</Badge> <Badge>C++ only</Badge>

```cpp
struct AR51SDK_API HandJointInfo;
```

The hand data model. This page covers the four types that describe a single tracked hand joint and the joint taxonomy around it:

- `HandJointInfo` — the per-joint pose struct (the unit returned by the hands adapter).
- [`EHandJointType`](#ehandjointtype) — the 23 ordered hand-skeleton joints (Blueprint-exposed).
- [`EHandType`](#ehandtype) — right vs. left.
- [`HandJointTypeHelper`](#handjointtypehelper) — static queries over the joint enum.

`HandJointInfo` is a **plain C++ `struct`** — no `USTRUCT` macro, **not** Blueprint-exposed. A platform's hand-tracking backend produces a `TArray<HandJointInfo>` per hand (one entry per [`EHandJointType`](#ehandjointtype)); game code reads it through the [`IHandsAdapter`](/docs/sdk-api/unreal-api/hands-boundary-anchors#ihandsadapter) interface.

:::caution[Units]
Unreal Engine uses **centimeters** for position and **degrees** for rotation; the AR 51 native domain uses **meters**. Every `FVector` position on these types is in **UE centimeters** in its respective space. ⚠️ Confirm whether the SDK converts AR 51 meters → UE cm at the adapter boundary, or whether the caller receives raw native units.
:::

## HandJointInfo

<Badge tone="type">struct (plain C++)</Badge> <Badge>C++ only</Badge>

```cpp
struct AR51SDK_API HandJointInfo
{
    EHandType        HandType;
    EHandJointType   JointType;
    float            Confidence;
    FVector          Position;                  // UE cm
    FQuat            Rotation;
    FVector          HmdTrackingSpacePosition;  // UE cm
    FQuat            HmdTrackingSpaceRotation;
};
```

Plain-old-data describing the pose of a single tracked hand joint. From the SDK doc comment: *"Provides information regarding a particular joint in a tracked hand. On platforms where finger-based confidence is not available the overall hand confidence is used. Joints with a confidence of zero are considered missing."*

### Fields

<div className="apiPropTable">

| Field | Type | Description |
|---|---|---|
| `HandType` | [`EHandType`](#ehandtype) | which hand this joint belongs to |
| `JointType` | [`EHandJointType`](#ehandjointtype) | which joint on that hand |
| `Confidence` | `float` | tracking confidence; `0` means the joint is missing/untracked. ⚠️ expected range unverified (likely `0..1`, but not asserted in source) |
| `Position` | [`FVector`](https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Core/Math/FVector) | resolved (world- or anchor-relative) joint position used by the helpers. **UE cm.** ⚠️ |
| `Rotation` | [`FQuat`](https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Core/Math/FQuat) | joint orientation matching `Position` |
| `HmdTrackingSpacePosition` | [`FVector`](https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Core/Math/FVector) | joint position in the HMD's raw tracking space. **UE cm.** ⚠️ |
| `HmdTrackingSpaceRotation` | [`FQuat`](https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Core/Math/FQuat) | joint orientation in HMD tracking space |

</div>

### Constructors

| Constructor | Use |
|---|---|
| [`HandJointInfo(HandType, JointType)`](#handjointinfohandtype-jointtype) | "empty" / missing joint |
| [`HandJointInfo(HandType, JointType, Confidence, Position, Rotation)`](#handjointinfo-single-pose) | single pose (tracking space = working space) |
| [`HandJointInfo(HandType, JointType, Confidence, HmdPos, HmdRot, Position, Rotation)`](#handjointinfo-full-form) | full form (distinct HMD-tracking-space + working-space poses) |

### Static helpers

| Method | Returns | |
|---|---|---|
| [`GetConfidentPositions`](#getconfidentpositions) | [`TArray<FVector>`](https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Core/Containers/TArray) | <Badge>C++ only</Badge> |
| [`GetPositions`](#getpositions) | [`TArray<FVector>`](https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Core/Containers/TArray) | <Badge>C++ only</Badge> |
| [`HasConfidentPositions`](#hasconfidentpositions) | `bool` | <Badge>C++ only</Badge> |

#### Constructor details

### HandJointInfo(HandType, JointType)

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

```cpp
HandJointInfo(EHandType handType, EHandJointType jointType);
```

"Empty" joint: `Confidence = 0`, `Position = FVector::ZeroVector`, `Rotation = FQuat::Identity` (and likewise for the HMD-tracking-space fields). Represents a missing joint.

</ApiBody>

### HandJointInfo (single pose)

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

```cpp
HandJointInfo(EHandType handType, EHandJointType jointType,
              float confidence, const FVector& position, const FQuat& rotation);
```

Sets `Position`/`Rotation` **and** the `HmdTrackingSpace*` fields to the same supplied values — tracking space is assumed identical to working space.

<Params>
<Param name="confidence" type="float">tracking confidence (`0` = missing). ⚠️ range unverified</Param>
<Param name="position" type="FVector">joint position. **UE cm.** ⚠️</Param>
<Param name="rotation" type="FQuat">joint orientation</Param>
</Params>

</ApiBody>

### HandJointInfo (full form)

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

```cpp
HandJointInfo(EHandType handType, EHandJointType jointType, float confidence,
              const FVector& hmdTrackingSpacePosition, const FQuat& hmdTrackingSpaceRotation,
              const FVector& position, const FQuat& rotation);
```

Full form: distinct HMD-tracking-space pose (`hmdTrackingSpace*`) and resolved working-space pose (`position`/`rotation`).

</ApiBody>

#### Static helper details

### GetConfidentPositions

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

```cpp
static TArray<FVector> GetConfidentPositions(const TArray<HandJointInfo>& jointsInfo,
                                             float minimumConfidence);
```

Returns all joint positions **only if** the hand passes the confidence gate (see [`HasConfidentPositions`](#hasconfidentpositions)); otherwise returns an empty array. All-or-nothing per hand — there is no per-joint filtering.

<Params>
<Param name="jointsInfo" type="TArray<HandJointInfo>">a whole hand's joints (e.g. from `IHandsAdapter::GetRightJointInfos()`)</Param>
<Param name="minimumConfidence" type="float">gate applied to the wrist (joint `[0]`) confidence</Param>
</Params>

<Returns type="TArray<FVector>" typeHref="https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Core/Containers/TArray">every `Position` in order if the hand is confident, else empty. **UE cm.** ⚠️</Returns>

<Example inferred>

```cpp
auto* Hands = AdapterFactory<IHandsAdapter>::GetAdapter();
const TArray<HandJointInfo> Right = Hands->GetRightJointInfos();
for (const FVector& P : HandJointInfo::GetConfidentPositions(Right, 0.5f))
{
    // P is in UE cm; empty array means the hand failed the wrist confidence gate
}
```

</Example>

</ApiBody>

### GetPositions

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

```cpp
static TArray<FVector> GetPositions(const TArray<HandJointInfo>& jointsInfo);
```

Extracts every `Position` into a flat array, preserving joint order. No confidence filtering — missing joints contribute their (zero) positions too.

<Returns type="TArray<FVector>" typeHref="https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Core/Containers/TArray">all `Position` values in order. **UE cm.** ⚠️</Returns>

</ApiBody>

### HasConfidentPositions

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

```cpp
static bool HasConfidentPositions(const TArray<HandJointInfo>& jointsInfo,
                                  float minimumConfidence);
```

`true` when the array is non-empty **and the first joint's** `Confidence >= minimumConfidence`.

:::caution[Wrist proxy]
This checks joint `[0]` — the [`Wrist`](#ehandjointtype) — as a **proxy for whole-hand confidence**, rather than inspecting every joint. `GetConfidentPositions` uses this same gate. If the wrist is confident, the whole hand is treated as confident.
:::

<Returns type="bool">`true` if the wrist passes the gate</Returns>

</ApiBody>

## EHandJointType

<Badge tone="type">UENUM · uint8</Badge> <Badge tone="accent">BlueprintType</Badge>

```cpp
UENUM(BlueprintType)
enum class EHandJointType : uint8 { /* … */ };
```

Enumerates the **23 tracked hand-skeleton joints**, ordered Wrist → per-finger chains. Each value carries a `UMETA(DisplayName=...)` so it reads cleanly in Blueprint dropdowns. The same ordering is what fills a hand's `TArray<HandJointInfo>` (index `0` is always the wrist).

| # | Value | # | Value |
|---|---|---|---|
| 0 | `Wrist` | 12 | `MiddleDistal` |
| 1 | `ThumbTrapezium` | 13 | `MiddleTip` |
| 2 | `ThumbMetaCarpal` | 14 | `RingProximal` |
| 3 | `ThumbProximal` | 15 | `RingIntermediate` |
| 4 | `ThumbDistal` | 16 | `RingDistal` |
| 5 | `ThumbTip` | 17 | `RingTip` |
| 6 | `IndexProximal` | 18 | `LittleMetaCarpal` |
| 7 | `IndexIntermediate` | 19 | `LittleProximal` |
| 8 | `IndexDistal` | 20 | `LittleIntermediate` |
| 9 | `IndexTip` | 21 | `LittleDistal` |
| 10 | `MiddleProximal` | 22 | `LittleTip` |
| 11 | `MiddleIntermediate` | | |

Chain shape notes:

- The **thumb** has no `Intermediate` — its chain is `ThumbTrapezium → ThumbMetaCarpal → ThumbProximal → ThumbDistal → ThumbTip`.
- The **little finger** includes a `LittleMetaCarpal` that the index/middle/ring do not.
- **Index / middle / ring** each start at `Proximal` (`Proximal → Intermediate → Distal → Tip`).

The fingertips (`*Tip`) are detected by [`HandJointTypeHelper::IsTip`](#istip), and per-finger ordered chains are available via the `Get*Sequence` helpers.

## EHandType

<Badge tone="type">enum (plain C++)</Badge> <Badge>C++ only</Badge>

```cpp
enum EHandType { RightHand = 0, LeftHand = 1 };
```

Identifies which hand a joint belongs to. This is a **plain C++ `enum`** — no `UENUM` macro, **not** Blueprint-exposed.

| Value | Number |
|---|---|
| `RightHand` | `0` |
| `LeftHand` | `1` |

## HandJointTypeHelper

<Badge tone="type">class (plain C++)</Badge> <Badge>C++ only</Badge>

```cpp
class AR51SDK_API HandJointTypeHelper;   // static methods only
```

A static-only utility class of convenience queries over [`EHandJointType`](#ehandjointtype). Not Blueprint-exposed.

| Method | Returns | |
|---|---|---|
| [`GetTypes`](#gettypes) | [`const TArray<EHandJointType>&`](https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Core/Containers/TArray) | <Badge>C++ only</Badge> |
| [`IsTip`](#istip) | `bool` | <Badge>C++ only</Badge> |
| [`Get*Sequence`](#finger-sequences) | [`const TArray<EHandJointType>&`](https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Core/Containers/TArray) | <Badge>C++ only</Badge> |
| [`ToString`](#tostring) | `FString` | <Badge>C++ only</Badge> |

### GetTypes

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

```cpp
static const TArray<EHandJointType>& GetTypes();
```

All joint types, presumably in enum order (Wrist → little tip).

<Returns type="const TArray<EHandJointType>&" typeHref="https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Core/Containers/TArray">every [`EHandJointType`](#ehandjointtype) value. ⚠️ exact contents unverified (defined in `HandJointType.cpp`)</Returns>

</ApiBody>

### IsTip

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

```cpp
static bool IsTip(EHandJointType type);
```

<Params>
<Param name="type" type="EHandJointType">a joint type</Param>
</Params>

<Returns type="bool">`true` if the joint is a fingertip (a `*Tip` value: `ThumbTip`, `IndexTip`, `MiddleTip`, `RingTip`, `LittleTip`)</Returns>

</ApiBody>

### Finger sequences

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

```cpp
static const TArray<EHandJointType>& GetThumbSequence();
static const TArray<EHandJointType>& GetIndexSequence();
static const TArray<EHandJointType>& GetMiddleSequence();
static const TArray<EHandJointType>& GetRingSequence();
static const TArray<EHandJointType>& GetPinkySequence();
```

The ordered joint chain for one finger, root → tip — useful for drawing bones or walking a finger. Note the naming mismatch: the enum spells the little finger **`Little*`**, but this accessor is **`GetPinkySequence`**.

<Returns type="const TArray<EHandJointType>&" typeHref="https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Core/Containers/TArray">the finger's joints in order (e.g. thumb = `ThumbTrapezium → … → ThumbTip`)</Returns>

<Example inferred>

```cpp
const TArray<HandJointInfo> Right = Hands->GetRightJointInfos();
for (EHandJointType J : HandJointTypeHelper::GetIndexSequence())
{
    const HandJointInfo& Info = Right[(int32)J];   // enum value doubles as array index
    UE_LOG(LogTemp, Log, TEXT("%s @ %s"),
        *HandJointTypeHelper::ToString(J), *Info.Position.ToString());
}
```

</Example>

</ApiBody>

### ToString

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

```cpp
static FString ToString(EHandJointType handJointType);
```

Header-inline. Returns the joint's name as a string (e.g. `"ThumbTip"`), or `"Unknown"` for unmapped values. Handy for logging / UI.

<Returns type="FString">the joint name, or `"Unknown"`</Returns>

</ApiBody>

## See also

- [`IHandsAdapter`](/docs/sdk-api/unreal-api/hands-boundary-anchors#ihandsadapter) — produces the `TArray<HandJointInfo>` per hand that these helpers consume
- [Hands, Boundary & Anchors](/docs/sdk-api/unreal-api/hands-boundary-anchors) — the area overview, units convention, and adapter factories
- [`USkeletonConsumer`](/docs/sdk-api/unreal-api/classes/skeletonconsumer) — the main entry point that fuses head/wrist/finger poses onto characters
- [Class index](/docs/sdk-api/unreal-api/classes) — all Unreal SDK types
